C   55

write.c

Guest on 5th May 2022 10:55:11 PM

  1. /* write - write to a logged in user    Authors: N. Andrew and F. van Kempen */
  2.  
  3. /*
  4.  * Usage:       write [-c] [-v] user [tty]
  5.  *                      -c Read & write one character at a time (cbreak mode)
  6.  *                      -v Verbose
  7.  *
  8.  * Version:     1.6
  9.  *
  10.  * NOTES:       Write requires 1.4a (or higher) libraries,
  11.  *              for getopt(), strchr().
  12.  *
  13.  * Authors:     Nick Andrew  (nick@nswitgould.oz)  - Public Domain
  14.  *              Fred van Kempen (minixug!waltje@kyber.uucp)
  15.  */
  16.  
  17. #include <sys/types.h>
  18. #include <fcntl.h>
  19. #include <pwd.h>
  20. #include <termios.h>
  21. #include <signal.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <unistd.h>
  25. #include <utmp.h>
  26. #include <time.h>
  27. #include <stdio.h>
  28. #include <paths.h>
  29.  
  30. #if 0
  31. static char *Version = "@(#) WRITE 1.6 (10/24/92)";
  32. #endif
  33.  
  34. int otty;                       /* file desc of callee's terminal */
  35. short int cbreak = 0;           /* are we in CBREAK (-c) mode? */
  36. short int verbose = 0;          /* are we in VERBOSE (-v) mode? */
  37. short int writing = 0;          /* is there a connection? */
  38. char *user = NULL;      /* callee's user name */
  39. char *tty = NULL;       /* callee's terminal if given */
  40. char *ourtty = NULL;    /* our terminal name */
  41. struct termios ttyold, ttynew;  /* our tty controlling structs */
  42.  
  43. extern int optind;
  44.  
  45. int main(int argc, char **argv);
  46. char *finduser(void);
  47. void settty(char *utty);
  48. void sayhello(void);
  49. void escape(char *cmd);
  50. void writetty(void);
  51. void usage(void);
  52. void intr(int dummy);
  53.  
  54. char *finduser()
  55. {
  56. /* Search the UTMP database for the user we want. */
  57.  
  58.   static char utmptty[16];
  59.   struct utmp utmp;
  60.   struct passwd *userptr;
  61.   int utmpfd;
  62.  
  63.   ourtty = ttyname(0);
  64.   if (ourtty == NULL) ourtty = "/dev/console";
  65.  
  66.   if (user == NULL) exit(-1);
  67.   if ((userptr = getpwnam(user)) == NULL) {
  68.         fprintf(stderr, "No such user: %s\n", user);
  69.         return(NULL);
  70.   }
  71.   if (verbose) fprintf(stderr, "Trying to write to %s\n",
  72.                 userptr->pw_gecos);
  73.  
  74.   if ((utmpfd = open(_PATH_UTMP, O_RDONLY)) < 0) {
  75.         fprintf(stderr, "Cannot open utmp file\n");
  76.         return(NULL);
  77.   }
  78.   utmptty[0] = '\0';
  79.  
  80.   /* We want to find if 'user' is logged on, and return in utmptty[]
  81.    * 'user' `s terminal, and if 'user' is logged onto the tty the
  82.    * caller specified, return that tty name. */
  83.   while (read(utmpfd, (char *) &utmp, sizeof(utmp)) == sizeof(utmp)) {
  84.         /* is this the user we are looking for? */
  85.         if (strncmp(utmp.ut_name, user, sizeof(utmp.ut_name))) continue;
  86.  
  87.         strcpy(utmptty, utmp.ut_line);
  88.         /* is he on the terminal we want to write to? */
  89.         if (tty == NULL || !strcmp(utmptty, tty)) {
  90.                 break;
  91.         }
  92.   }
  93.  
  94.   if (utmptty[0] == '\0') {
  95.         fprintf(stderr, "%s is not logged on\n", user);
  96.         return( NULL);
  97.   }
  98.   if (tty != NULL && strcmp(utmptty, tty)) {
  99.         fprintf(stderr, "%s is logged onto %s, not %s\n", user, utmptty, tty);
  100.         return( NULL);
  101.   }
  102.   close(utmpfd);
  103.  
  104.   if (verbose) fprintf(stderr, "Writing to %s on %s\n", user, utmptty);
  105.   return(utmptty);
  106. }
  107.  
  108.  
  109. void settty(utty)
  110. char *utty;                     /* name of terminal found in utmp */
  111. {
  112. /* Open other person's terminal and setup our own terminal. */
  113.  
  114.   char buff[48];
  115.  
  116.   sprintf(buff, "/dev/%s", utty);
  117.   if ((otty = open(buff, O_WRONLY)) < 0) {
  118.         fprintf(stderr, "Cannot open %s to write to %s\n", utty, user);
  119.         fprintf(stderr, "It may have write permission turned off\n");
  120.         exit(-1);
  121.   }
  122.   tcgetattr(0, &ttyold);
  123.   tcgetattr(0, &ttynew);
  124.   ttynew.c_lflag &= ~(ICANON|ECHO);
  125.   signal(SIGINT, intr);
  126.   if (cbreak) tcsetattr(0, TCSANOW, &ttynew);
  127. }
  128.  
  129.  
  130. void sayhello()
  131. {
  132.   struct passwd *pw;
  133.   char buff[128];
  134.   time_t now;
  135.   char *sp;
  136.  
  137.   time(&now);
  138.  
  139.   pw = getpwuid(getuid());
  140.   if (pw == NULL) {
  141.         fprintf(stderr, "unknown user\n");
  142.         exit(-1);
  143.   }
  144.   if ((sp = strrchr(ourtty, '/')) != NULL)
  145.         ++sp;
  146.   else
  147.         sp = ourtty;
  148.  
  149.   sprintf(buff, "\nMessage from %s (%s) %-24.24s...\n",
  150.         pw->pw_name, sp, ctime(&now));
  151.  
  152.   write(otty, buff, strlen(buff));
  153.   printf("\007\007");
  154.   fflush(stdout);
  155. }
  156.  
  157.  
  158. void escape(cmd)
  159. char *cmd;
  160. {
  161. /* Shell escape. */
  162.  
  163.   register char *x;
  164.  
  165.   write(1, "!\n", 2);
  166.   for (x = cmd; *x; ++x)
  167.         if (*x == '\n') *x = '\0';
  168.  
  169.   system(cmd);
  170.   write(1, "!\n", 2);
  171. }
  172.  
  173.  
  174. void writetty()
  175. {
  176. /* The write loop. */
  177.  
  178.   char line[80];
  179.   int n, cb_esc;
  180.  
  181.   writing = 1;
  182.   cb_esc = 0;
  183.  
  184.   while ((n = read(0, line, 79)) > 0) {
  185.         if (line[0] == '\004') break;   /* EOT */
  186.  
  187.         if (cbreak && line[0] == '\n') cb_esc = 1;
  188.  
  189.         if (cbreak) write(1, line, n);
  190.  
  191.         if (line[0] == '!') {
  192.                 if (cbreak && cb_esc) {
  193.                         cb_esc = 0;
  194.                         tcsetattr(0, TCSANOW, &ttyold);
  195.                         read(0, line, 79);
  196.                         escape(line);
  197.                         tcsetattr(0, TCSANOW, &ttynew);
  198.                 } else if (cbreak)
  199.                         write(otty, line, n);
  200.                 else
  201.                         escape(&line[1]);
  202.                 continue;
  203.         }
  204.         write(otty, line, n);
  205.   }
  206.   write(1, "\nEOT\n", 5);
  207.   write(otty, "\nEOT\n", 5);
  208. }
  209.  
  210.  
  211. void usage()
  212. {
  213.   fprintf(stderr, "usage: write [-c] [-v] user [tty]\n");
  214.   fprintf(stderr, "\t-c : cbreak mode\n\t-v : verbose\n");
  215.   exit(-1);
  216. }
  217.  
  218.  
  219. int main(argc, argv)
  220. int argc;
  221. char *argv[];
  222. {
  223.   register int c;
  224.   char *sp;
  225.  
  226.   setbuf(stdout, (char *) NULL);
  227.  
  228.   /* Parse options. */
  229.   while ((c = getopt(argc, argv, "cv")) != EOF) switch (c) {
  230.                 case 'c':       cbreak = 1;     break;
  231.                 case 'v':       verbose = 1;    break;
  232.             default:
  233.                 usage();
  234.         }
  235.  
  236.   /* Parse user and tty arguments */
  237.   if (optind < argc) {
  238.         user = argv[optind++];
  239.  
  240.         /* WTMP usernames are 1-8 chars */
  241.         if (strlen(user) > 8) *(user + 8) = '\0';
  242.  
  243.         if (optind < argc) {
  244.                 tty = argv[optind++];
  245.                 if (optind < argc) usage();
  246.         }
  247.   } else
  248.         usage();
  249.  
  250.   sp = finduser();              /* find which tty to write onto */
  251.   if (sp != NULL) {     /* did we find one? */
  252.         settty(sp);             /* setup our terminal */
  253.         sayhello();             /* print the initial message */
  254.         writetty();             /* the write loop */
  255.         tcsetattr(0, TCSANOW, &ttyold);
  256.         exit(0);
  257.   }
  258.   return(-1);
  259. }
  260.  
  261. void intr(dummy)
  262. int dummy;                      /* to satisfy the prototype */
  263. {
  264. /* The interrupt key has been hit. exit cleanly. */
  265.  
  266.   signal(SIGINT, SIG_IGN);
  267.   fprintf(stderr, "\nInterrupt. Exiting write\n");
  268.   tcsetattr(0, TCSANOW, &ttyold);
  269.   if (writing) write(otty, "\nEOT\n", 5);
  270.   exit(0);
  271. }

Raw Paste


Login or Register to edit or fork this paste. It's free.