ftp.nice.ch/pub/next/unix/admin/msend.1.0.N.bs.tar.gz#/msend/write.c

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.