home *** CD-ROM | disk | FTP | other *** search
- /* 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"
- #ifdef M_SYS
- #include <unistd.h>
- #endif
- #if defined(_AIX) && defined(USE_LOCKF)
- #include <sys/lockf.h>
- #endif
-
- 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[Bogus? %s]\r\n",si->msg);
- else
- #endif
- if (isatty(fileno(f)))
- fprintf(f,"\r\n[%s]\r\n",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) {
- #ifndef USE_LOCKF
- flock(fileno(f),LOCK_EX);
- #else
- lockf(fileno(f), F_TLOCK, 0);
- #endif
- fprintf(f,"[%s]\n",si->msg);
- #ifndef USE_LOCKF
- flock(fileno(f),LOCK_UN);
- #else
- lockf(fileno(f), F_ULOCK, 0);
- #endif
- fclose(f);
- }
-
- if (getuid() == ROOTUID)
- seteuid(DAEMONUID);
-
- return(RE_OK);
- }
-
- void broadcast(si)
- struct simsg *si;
- { char s[80];
- struct utmp *u;
-
- sprintf(s,"Broadcast message %s",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));
- }
-