|
|
1.1 ! root 1: /* ! 2: * Rec'd from Lauren Weinstein, 7-16-84. ! 3: * Write to another user ! 4: * on the system. ! 5: * This is setuid in order to ! 6: * use execute permission on the ! 7: * terminal to allow/disallow writes. ! 8: * ! 9: * Compile -s -n -i ! 10: */ ! 11: ! 12: #include <stdio.h> ! 13: #include <utmp.h> ! 14: #include <signal.h> ! 15: #include <sys/stat.h> ! 16: #include <sgtty.h> ! 17: ! 18: #define FALSE 0 ! 19: #define TRUE 1 ! 20: ! 21: #define NSYSC 150 /* Maximum system call line */ ! 22: FILE *tf; ! 23: struct stat sb; ! 24: struct sgttyb sgttyb, sgttys; /* for user tty modes */ ! 25: struct sgttyb sgttyd; /* for dest tty modes */ ! 26: struct tchars tchars; /* for determining EOF char */ ! 27: char sighup, sigquit, sigint; /* signal change flags */ ! 28: int eofmark; /* EOF marker */ ! 29: char dtty[40] = "/dev/"; ! 30: int conopen; /* TRUE if connection open */ ! 31: int status; /* exit status */ ! 32: int dcrtmode; /* non-zero for dest tty crt mode */ ! 33: int ucrtmode; /* non-zero for user tty crt mode */ ! 34: int istty; /* TRUE if input is a tty */ ! 35: int quit(); ! 36: char *getutmp(); ! 37: char *getlogin(); ! 38: char *ttyname(); ! 39: char crtwarn[] = ! 40: "Warning: One or both ttys is not a screen-oriented device.\n\ ! 41: Backspacing/character erase will not function properly...\n"; ! 42: ! 43: main(argc, argv) ! 44: char **argv; ! 45: { ! 46: char *totty, *touname; ! 47: char *fromtty, *fromuname; ! 48: char crtmode = 0; /* TRUE if both ttys are crt's */ ! 49: register int c; ! 50: register int nlf = 1; ! 51: ! 52: if (argc == 3) ! 53: totty = argv[2]; ! 54: else { ! 55: if (argc != 2) ! 56: usage(); ! 57: totty = NULL; ! 58: } ! 59: touname = argv[1]; ! 60: ! 61: gtty(0, &sgttyb); /* get tty modes into buffer */ ! 62: if (sgttyb.sg_flags & CRT) /* crt mode on user tty? */ ! 63: ucrtmode++; /* yes */ ! 64: gtty(0, &sgttys); /* save copy of original modes */ ! 65: ! 66: fromuname = getlogin(); ! 67: totty = getutmp(totty, touname); ! 68: strcat(dtty, totty); /* build full ttyname */ ! 69: ! 70: if ((fromtty = ttyname(fileno(stderr))) != NULL) { ! 71: stat(fromtty, &sb); ! 72: if ((sb.st_mode & S_IEXEC) == 0) ! 73: fprintf(stderr, "Warning: no reply possible\n"); ! 74: fromtty += 5; /* Skip over `/dev/' */ ! 75: } ! 76: if (signal(SIGINT, SIG_IGN) != SIG_IGN) ! 77: { signal(SIGINT, &quit); /* catch ints */ ! 78: sigint++; /* flag we're catching ints */ ! 79: } ! 80: if (signal(SIGHUP, SIG_IGN) != SIG_IGN) ! 81: { signal(SIGHUP, &quit); /* catch hangups */ ! 82: sighup++; /* flag */ ! 83: } ! 84: if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) ! 85: { signal(SIGQUIT, &quit); /* catch quits */ ! 86: sigquit++; ! 87: } ! 88: ioctl(0, TIOCGETC, &tchars); /* get char settings */ ! 89: setup(touname, dtty); ! 90: ! 91: if (isatty(0)) /* input a tty? */ ! 92: { istty = TRUE; /* yes */ ! 93: eofmark = tchars.t_eofc; /* set EOF marker */ ! 94: } ! 95: else ! 96: eofmark = EOF; /* set EOF marker */ ! 97: ! 98: if (!(crtmode = dcrtmode&ucrtmode)) /* check for both crt's */ ! 99: if (!ucrtmode && istty) /* input not crt and not tty? */ ! 100: fprintf(stderr, crtwarn); /* yes, warn user */ ! 101: ! 102: conopen = TRUE; /* flag connection open */ ! 103: sgttyb.sg_flags |= CBREAK; /* want cbreak mode */ ! 104: stty(0, &sgttyb); /* set new mode (no flush) */ ! 105: ! 106: /* ! 107: * Turn off setuid privileges. ! 108: */ ! 109: setuid(getuid()); ! 110: fprintf(tf, "\r\n\7Message from %s (%s) ...\r\n", fromuname, fromtty); ! 111: printf("\r\nUser %s has been notified ...\r\n", touname); ! 112: while ((c = getchar()) != eofmark) { /* continue until end of file */ ! 113: if (nlf && c=='!') { ! 114: callsys(); ! 115: continue; ! 116: } ! 117: if (c == '\n') ! 118: nlf = 1; ! 119: else ! 120: nlf = 0; ! 121: putc(c, tf); ! 122: if (c == '\b' && crtmode) /* backspace and crt's? */ ! 123: { putc(' ', stdout); /* erase local char */ ! 124: putc('\b', stdout); ! 125: putc(' ', tf); /* erase dest char */ ! 126: putc('\b', tf); ! 127: } ! 128: } ! 129: quit(); ! 130: } ! 131: ! 132: callsys() ! 133: { ! 134: char sysline[NSYSC]; ! 135: register char *cp; ! 136: register int c; ! 137: ! 138: cp = sysline; ! 139: while ((c = getchar()) != '\n') ! 140: if (cp < &sysline[NSYSC-1]) ! 141: *cp++ = c; ! 142: *cp = '\0'; ! 143: signal(SIGINT, SIG_IGN); /* ignore ints */ ! 144: signal(SIGHUP, SIG_IGN); /* hups */ ! 145: signal(SIGQUIT, SIG_IGN); /* and quits */ ! 146: stty(0, &sgttys); /* restore original modes */ ! 147: system(sysline); /* fork child command */ ! 148: stty(0, &sgttyb); /* back to special modes */ ! 149: if (sigint) /* restore int status */ ! 150: signal(SIGINT, &quit); ! 151: if (sighup) /* hup */ ! 152: signal(SIGHUP, &quit); ! 153: if (sigquit) /* quit */ ! 154: signal(SIGQUIT, &quit); ! 155: printf("!\n"); ! 156: } ! 157: ! 158: /* ! 159: * Check whether or not writes are ! 160: * allowed to this terminal. ! 161: */ ! 162: setup(u, t) ! 163: char *u, *t; ! 164: { ! 165: register char abortf = 0; ! 166: register char c; ! 167: ! 168: if ((tf = fopen(t, "w")) == NULL) ! 169: fprintf(stderr, "write: cannot open %s\n", t); ! 170: if (gtty(fileno(tf), &sgttyd) >= 0) /* stat dest tty */ ! 171: if (sgttyd.sg_flags & CRT) /* crt mode on dest tty? */ ! 172: dcrtmode++; ! 173: if (fstat(fileno(tf), &sb) < 0) { ! 174: fprintf(stderr, "write: can't write to %s\n", u); ! 175: quiterr(); ! 176: } ! 177: if ((sb.st_mode&S_IEXEC) == 0) { ! 178: if (getuid() == 0) /* is our real uid su? */ ! 179: { fprintf(stderr, ! 180: "User \"%s\" is denying messages. Override? ", u); ! 181: if ((c = getchar()) != 'y') ! 182: abortf++; /* flag abort */ ! 183: while (c != EOF && c != '\n') /* flush remaining input */ ! 184: c = getchar(); ! 185: if ( ! abortf) /* override requested? */ ! 186: return; /* allow write */ ! 187: else ! 188: quit(); ! 189: } ! 190: fprintf(stderr, "write: no permission to write to %s\n", u); ! 191: quiterr(); ! 192: } ! 193: } ! 194: ! 195: /* ! 196: * Return the tty for the specified ! 197: * username and possibly tty ! 198: * from the utmp file. ! 199: */ ! 200: char * ! 201: getutmp(t, u) ! 202: char *t, *u; ! 203: { ! 204: register FILE *fp; ! 205: static struct utmp ut; ! 206: ! 207: ! 208: if ((fp = fopen("/etc/utmp", "r")) == NULL) { ! 209: fprintf(stderr, "write: /etc/utmp not accessible\n"); ! 210: quiterr(); ! 211: } ! 212: ! 213: while (fread(&ut, sizeof ut, 1, fp) == 1) { ! 214: if (strncmp(ut.ut_name, u, DIRSIZ) != 0) ! 215: continue; ! 216: if (t != NULL) ! 217: if (strncmp(ut.ut_line, t, 8) == 0) { ! 218: fclose(fp); ! 219: return (t); ! 220: } else ! 221: continue; ! 222: ut.ut_line[8] == '\0'; ! 223: fclose(fp); ! 224: return (ut.ut_line); ! 225: } ! 226: if (t == NULL) ! 227: fprintf(stderr, "write: %s not logged in\n", u); ! 228: else ! 229: fprintf(stderr, "write: %s not logged onto %s\n", u, t); ! 230: quiterr(); ! 231: } ! 232: ! 233: quit() ! 234: { ! 235: if (conopen) /* if connection open */ ! 236: { stty(0, &sgttys); /* normal mode */ ! 237: fprintf(tf, "EOT\n"); ! 238: fclose(tf); /* close connection */ ! 239: } ! 240: exit(status); ! 241: } ! 242: ! 243: quiterr() ! 244: { ! 245: status = 1; /* exit with error status */ ! 246: quit(); ! 247: } ! 248: ! 249: usage() ! 250: { ! 251: fprintf(stderr, "Usage: write username [ttyname]\n"); ! 252: quit(1); ! 253: } ! 254: ! 255:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.