|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1989 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Jef Poskanzer and Craig Leres of the Lawrence Berkeley Laboratory. ! 7: * ! 8: * Redistribution and use in source and binary forms are permitted provided ! 9: * that: (1) source distributions retain this entire copyright notice and ! 10: * comment, and (2) distributions including binaries display the following ! 11: * acknowledgement: ``This product includes software developed by the ! 12: * University of California, Berkeley and its contributors'' in the ! 13: * documentation or other materials provided with the distribution and in ! 14: * all advertising materials mentioning features or use of this software. ! 15: * Neither the name of the University nor the names of its contributors may ! 16: * be used to endorse or promote products derived from this software without ! 17: * specific prior written permission. ! 18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 19: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 20: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 21: */ ! 22: ! 23: #ifndef lint ! 24: char copyright[] = ! 25: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ ! 26: All rights reserved.\n"; ! 27: #endif /* not lint */ ! 28: ! 29: #ifndef lint ! 30: static char sccsid[] = "@(#)write.c 4.22 (Berkeley) 6/1/90"; ! 31: #endif /* not lint */ ! 32: ! 33: #include <sys/param.h> ! 34: #include <sys/signal.h> ! 35: #include <sys/stat.h> ! 36: #include <sys/file.h> ! 37: #include <sys/time.h> ! 38: #include <utmp.h> ! 39: #include <ctype.h> ! 40: #include <pwd.h> ! 41: #include <stdio.h> ! 42: #include <string.h> ! 43: ! 44: extern int errno; ! 45: ! 46: main(argc, argv) ! 47: int argc; ! 48: char **argv; ! 49: { ! 50: register char *cp; ! 51: time_t atime; ! 52: uid_t myuid; ! 53: int msgsok, myttyfd; ! 54: char tty[MAXPATHLEN], *mytty, *ttyname(); ! 55: void done(); ! 56: ! 57: /* check that sender has write enabled */ ! 58: if (isatty(fileno(stdin))) ! 59: myttyfd = fileno(stdin); ! 60: else if (isatty(fileno(stdout))) ! 61: myttyfd = fileno(stdout); ! 62: else if (isatty(fileno(stderr))) ! 63: myttyfd = fileno(stderr); ! 64: else { ! 65: (void)fprintf(stderr, "write: can't find your tty\n"); ! 66: exit(1); ! 67: } ! 68: if (!(mytty = ttyname(myttyfd))) { ! 69: (void)fprintf(stderr, "write: can't find your tty's name\n"); ! 70: exit(1); ! 71: } ! 72: if (cp = rindex(mytty, '/')) ! 73: mytty = cp + 1; ! 74: if (term_chk(mytty, &msgsok, &atime, 1)) ! 75: exit(1); ! 76: if (!msgsok) { ! 77: (void)fprintf(stderr, ! 78: "write: you have write permission turned off.\n"); ! 79: exit(1); ! 80: } ! 81: ! 82: myuid = getuid(); ! 83: ! 84: /* check args */ ! 85: switch (argc) { ! 86: case 2: ! 87: search_utmp(argv[1], tty, mytty, myuid); ! 88: do_write(tty, mytty, myuid); ! 89: break; ! 90: case 3: ! 91: if (!strncmp(argv[2], "/dev/", 5)) ! 92: argv[2] += 5; ! 93: if (utmp_chk(argv[1], argv[2])) { ! 94: (void)fprintf(stderr, ! 95: "write: %s is not logged in on %s.\n", ! 96: argv[1], argv[2]); ! 97: exit(1); ! 98: } ! 99: if (term_chk(argv[2], &msgsok, &atime, 1)) ! 100: exit(1); ! 101: if (myuid && !msgsok) { ! 102: (void)fprintf(stderr, ! 103: "write: %s has messages disabled on %s\n", ! 104: argv[1], argv[2]); ! 105: exit(1); ! 106: } ! 107: do_write(argv[2], mytty, myuid); ! 108: break; ! 109: default: ! 110: (void)fprintf(stderr, "usage: write user [tty]\n"); ! 111: exit(1); ! 112: } ! 113: done(); ! 114: /* NOTREACHED */ ! 115: } ! 116: ! 117: /* ! 118: * utmp_chk - checks that the given user is actually logged in on ! 119: * the given tty ! 120: */ ! 121: utmp_chk(user, tty) ! 122: char *user, *tty; ! 123: { ! 124: struct utmp u; ! 125: int ufd; ! 126: ! 127: if ((ufd = open(_PATH_UTMP, O_RDONLY)) < 0) ! 128: return(0); /* ignore error, shouldn't happen anyway */ ! 129: ! 130: while (read(ufd, (char *) &u, sizeof(u)) == sizeof(u)) ! 131: if (strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0 && ! 132: strncmp(tty, u.ut_line, sizeof(u.ut_line)) == 0) { ! 133: (void)close(ufd); ! 134: return(0); ! 135: } ! 136: ! 137: (void)close(ufd); ! 138: return(1); ! 139: } ! 140: ! 141: /* ! 142: * search_utmp - search utmp for the "best" terminal to write to ! 143: * ! 144: * Ignores terminals with messages disabled, and of the rest, returns ! 145: * the one with the most recent access time. Returns as value the number ! 146: * of the user's terminals with messages enabled, or -1 if the user is ! 147: * not logged in at all. ! 148: * ! 149: * Special case for writing to yourself - ignore the terminal you're ! 150: * writing from, unless that's the only terminal with messages enabled. ! 151: */ ! 152: search_utmp(user, tty, mytty, myuid) ! 153: char *user, *tty, *mytty; ! 154: uid_t myuid; ! 155: { ! 156: struct utmp u; ! 157: time_t bestatime, atime; ! 158: int ufd, nloggedttys, nttys, msgsok, user_is_me; ! 159: char atty[UT_LINESIZE + 1]; ! 160: ! 161: if ((ufd = open(_PATH_UTMP, O_RDONLY)) < 0) { ! 162: perror("utmp"); ! 163: exit(1); ! 164: } ! 165: ! 166: nloggedttys = nttys = 0; ! 167: bestatime = 0; ! 168: user_is_me = 0; ! 169: while (read(ufd, (char *) &u, sizeof(u)) == sizeof(u)) ! 170: if (strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0) { ! 171: ++nloggedttys; ! 172: (void)strncpy(atty, u.ut_line, UT_LINESIZE); ! 173: atty[UT_LINESIZE] = '\0'; ! 174: if (term_chk(atty, &msgsok, &atime, 0)) ! 175: continue; /* bad term? skip */ ! 176: if (myuid && !msgsok) ! 177: continue; /* skip ttys with msgs off */ ! 178: if (strcmp(atty, mytty) == 0) { ! 179: user_is_me = 1; ! 180: continue; /* don't write to yourself */ ! 181: } ! 182: ++nttys; ! 183: if (atime > bestatime) { ! 184: bestatime = atime; ! 185: (void)strcpy(tty, atty); ! 186: } ! 187: } ! 188: ! 189: (void)close(ufd); ! 190: if (nloggedttys == 0) { ! 191: (void)fprintf(stderr, "write: %s is not logged in\n", user); ! 192: exit(1); ! 193: } ! 194: if (nttys == 0) { ! 195: if (user_is_me) { /* ok, so write to yourself! */ ! 196: (void)strcpy(tty, mytty); ! 197: return; ! 198: } ! 199: (void)fprintf(stderr, ! 200: "write: %s has messages disabled\n", user); ! 201: exit(1); ! 202: } else if (nttys > 1) { ! 203: (void)fprintf(stderr, ! 204: "write: %s is logged in more than once; writing to %s\n", ! 205: user, tty); ! 206: } ! 207: } ! 208: ! 209: /* ! 210: * term_chk - check that a terminal exists, and get the message bit ! 211: * and the access time ! 212: */ ! 213: term_chk(tty, msgsokP, atimeP, showerror) ! 214: char *tty; ! 215: int *msgsokP, showerror; ! 216: time_t *atimeP; ! 217: { ! 218: struct stat s; ! 219: char path[MAXPATHLEN]; ! 220: ! 221: (void)sprintf(path, "/dev/%s", tty); ! 222: if (stat(path, &s) < 0) { ! 223: if (showerror) ! 224: (void)fprintf(stderr, ! 225: "write: %s: %s\n", path, strerror(errno)); ! 226: return(1); ! 227: } ! 228: *msgsokP = (s.st_mode & (S_IWRITE >> 3)) != 0; /* group write bit */ ! 229: *atimeP = s.st_atime; ! 230: return(0); ! 231: } ! 232: ! 233: /* ! 234: * do_write - actually make the connection ! 235: */ ! 236: do_write(tty, mytty, myuid) ! 237: char *tty, *mytty; ! 238: uid_t myuid; ! 239: { ! 240: register char *login, *nows; ! 241: register struct passwd *pwd; ! 242: time_t now, time(); ! 243: char *getlogin(), path[MAXPATHLEN], host[MAXHOSTNAMELEN], line[512]; ! 244: void done(); ! 245: ! 246: /* Determine our login name before the we reopen() stdout */ ! 247: if ((login = getlogin()) == NULL) ! 248: if (pwd = getpwuid(myuid)) ! 249: login = pwd->pw_name; ! 250: else ! 251: login = "???"; ! 252: ! 253: (void)sprintf(path, "/dev/%s", tty); ! 254: if ((freopen(path, "w", stdout)) == NULL) { ! 255: (void)fprintf(stderr, "write: %s: %s\n", path, strerror(errno)); ! 256: exit(1); ! 257: } ! 258: ! 259: (void)signal(SIGINT, done); ! 260: (void)signal(SIGHUP, done); ! 261: ! 262: /* print greeting */ ! 263: if (gethostname(host, sizeof(host)) < 0) ! 264: (void)strcpy(host, "???"); ! 265: now = time((time_t *)NULL); ! 266: nows = ctime(&now); ! 267: nows[16] = '\0'; ! 268: (void)printf("\r\n\007\007\007Message from %s@%s on %s at %s ...\r\n", ! 269: login, host, mytty, nows + 11); ! 270: ! 271: while (fgets(line, sizeof(line), stdin) != NULL) ! 272: wr_fputs(line); ! 273: } ! 274: ! 275: /* ! 276: * done - cleanup and exit ! 277: */ ! 278: void ! 279: done() ! 280: { ! 281: (void)printf("EOF\r\n"); ! 282: exit(0); ! 283: } ! 284: ! 285: /* ! 286: * wr_fputs - like fputs(), but makes control characters visible and ! 287: * turns \n into \r\n ! 288: */ ! 289: wr_fputs(s) ! 290: register char *s; ! 291: { ! 292: register char c; ! 293: ! 294: #define PUTC(c) if (putchar(c) == EOF) goto err; ! 295: ! 296: for (; *s != '\0'; ++s) { ! 297: c = toascii(*s); ! 298: if (c == '\n') { ! 299: PUTC('\r'); ! 300: PUTC('\n'); ! 301: } else if (!isprint(c) && !isspace(c) && c != '\007') { ! 302: PUTC('^'); ! 303: PUTC(c^0x40); /* DEL to ?, others to alpha */ ! 304: } else ! 305: PUTC(c); ! 306: } ! 307: return; ! 308: ! 309: err: (void)fprintf(stderr, "write: %s\n", strerror(errno)); ! 310: exit(1); ! 311: #undef PUTC ! 312: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.