|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.