This is write.c in view mode; [Download] [Up]
/* write.c: * * these routines are used for writing to users * * (c) Copyright 1988, 1989, 1990 Jim Frost. All Rights Reserved. Please see * the accompanying file "Copyright" for more information. */ #include "Copyright" #include "config.h" #include "msend.h" extern int errno; #ifdef SECURE_PORT extern short notsecure; #endif /* this writes to the tty specified in si and saves the message in spool */ static int ttywrite(si) struct simsg *si; { FILE *f; char fname[MAXFILENAME]; int uid; /* try to write to user's tty */ sprintf(fname,"/dev/%s",si->ttty); if ((f= fopen(fname,"w")) == NULL) if (errno == EACCES) return(RE_NOMSGS); else return(RE_SYSERR); #ifdef SECURE_PORT if (notsecure) fprintf(f,"\r\n\007[Bogus? %s]\r\n",si->msg); else #endif fprintf(f,"\r\n\007\007\007[%s]\r\n\007\007",si->msg); fclose(f); /* save the message in the spool for "huh" option */ if (getuid() == ROOTUID) { if ((uid= getid(si->taddr)) < 0) /* write to file as if we were user */ return(RE_NOUSER); seteuid(uid); } #ifdef SPOOLDIR sprintf(fname,"%s/%s",SPOOLDIR,si->taddr); #else sprintf(fname,"%s/.msendmsgs",gethome(si->taddr)); #endif if ((f= fopen(fname,"a")) != NULL) { flock(fileno(f),LOCK_EX); fprintf(f,"[%s]\n",si->msg); flock(fileno(f),LOCK_UN); fclose(f); } if (getuid() == ROOTUID) seteuid(DAEMONUID); return(RE_OK); } void broadcast(si) struct simsg *si; { char s[80]; struct utmp *u; sprintf(s,"\007\007\007Broadcast message %s\007\007",si->msg); /* log it! */ error(s); /* loop for every utmp entry and try to write. ignore any * errors returned by ttywrite. we have to implement the * entire write command here or else we get an infinite * loop on the first utmp entry. */ while (u= getutent()) { #ifdef SYSVUTMP if (u->ut_type != USER_PROCESS) continue; #endif if (strcmp(u->ut_name,"")) { sprintf(si->ttty,u->ut_line); sprintf(si->taddr,u->ut_name); ttywrite(si); } } endutent(); } /* single user */ int writeuser(si) struct simsg *si; { struct utmp *u; /* utmp entry */ struct stat stb; struct rimsg ri; char *home; char ttyname[sizeof("/dev/")+MAXTTY+1]; char token[MAXTOKEN+1]; char fname[MAXFILENAME+1]; char line[MAXLINE+1]; FILE *f; time_t ltime; int ttystat; int notfound; int allttys; int forward; int fwderr; int ttyerr; int uid; /* send to particular tty */ if (si->mode & SM_TTY) { /* look up user of that tty. */ ttystat= RE_SYSERR; while (u= getutent()) if (!strcmp(u->ut_line,si->ttty)) { strcpy(si->taddr,u->ut_name); strcpy(si->ttty,u->ut_line); ttystat= ttywrite(si); break; } endutent(); if (ttystat == RE_SYSERR) errno= ENODEV; /* error message for user */ return(ttystat); } /* open user's options file and see if they want some special * propagation */ allttys= 0; forward= 0; fwderr= RE_OK; if ((home= gethome(si->taddr)) == NULL) return(RE_NOUSER); if (getuid() == ROOTUID) { if ((uid= getid(si->taddr)) < 0) return(RE_NOUSER); seteuid(uid); } sprintf(fname,"%s/.msendrc",home); if ((f= fopen(fname,"r")) != NULL) { while (fgets(line,MAXLINE,f) != NULL) { sscanf(line,"%s",token); /* tty options */ if (!strcmp(token,"allttys")) allttys= 1; else if (!strcmp(token,"write-to-tty")) { sscanf(line,"%*s %s",si->ttty); ttywrite(si); forward= 1; /* same idea as forwarding */ } /* forwarding options. note that we return the first error that * we get when forwarding so the user has some idea that something * went wrong. compound errors will be lost. we ignore obvious * host loops. */ else if (!strcmp(token,"forward-to-user")) { sscanf(line,"%*s %s",si->taddr); if ((striphost(si->taddr,si->tohost)) && (!fwdloop(si->tohost))) { si->fwdcount++; forward= 1; sendmessage(si,&ri,si->mode); if (fwderr == RE_OK) fwderr= ri.h.errno; } } else if (!strcmp(token,"forward-to-tty")) { sscanf(line,"%*s %s %s",si->ttty,si->taddr); if ((striphost(si->taddr,si->tohost)) && (!fwdloop(si->tohost))) { forward= 1; si->fwdcount++; sendmessage(si,&ri,si->mode); if (fwderr == RE_OK) fwderr= ri.h.errno; } } else if (!strcmp(token,"write-and-forward-to-user")) { sscanf(line,"%*s %s",si->taddr); if ((striphost(si->taddr,si->tohost)) && (!fwdloop(si->tohost))) { si->fwdcount++; sendmessage(si,&ri,si->mode); if (fwderr == RE_OK) fwderr= ri.h.errno; } } } fclose(f); if (forward) return(fwderr); } if (getuid() == ROOTUID) seteuid(DAEMONUID); /* send to least idle user or all writable ttys, depending on mode. */ ltime= (time_t)0; notfound= 1; ttyerr= RE_OK; while (u= getutent()) { if (!strcmp(u->ut_name,si->taddr)) { /* match user */ sprintf(ttyname,"/dev/%s",u->ut_line); if (stat(ttyname,&stb) != -1) { notfound= 0; if (stb.st_mode & 022) /* see if we have permission */ if (allttys) { /* write to every possible tty */ strcpy(si->ttty,u->ut_line); if (ttyerr != RE_OK) ttywrite(si); else ttyerr= ttywrite(si); } else { /* look for least idle terminal */ if (!ltime) { ltime= stb.st_mtime; strcpy(si->ttty,u->ut_line); } else if (stb.st_mtime > ltime) { /* less idle */ ltime= stb.st_mtime; strcpy(si->ttty,u->ut_line); } } } } } endutent(); if (allttys) return(ttyerr); if (notfound) return(RE_NOTTHERE); else if (!ltime) return(RE_NOMSGS); return(ttywrite(si)); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.