122608Sserge #ifndef lint 2*22703Slepreau static char *sccsid = "@(#)write.c 4.10 06/07/85"; 322608Sserge #endif 41169Sbill /* 51169Sbill * write to another user 61169Sbill */ 71169Sbill 81169Sbill #include <stdio.h> 922608Sserge #include <ctype.h> 101169Sbill #include <sys/types.h> 111169Sbill #include <sys/stat.h> 121169Sbill #include <signal.h> 131169Sbill #include <utmp.h> 1413599Swnj #include <sys/time.h> 151169Sbill 166202Sroot #define NMAX sizeof(ubuf.ut_name) 176202Sroot #define LMAX sizeof(ubuf.ut_line) 181169Sbill 191169Sbill char *strcat(); 201169Sbill char *strcpy(); 211169Sbill struct utmp ubuf; 221169Sbill int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0}; 2322608Sserge char me[NMAX + 1] = "???"; 241169Sbill char *him; 251169Sbill char *mytty; 261169Sbill char histty[32]; 271169Sbill char *histtya; 281169Sbill char *ttyname(); 291169Sbill char *rindex(); 301169Sbill int logcnt; 311169Sbill int eof(); 321169Sbill int timout(); 331169Sbill FILE *tf; 341169Sbill char *getenv(); 351169Sbill 361169Sbill main(argc, argv) 376202Sroot int argc; 386202Sroot char *argv[]; 391169Sbill { 401169Sbill struct stat stbuf; 411169Sbill register i; 421169Sbill register FILE *uf; 431169Sbill int c1, c2; 446202Sroot long clock = time(0); 45*22703Slepreau int suser = getuid() == 0; 461169Sbill struct tm *localtime(); 471169Sbill struct tm *localclock = localtime( &clock ); 481169Sbill 496202Sroot if (argc < 2) { 5022608Sserge fprintf(stderr, "Usage: write user [ttyname]\n"); 511169Sbill exit(1); 521169Sbill } 531169Sbill him = argv[1]; 546202Sroot if (argc > 2) 551169Sbill histtya = argv[2]; 561169Sbill if ((uf = fopen("/etc/utmp", "r")) == NULL) { 5722608Sserge perror("write: Can't open /etc/utmp"); 581169Sbill goto cont; 591169Sbill } 601169Sbill mytty = ttyname(2); 611169Sbill if (mytty == NULL) { 6222608Sserge fprintf(stderr, "write: Can't find your tty\n"); 631169Sbill exit(1); 641169Sbill } 656202Sroot if (stat(mytty, &stbuf) < 0) { 6622608Sserge perror("write: Can't stat your tty"); 676202Sroot exit(1); 681881Serics } 69*22703Slepreau if (!suser && (stbuf.st_mode&02) == 0) { 7022608Sserge fprintf(stderr, 7122608Sserge "write: You have write permission turned off\n"); 726202Sroot exit(1); 731881Serics } 741169Sbill mytty = rindex(mytty, '/') + 1; 751169Sbill if (histtya) { 761169Sbill strcpy(histty, "/dev/"); 771169Sbill strcat(histty, histtya); 781169Sbill } 791169Sbill while (fread((char *)&ubuf, sizeof(ubuf), 1, uf) == 1) { 801799Seric if (ubuf.ut_name[0] == '\0') 811799Seric continue; 821169Sbill if (strcmp(ubuf.ut_line, mytty)==0) { 836202Sroot for (i=0; i<NMAX; i++) { 841169Sbill c1 = ubuf.ut_name[i]; 856202Sroot if (c1 == ' ') 861169Sbill c1 = 0; 871169Sbill me[i] = c1; 886202Sroot if (c1 == 0) 891169Sbill break; 901169Sbill } 911169Sbill } 9222608Sserge if (him[0] == '-' && him[1] == 0) 9322608Sserge goto nomat; 946202Sroot for (i=0; i<NMAX; i++) { 951169Sbill c1 = him[i]; 961169Sbill c2 = ubuf.ut_name[i]; 976202Sroot if (c1 == 0) 986202Sroot if (c2 == 0 || c2 == ' ') 991169Sbill break; 1006202Sroot if (c1 != c2) 1011169Sbill goto nomat; 1021169Sbill } 1031169Sbill logcnt++; 1041169Sbill if (histty[0]==0) { 1051169Sbill strcpy(histty, "/dev/"); 1061169Sbill strcat(histty, ubuf.ut_line); 1071169Sbill } 1081169Sbill nomat: 1091169Sbill ; 1101169Sbill } 1111169Sbill cont: 1121169Sbill if (logcnt==0 && histty[0]=='\0') { 11322608Sserge fprintf(stderr, "write: %s not logged in\n", him); 1141169Sbill exit(1); 1151169Sbill } 11622608Sserge if (uf != NULL) 11722608Sserge fclose(uf); 1181169Sbill if (histtya==0 && logcnt > 1) { 11922608Sserge fprintf(stderr, 12022608Sserge "write: %s logged in more than once ... writing to %s\n", 12122608Sserge him, histty+5); 1221169Sbill } 1236202Sroot if (histty[0] == 0) { 1241169Sbill printf(him); 1256202Sroot if (logcnt) 1261169Sbill printf(" not on that tty\n"); else 1271169Sbill printf(" not logged in\n"); 1281169Sbill exit(1); 1291169Sbill } 1301169Sbill if (access(histty, 0) < 0) { 13122608Sserge fprintf(stderr, "write: No such tty\n"); 1321169Sbill exit(1); 1331169Sbill } 1341169Sbill signal(SIGALRM, timout); 1351169Sbill alarm(5); 1361169Sbill if ((tf = fopen(histty, "w")) == NULL) 1371169Sbill goto perm; 1381169Sbill alarm(0); 1391169Sbill if (fstat(fileno(tf), &stbuf) < 0) 1401169Sbill goto perm; 141*22703Slepreau if (!suser && (stbuf.st_mode&02) == 0) 1421169Sbill goto perm; 1431169Sbill sigs(eof); 1446202Sroot { char hostname[32]; 1456202Sroot gethostname(hostname, sizeof (hostname)); 14622608Sserge fprintf(tf, 14722608Sserge "\r\nMessage from %s@%s on %s at %d:%02d ...\r\n\007\007\007", 14822608Sserge me, hostname, mytty, localclock->tm_hour, localclock->tm_min); 14922608Sserge fflush(tf); 1506202Sroot } 1516202Sroot for (;;) { 15222608Sserge char buf[BUFSIZ]; 15322608Sserge register char *bp; 15422608Sserge i = read(0, buf, sizeof buf); 1556202Sroot if (i <= 0) 1561169Sbill eof(); 1576202Sroot if (buf[0] == '!') { 1581169Sbill buf[i] = 0; 1591169Sbill ex(buf); 1601169Sbill continue; 1611169Sbill } 16222608Sserge for (bp = buf; --i >= 0; bp++) { 16322608Sserge if (*bp == '\n') 16422608Sserge putc('\r', tf); 16522608Sserge 16622608Sserge if (!isascii(*bp)) { 16722608Sserge putc('M', tf); 16822608Sserge putc('-', tf); 16922608Sserge *bp = toascii(*bp); 17022608Sserge } 17122608Sserge 17222608Sserge if (isprint(*bp) || 17322608Sserge *bp == ' ' || *bp == '\t' || *bp == '\n') { 17422608Sserge putc(*bp, tf); 17522608Sserge } else { 17622608Sserge putc('^', tf); 17722608Sserge putc(*bp ^ 0100, tf); 17822608Sserge } 17922608Sserge 18022608Sserge if (*bp == '\n') 18122608Sserge fflush(tf); 18222608Sserge 18322608Sserge if (ferror(tf) || feof(tf)) { 18422608Sserge printf("\n\007Write failed (%s logged out?)\n", 18522608Sserge him); 18622608Sserge exit(1); 18722608Sserge } 1887401Skre } 1891169Sbill } 1901169Sbill perm: 19122608Sserge fprintf(stderr, "write: Permission denied\n"); 1921169Sbill exit(1); 1931169Sbill } 1941169Sbill 1951169Sbill timout() 1961169Sbill { 1971169Sbill 19822608Sserge fprintf(stderr, "write: Timeout opening their tty\n"); 1991169Sbill exit(1); 2001169Sbill } 2011169Sbill 2021169Sbill eof() 2031169Sbill { 2041169Sbill 2051169Sbill fprintf(tf, "EOF\r\n"); 2061169Sbill exit(0); 2071169Sbill } 2081169Sbill 2091169Sbill ex(bp) 2106202Sroot char *bp; 2111169Sbill { 2121169Sbill register i; 2131169Sbill 2141169Sbill sigs(SIG_IGN); 2151169Sbill i = fork(); 2166202Sroot if (i < 0) { 2171169Sbill printf("Try again\n"); 2181169Sbill goto out; 2191169Sbill } 2206202Sroot if (i == 0) { 2211169Sbill sigs((int (*)())0); 2226202Sroot execl(getenv("SHELL") ? 2236202Sroot getenv("SHELL") : "/bin/sh", "sh", "-c", bp+1, 0); 2241169Sbill exit(0); 2251169Sbill } 2266202Sroot while (wait((int *)NULL) != i) 2271169Sbill ; 2281169Sbill printf("!\n"); 2291169Sbill out: 2301169Sbill sigs(eof); 2311169Sbill } 2321169Sbill 2331169Sbill sigs(sig) 2346202Sroot int (*sig)(); 2351169Sbill { 2361169Sbill register i; 2371169Sbill 2386202Sroot for (i=0; signum[i]; i++) 2396202Sroot signal(signum[i], sig); 2401169Sbill } 241