Annotation of coherent/d/bin/msg.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Rec'd from Lauren Weinstein, 7-16-84.
                      3:  * Send a one-line message to
                      4:  * another user or a number of users.
                      5:  * This is setuid in order to
                      6:  * use execute permission on the
                      7:  * terminal to allow/disallow msgs.
                      8:  *
                      9:  * The super user may use the "-s" flag to suppress the user id
                     10:  * prefix on messages, which also suppresses any error messages,
                     11:  * and forces an exit code of 0 unless an error condition occurs.
                     12:  * This is mainly for use by other programs (e.g. "rmail").
                     13:  */
                     14: 
                     15: #include <stdio.h>
                     16: #include <utmp.h>
                     17: #include <sys/stat.h>
                     18: #include <signal.h>
                     19: 
                     20: #define        MAXMSG  256             /* Longest message allowable */
                     21: #define        NUSER   100             /* Maximum number of users to send to */
                     22: #define ALARMT  10             /* Message send timeout in seconds */
                     23: 
                     24: char   msgbuf[MAXMSG];
                     25: struct users {
                     26:        char    *u_name;
                     27:        int     u_flag;
                     28: }      users[NUSER];
                     29: 
                     30: int    wtimeout;   /* non-zero for timeout on tty write */
                     31: int     suppress;   /* non-zero to suppress id headers, etc. */
                     32: 
                     33: char   usemsg[] = "\
                     34: Usage: msg user\n\
                     35:        msg user ... message\n\
                     36: ";
                     37: 
                     38: char   *getlogin();
                     39: char   *ttyname();
                     40: int    catch();
                     41: 
                     42: main(argc, argv)
                     43: char *argv[];
                     44: {
                     45:        char *fromuname;
                     46:        register int i;
                     47:        register struct users *ulp = users;
                     48: 
                     49: 
                     50:        /* are we the superuser and was the "-s" flag given? */
                     51:        if (!geteuid() && argc > 1 && !strcmp(argv[1], "-s"))
                     52:        {  suppress++;  /* set "suppress user id" prefix flag */
                     53:           close(2);    /* close error output */
                     54:           open("/dev/null", 1);  /* reopen fd 2 on /dev/null */ 
                     55:           argc--;      /* adjust args */       
                     56:           argv++;
                     57:        }
                     58: 
                     59:        if (argc < 2)
                     60:                usage();
                     61:        if ((fromuname = getlogin()) == NULL)
                     62:                fromuname = "daemon";
                     63:        if (argc==2 || strcmp(argv[argc-1], "-")==0)
                     64:                fgets(msgbuf, MAXMSG, stdin);
                     65:        else {
                     66:                strcpy(msgbuf, argv[argc-1]);
                     67:                strcat(msgbuf, "\r\n");
                     68:        }
                     69:        if (argc == 2)
                     70:                (ulp++)->u_name = argv[1];
                     71:        else
                     72:                for (i=1; i<argc-1; i++)
                     73:                        (ulp++)->u_name = argv[i];
                     74:        exit(msg(suppress ? 0 : fromuname));
                     75: }
                     76: 
                     77: /*
                     78:  * Find out terminal names for the
                     79:  * given user-list and complain about
                     80:  * those not logged in.
                     81:  */
                     82: msg(f)
                     83: char *f;
                     84: {
                     85:        register struct users *up;
                     86:        register FILE *fp;
                     87:        register int st = 0;
                     88:        static struct utmp ut;
                     89: 
                     90:        if ((fp = fopen("/etc/utmp", "r")) == NULL) {
                     91:                fprintf(stderr, "msg: /etc/utmp not accessible\n");
                     92:                exit(2);
                     93:        }
                     94:        while (fread(&ut, sizeof ut, 1, fp) == 1) {
                     95:                if (ut.ut_name[0] == '\0')
                     96:                        continue;
                     97:                for (up = users; up->u_name != NULL; up++)
                     98:                        if (strncmp(ut.ut_name, up->u_name, DIRSIZ) == 0)
                     99:                                break;
                    100:                if (up->u_name == NULL)
                    101:                        continue;
                    102:                send(f, &ut);
                    103:                up->u_flag = 1;
                    104:        }
                    105:        for (up = users; up->u_name != NULL; up++)
                    106:                if (up->u_flag == 0) {
                    107:                        fprintf(stderr, "%s: not logged in\n", up->u_name);
                    108:                        if (!suppress)
                    109:                           st = 1;  /* indicate user not logged in */
                    110:                }
                    111:        return(st);
                    112: }
                    113: 
                    114: /*
                    115:  * Send the message.  Return non-zero if
                    116:  * it does not work or is not allowed.
                    117:  */
                    118: send(f, up)
                    119: char *f;
                    120: register struct utmp *up;
                    121: {
                    122:        FILE *tf;
                    123:        register struct stat sb;
                    124:        char tty[40], c;
                    125:        register char abortf = 0;
                    126: 
                    127:        sprintf(tty, "/dev/%.*s", sizeof up->ut_line, up->ut_line);
                    128:        if ((tf = fopen(tty, "w")) == NULL) {
                    129:                fprintf(stderr, "msg: cannot open %.*s\n",
                    130:                    sizeof up->ut_line, up->ut_line);
                    131:                return;
                    132:        }
                    133:        if (fstat(fileno(tf), &sb) < 0) 
                    134:        {       fprintf(stderr, "msg: can't send to %.*s\n",
                    135:                    sizeof up->ut_name, up->ut_name);
                    136:                fclose(tf);
                    137:                return;
                    138:        }
                    139:        if ((sb.st_mode&S_IEXEC) == 0) {
                    140:                if (!getuid())  /* is our real uid su? */
                    141:                {  fprintf(stderr, 
                    142:                      "User \"%.*s\" is denying messages.  Override? ",
                    143:                      sizeof up->ut_name, up->ut_name);
                    144:                   if ((c = getchar()) != 'y')
                    145:                      abortf++;  /* flag abort */  
                    146:                   while (c != EOF && c != '\n')  /* flush remaining input */
                    147:                      c = getchar();
                    148:                   if (abortf)  /* don't want override? */
                    149:                   {  fclose(tf);  
                    150:                      return;
                    151:                   }
                    152:                }
                    153:                else
                    154:                {  fprintf(stderr, "write: no permission to write to %.*s\n",
                    155:                      sizeof up->ut_name, up->ut_name);
                    156:                   fclose(tf);
                    157:                   return;      
                    158:                }
                    159:        }       
                    160:        signal(SIGALRM, &catch);  /* catch alarms */
                    161:        alarm(ALARMT);            /* set timeout */
                    162:        if (f == NULL)
                    163:                fprintf(tf, "\r\n\007%s", msgbuf);  /* send the msg */
                    164:        else
                    165:                fprintf(tf, "\r\n\007%s: %s", f, msgbuf);
                    166:        alarm(0);                 /* turn off timeout */
                    167:        if (wtimeout)             /* timeout on write? */
                    168:        {  wtimeout = 0;          /* clear timeout flag */
                    169:           fprintf(stderr, "msg: can't send to %.*s\n",
                    170:              sizeof up->ut_name, up->ut_name);
                    171:        }
                    172:         fclose(tf);
                    173: }
                    174: 
                    175: /* for alarm timeout */
                    176: catch()
                    177: {
                    178:        wtimeout++;  /* set write timeout flag */
                    179: }
                    180: 
                    181: usage()
                    182: {
                    183:        fprintf(stderr, usemsg);
                    184:        exit(2);
                    185: }
                    186: 
                    187: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.