1*1572Sbill static char *sccsid = "@(#)comsat.c 4.2 (Berkeley) 10/20/80"; 21513Sroot #include <stdio.h> 31513Sroot #include <sys/mx.h> 41513Sroot #include <sgtty.h> 51513Sroot #include <utmp.h> 61513Sroot #include <sys/types.h> 71513Sroot #include <stat.h> 81513Sroot #include <wait.h> 91513Sroot #include <signal.h> 101513Sroot 111513Sroot /* 121513Sroot * comsat 131513Sroot */ 141513Sroot #define dprintf if (0) printf 151513Sroot int xd; 161513Sroot 171513Sroot struct ctp { 181513Sroot short ctrl; 191513Sroot short ctrlarg; 201513Sroot struct sgttyb ctrlv; 211513Sroot } ctp; 221513Sroot 231513Sroot #define MAXUTMP 100 /* down from init */ 241513Sroot 251513Sroot struct utmp utmp[100]; 261513Sroot int nutmp; 271513Sroot int uf; 281513Sroot unsigned utmpmtime; /* last modification time for utmp */ 291513Sroot int onalrm(); 301513Sroot 311513Sroot #define NAMLEN (sizeof (uts[0].ut_name) + 1) 321513Sroot 331513Sroot main(argc, argv) 341513Sroot char **argv; 351513Sroot { 361513Sroot register cc; 371513Sroot char buf[BUFSIZ]; 381513Sroot 391513Sroot if (fork()) 401513Sroot exit(); 411513Sroot chdir("/usr/spool/mail"); 421513Sroot if((uf = open("/etc/utmp",0)) < 0) 431513Sroot perror("/etc/utmp"), exit(1); 441513Sroot while (fork()) 451513Sroot wait(0); 46*1572Sbill sleep(10); 471513Sroot onalrm(); 481513Sroot sigset(SIGALRM, onalrm); 491513Sroot sigignore(SIGTTOU); 501513Sroot unlink("/dev/mail"); 511513Sroot xd = mpx("/dev/mail", 0666); 521513Sroot if (xd < 0) { 531513Sroot close(2); 541513Sroot open("/dev/console", 1); 551513Sroot perror("/dev/mail"); 561513Sroot exit(1); 571513Sroot } 581513Sroot while((cc=read(xd, buf, BUFSIZ)) >= 0) { 591513Sroot dprintf("0: got %d bytes\n", cc); 601513Sroot unpack(buf, cc); 611513Sroot } 62*1572Sbill _exit(1); 631513Sroot } 641513Sroot 651513Sroot #define skip(rp, c) ((struct rh *)(((char *)rp)+c)) 661513Sroot 671513Sroot unpack(rp, cc) 681513Sroot register struct rh *rp; 691513Sroot { 701513Sroot register struct rh *end; 711513Sroot int i; 721513Sroot 731513Sroot i = 0; 741513Sroot end = skip(rp, cc); 751513Sroot while (rp < end) { 761513Sroot dprintf("%d: ", ++i); 771513Sroot if (rp->count==0) { 781513Sroot dprintf("%d byte control message\n", rp->ccount); 791513Sroot control(rp->index, rp+1, rp->ccount); 801513Sroot } else { 811513Sroot dprintf("%*.*s\n", rp->count, rp->count, rp+1); 821513Sroot sighold(SIGALRM); 831513Sroot mailfor(rp+1); 841513Sroot sigrelse(SIGALRM); 851513Sroot } 861513Sroot rp->count += rp->ccount; 871513Sroot if (rp->count & 1) 881513Sroot rp->count++; 891513Sroot rp = skip(rp, rp->count); 901513Sroot rp++; 911513Sroot } 921513Sroot } 931513Sroot 941513Sroot control(x, cb, cc) 951513Sroot register char *cb; 961513Sroot { 971513Sroot register char *end; 981513Sroot int cmd; 991513Sroot short *sp; 1001513Sroot struct wh or; 1011513Sroot 1021513Sroot end = cb + cc; 1031513Sroot cmd = *cb++; 1041513Sroot sp = (short *)cb+1; 1051513Sroot switch (cmd) { 1061513Sroot 1071513Sroot case M_WATCH: 1081513Sroot dprintf("attach %x, uid %d\n", x, *sp); 1091513Sroot attach(x, xd); 1101513Sroot break; 1111513Sroot 1121513Sroot case M_CLOSE: 1131513Sroot sp = (short *)cb; 1141513Sroot dprintf("detach %x, uid %d\n", x, *sp); 1151513Sroot detach(x, xd); 1161513Sroot break; 1171513Sroot 1181513Sroot case M_IOCTL: 1191513Sroot dprintf("ioctl %x\n", x); 1201513Sroot or.index = x; 1211513Sroot or.count = 0; 1221513Sroot or.ccount = sizeof ctp; 1231513Sroot or.data = (char *) &ctp.ctrlarg; 1241513Sroot ctp.ctrlarg = M_IOANS; 1251513Sroot write(xd, &or, sizeof or); 1261513Sroot break; 1271513Sroot 1281513Sroot default: 1291513Sroot dprintf("unknown command %d\n", cmd); 1301513Sroot return; 1311513Sroot } 1321513Sroot } 1331513Sroot 1341513Sroot onalrm() 1351513Sroot { 1361513Sroot struct stat statbf; 1371513Sroot struct utmp *utp; 1381513Sroot 1391513Sroot dprintf("alarm\n"); 1401513Sroot alarm(15); 1411513Sroot fstat(uf,&statbf); 1421513Sroot if (statbf.st_mtime > utmpmtime) { 1431513Sroot dprintf(" changed\n"); 1441513Sroot utmpmtime = statbf.st_mtime; 1451513Sroot lseek(uf, 0, 0); 1461513Sroot nutmp = read(uf,utmp,sizeof(utmp))/sizeof(struct utmp); 1471513Sroot } else 1481513Sroot dprintf(" ok\n"); 1491513Sroot } 1501513Sroot 1511513Sroot mailfor(name) 1521513Sroot char *name; 1531513Sroot { 1541513Sroot register struct utmp *utp = &utmp[nutmp]; 1551513Sroot register char *cp; 1561513Sroot char *rindex(); 1571513Sroot int offset; 1581513Sroot 1591513Sroot dprintf("mailfor %s\n", name); 1601513Sroot cp = name; 1611513Sroot while (*cp && *cp != '@') 1621513Sroot cp++; 1631513Sroot if (*cp == 0) { 1641513Sroot dprintf("bad format\n"); 1651513Sroot return; 1661513Sroot } 1671513Sroot *cp = 0; 1681513Sroot offset = atoi(cp+1); 1691513Sroot while (--utp >= utmp) 1701513Sroot if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name))) 1711513Sroot if (fork() == 0) { 1721513Sroot signal(SIGALRM, SIG_DFL); 1731513Sroot alarm(30); 1741513Sroot notify(utp, offset), exit(0); 1751513Sroot } else 1761513Sroot while (wait3(0, WNOHANG, 0) > 0) 1771513Sroot continue; 1781513Sroot } 1791513Sroot 1801513Sroot char *cr; 1811513Sroot 1821513Sroot notify(utp, offset) 1831513Sroot register struct utmp *utp; 1841513Sroot { 1851513Sroot FILE *tp; 1861513Sroot struct sgttyb gttybuf; 1871513Sroot char tty[20]; 1881513Sroot char name[sizeof (utmp[0].ut_name) + 1]; 1891513Sroot struct stat stb; 1901513Sroot 1911513Sroot strcpy(tty, "/dev/"); 1921513Sroot strncat(tty, utp->ut_line, sizeof(utp->ut_line)); 1931513Sroot dprintf("notify %s on %s\n", utp->ut_name, tty); 1941513Sroot if (stat(tty, &stb) == 0 && (stb.st_mode & 0100) == 0) { 1951513Sroot dprintf("wrong mode\n"); 1961513Sroot return; 1971513Sroot } 1981513Sroot if ((tp = fopen(tty,"w")) == 0) { 1991513Sroot dprintf("fopen failed\n"); 2001513Sroot return; 2011513Sroot } 2021513Sroot gtty(fileno(tp),>tybuf); 2031513Sroot cr = (gttybuf.sg_flags & CRMOD) ? "" : "\r"; 2041513Sroot strncpy(name, utp->ut_name, sizeof (utp->ut_name)); 2051513Sroot name[sizeof (name) - 1] = 0; 2061513Sroot fprintf(tp,"%s\n\007New mail for %s\007 has arrived:%s\n", 2071513Sroot cr, name, cr); 2081513Sroot fprintf(tp,"----%s\n", cr); 2091513Sroot jkfprintf(tp, name, offset); 2101513Sroot fclose(tp); 2111513Sroot } 2121513Sroot 2131513Sroot jkfprintf(tp, name, offset) 2141513Sroot register FILE *tp; 2151513Sroot { 2161513Sroot register FILE *fi; 2171513Sroot register int linecnt, charcnt; 2181513Sroot 2191513Sroot dprintf("HERE %s's mail starting at %d\n", 2201513Sroot name, offset); 2211513Sroot if ((fi = fopen(name,"r")) == NULL) { 2221513Sroot dprintf("Cant read the mail\n"); 2231513Sroot return; 2241513Sroot } 2251513Sroot fseek(fi, offset, 0); 2261513Sroot linecnt = 7; 2271513Sroot charcnt = 560; 2281513Sroot /* 2291513Sroot * print the first 7 lines or 560 characters of the new mail 2301513Sroot * (whichever comes first) 2311513Sroot */ 2321513Sroot for (;;) { 2331513Sroot register ch; 2341513Sroot 2351513Sroot if ((ch = getc(fi)) == EOF) { 2361513Sroot fprintf(tp,"----%s\n", cr); 2371513Sroot break; 2381513Sroot } 2391513Sroot if (ch == '\n') { 2401513Sroot fprintf(tp,"%s\n", cr); 2411513Sroot if (linecnt-- < 0) { 2421513Sroot fprintf(tp,"...more...%s\n", cr); 2431513Sroot break; 2441513Sroot } 2451513Sroot } else if(linecnt <= 0) { 2461513Sroot fprintf(tp,"...more...%s\n", cr); 2471513Sroot break; 2481513Sroot } else 2491513Sroot putc(ch, tp); 2501513Sroot if (charcnt-- == 0) { 2511513Sroot fprintf(tp, "%s\n", cr); 2521513Sroot break; 2531513Sroot } 2541513Sroot } 2551513Sroot } 256