122608Sserge #ifndef lint 2*37937Sbostic static char *sccsid = "@(#)write.c 4.15 05/11/89"; 322608Sserge #endif 41169Sbill /* 51169Sbill * write to another user 61169Sbill */ 71169Sbill 81169Sbill #include <sys/types.h> 91169Sbill #include <sys/stat.h> 10*37937Sbostic #include <sys/signal.h> 11*37937Sbostic #include <sys/time.h> 121169Sbill #include <utmp.h> 13*37937Sbostic #include <stdio.h> 14*37937Sbostic #include <ctype.h> 15*37937Sbostic #include <paths.h> 161169Sbill 176202Sroot #define NMAX sizeof(ubuf.ut_name) 186202Sroot #define LMAX sizeof(ubuf.ut_line) 191169Sbill 201169Sbill char *strcat(); 211169Sbill char *strcpy(); 221169Sbill struct utmp ubuf; 231169Sbill int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0}; 2422608Sserge char me[NMAX + 1] = "???"; 251169Sbill char *him; 261169Sbill char *mytty; 271169Sbill char histty[32]; 2826068Skarels char ttybuf[32]; 291169Sbill char *histtya; 301169Sbill char *ttyname(); 311169Sbill char *rindex(); 321169Sbill int logcnt; 331169Sbill int eof(); 341169Sbill int timout(); 351169Sbill FILE *tf; 361169Sbill char *getenv(); 371169Sbill 381169Sbill main(argc, argv) 396202Sroot int argc; 406202Sroot char *argv[]; 411169Sbill { 421169Sbill struct stat stbuf; 431169Sbill register i; 441169Sbill register FILE *uf; 451169Sbill int c1, c2; 466202Sroot long clock = time(0); 4722703Slepreau int suser = getuid() == 0; 4826068Skarels int nomesg = 0; 491169Sbill struct tm *localtime(); 501169Sbill struct tm *localclock = localtime( &clock ); 511169Sbill 526202Sroot if (argc < 2) { 5322608Sserge fprintf(stderr, "Usage: write user [ttyname]\n"); 541169Sbill exit(1); 551169Sbill } 561169Sbill him = argv[1]; 576202Sroot if (argc > 2) 581169Sbill histtya = argv[2]; 5937042Sbostic if ((uf = fopen(_PATH_UTMP, "r")) == NULL) { 6037042Sbostic fprintf(stderr, "write: can't read %s\n", _PATH_UTMP); 6126069Skarels if (histtya == 0) 6226069Skarels exit(10); 631169Sbill goto cont; 641169Sbill } 651169Sbill mytty = ttyname(2); 661169Sbill if (mytty == NULL) { 6722608Sserge fprintf(stderr, "write: Can't find your tty\n"); 681169Sbill exit(1); 691169Sbill } 706202Sroot if (stat(mytty, &stbuf) < 0) { 7122608Sserge perror("write: Can't stat your tty"); 726202Sroot exit(1); 731881Serics } 7426857Smckusick if ((stbuf.st_mode&020) == 0) { 7522608Sserge fprintf(stderr, 7622608Sserge "write: You have write permission turned off\n"); 7726068Skarels if (!suser) 7826068Skarels exit(1); 791881Serics } 801169Sbill mytty = rindex(mytty, '/') + 1; 811169Sbill if (histtya) { 8237042Sbostic strcpy(histty, _PATH_DEV); 831169Sbill strcat(histty, histtya); 841169Sbill } 851169Sbill while (fread((char *)&ubuf, sizeof(ubuf), 1, uf) == 1) { 861799Seric if (ubuf.ut_name[0] == '\0') 871799Seric continue; 881169Sbill if (strcmp(ubuf.ut_line, mytty)==0) { 896202Sroot for (i=0; i<NMAX; i++) { 901169Sbill c1 = ubuf.ut_name[i]; 916202Sroot if (c1 == ' ') 921169Sbill c1 = 0; 931169Sbill me[i] = c1; 946202Sroot if (c1 == 0) 951169Sbill break; 961169Sbill } 971169Sbill } 9822608Sserge if (him[0] == '-' && him[1] == 0) 9922608Sserge goto nomat; 1006202Sroot for (i=0; i<NMAX; i++) { 1011169Sbill c1 = him[i]; 1021169Sbill c2 = ubuf.ut_name[i]; 1036202Sroot if (c1 == 0) 1046202Sroot if (c2 == 0 || c2 == ' ') 1051169Sbill break; 1066202Sroot if (c1 != c2) 1071169Sbill goto nomat; 1081169Sbill } 10926068Skarels if (histtya && strncmp(histtya, ubuf.ut_line, 11026068Skarels sizeof(ubuf.ut_line))) 11126068Skarels continue; 1121169Sbill logcnt++; 11326068Skarels if (histty[0]==0 || nomesg && histtya == 0) { 11437042Sbostic strcpy(ttybuf, _PATH_DEV); 11526068Skarels strcat(ttybuf, ubuf.ut_line); 11626068Skarels if (histty[0]==0) 11726068Skarels strcpy(histty, ttybuf); 11826068Skarels if (access(ttybuf, 0) < 0 || stat(ttybuf, &stbuf) < 0 || 11926857Smckusick (stbuf.st_mode&020) == 0) 12026068Skarels nomesg++; 12126068Skarels else { 12226068Skarels strcpy(histty, ttybuf); 12326068Skarels nomesg = 0; 12426068Skarels } 1251169Sbill } 1261169Sbill nomat: 1271169Sbill ; 1281169Sbill } 12926069Skarels fclose(uf); 13026068Skarels if (logcnt==0) { 13126069Skarels fprintf(stderr, "write: %s not logged in%s\n", him, 13226069Skarels histtya ? " on that tty" : ""); 1331169Sbill exit(1); 1341169Sbill } 1351169Sbill if (histtya==0 && logcnt > 1) { 13622608Sserge fprintf(stderr, 13722608Sserge "write: %s logged in more than once ... writing to %s\n", 13822608Sserge him, histty+5); 1391169Sbill } 14026069Skarels cont: 1411169Sbill if (access(histty, 0) < 0) { 14222608Sserge fprintf(stderr, "write: No such tty\n"); 1431169Sbill exit(1); 1441169Sbill } 1451169Sbill signal(SIGALRM, timout); 1461169Sbill alarm(5); 14726068Skarels if ((tf = fopen(histty, "w")) == NULL) { 14826068Skarels fprintf(stderr, "write: Permission denied\n"); 14926068Skarels exit(1); 15026068Skarels } 1511169Sbill alarm(0); 1521169Sbill sigs(eof); 1536202Sroot { char hostname[32]; 1546202Sroot gethostname(hostname, sizeof (hostname)); 15522608Sserge fprintf(tf, 15622608Sserge "\r\nMessage from %s@%s on %s at %d:%02d ...\r\n\007\007\007", 15722608Sserge me, hostname, mytty, localclock->tm_hour, localclock->tm_min); 15822608Sserge fflush(tf); 1596202Sroot } 1606202Sroot for (;;) { 16122608Sserge char buf[BUFSIZ]; 16222608Sserge register char *bp; 16322608Sserge i = read(0, buf, sizeof buf); 1646202Sroot if (i <= 0) 1651169Sbill eof(); 1666202Sroot if (buf[0] == '!') { 1671169Sbill buf[i] = 0; 1681169Sbill ex(buf); 1691169Sbill continue; 1701169Sbill } 17122608Sserge for (bp = buf; --i >= 0; bp++) { 17222608Sserge if (*bp == '\n') 17322608Sserge putc('\r', tf); 17422608Sserge 17522608Sserge if (!isascii(*bp)) { 17622608Sserge putc('M', tf); 17722608Sserge putc('-', tf); 17822608Sserge *bp = toascii(*bp); 17922608Sserge } 18022608Sserge 18122608Sserge if (isprint(*bp) || 18222608Sserge *bp == ' ' || *bp == '\t' || *bp == '\n') { 18322608Sserge putc(*bp, tf); 18422608Sserge } else { 18522608Sserge putc('^', tf); 18622608Sserge putc(*bp ^ 0100, tf); 18722608Sserge } 18822608Sserge 18922608Sserge if (*bp == '\n') 19022608Sserge fflush(tf); 19122608Sserge 19222608Sserge if (ferror(tf) || feof(tf)) { 19322608Sserge printf("\n\007Write failed (%s logged out?)\n", 19422608Sserge him); 19522608Sserge exit(1); 19622608Sserge } 1977401Skre } 1981169Sbill } 1991169Sbill } 2001169Sbill 2011169Sbill timout() 2021169Sbill { 2031169Sbill 20422608Sserge fprintf(stderr, "write: Timeout opening their tty\n"); 2051169Sbill exit(1); 2061169Sbill } 2071169Sbill 2081169Sbill eof() 2091169Sbill { 2101169Sbill 2111169Sbill fprintf(tf, "EOF\r\n"); 2121169Sbill exit(0); 2131169Sbill } 2141169Sbill 2151169Sbill ex(bp) 2166202Sroot char *bp; 2171169Sbill { 2181169Sbill register i; 2191169Sbill 2201169Sbill sigs(SIG_IGN); 2211169Sbill i = fork(); 2226202Sroot if (i < 0) { 2231169Sbill printf("Try again\n"); 2241169Sbill goto out; 2251169Sbill } 2266202Sroot if (i == 0) { 22726857Smckusick fclose(tf); /* Close his terminal */ 22826857Smckusick setgid(getgid()); /* Give up effective group privs */ 2291169Sbill sigs((int (*)())0); 2306202Sroot execl(getenv("SHELL") ? 23137042Sbostic getenv("SHELL") : _PATH_BSHELL, "sh", "-c", bp+1, 0); 2321169Sbill exit(0); 2331169Sbill } 2346202Sroot while (wait((int *)NULL) != i) 2351169Sbill ; 2361169Sbill printf("!\n"); 2371169Sbill out: 2381169Sbill sigs(eof); 2391169Sbill } 2401169Sbill 2411169Sbill sigs(sig) 2426202Sroot int (*sig)(); 2431169Sbill { 2441169Sbill register i; 2451169Sbill 2466202Sroot for (i=0; signum[i]; i++) 2476202Sroot signal(signum[i], sig); 2481169Sbill } 249