19289Ssam #ifndef lint 2*16808Sralph static char sccsid[] = "@(#)comsat.c 4.12 (Berkeley) 08/01/84"; 39289Ssam #endif 46394Sroot 59289Ssam #include <sys/types.h> 69289Ssam #include <sys/socket.h> 713549Ssam #include <sys/stat.h> 813549Ssam #include <sys/wait.h> 916587Ssam #include <sys/file.h> 109289Ssam 119289Ssam #include <netinet/in.h> 129289Ssam 131513Sroot #include <stdio.h> 141513Sroot #include <sgtty.h> 151513Sroot #include <utmp.h> 161513Sroot #include <signal.h> 176394Sroot #include <errno.h> 189289Ssam #include <netdb.h> 19*16808Sralph #include <syslog.h> 201513Sroot 211513Sroot /* 221513Sroot * comsat 231513Sroot */ 2412746Ssam int debug = 0; 2512746Ssam #define dprintf if (debug) printf 261513Sroot 271513Sroot #define MAXUTMP 100 /* down from init */ 281513Sroot 299878Ssam struct sockaddr_in sin = { AF_INET }; 306394Sroot extern errno; 316394Sroot 3216587Ssam char hostname[32]; 331513Sroot struct utmp utmp[100]; 341513Sroot int nutmp; 351513Sroot int uf; 361513Sroot unsigned utmpmtime; /* last modification time for utmp */ 371513Sroot int onalrm(); 3816587Ssam int reapchildren(); 3916367Skarels long lastmsgtime; 401513Sroot 4116367Skarels #define MAXIDLE 120 421513Sroot #define NAMLEN (sizeof (uts[0].ut_name) + 1) 431513Sroot 441513Sroot main(argc, argv) 4516367Skarels int argc; 4616367Skarels char *argv[]; 471513Sroot { 4816367Skarels register int cc; 491513Sroot char buf[BUFSIZ]; 5016367Skarels char msgbuf[100]; 5116367Skarels struct sockaddr_in from; 5216367Skarels int fromlen; 531513Sroot 5416367Skarels /* verify proper invocation */ 5516367Skarels fromlen = sizeof (from); 5616367Skarels if (getsockname(0, &from, &fromlen) < 0) { 5716367Skarels fprintf(stderr, "%s: ", argv[0]); 5816367Skarels perror("getsockname"); 5916367Skarels _exit(1); 6016367Skarels } 6116367Skarels chdir("/usr/spool/mail"); 6216367Skarels if ((uf = open("/etc/utmp",0)) < 0) { 63*16808Sralph openlog("comsat", 0, 0); 64*16808Sralph syslog(LOG_ERR, "/etc/utmp: %m"); 6516367Skarels (void) recv(0, msgbuf, sizeof (msgbuf) - 1, 0); 669289Ssam exit(1); 679289Ssam } 6816367Skarels lastmsgtime = time(0); 6916587Ssam gethostname(hostname, sizeof (hostname)); 701513Sroot onalrm(); 7113022Ssam signal(SIGALRM, onalrm); 7213022Ssam signal(SIGTTOU, SIG_IGN); 7316587Ssam signal(SIGCHLD, reapchildren); 746394Sroot for (;;) { 7516367Skarels cc = recv(0, msgbuf, sizeof (msgbuf) - 1, 0); 766394Sroot if (cc <= 0) { 776394Sroot if (errno != EINTR) 786394Sroot sleep(1); 796394Sroot errno = 0; 806394Sroot continue; 811513Sroot } 8216367Skarels sigblock(1<<SIGALRM); 836394Sroot msgbuf[cc] = 0; 8416367Skarels lastmsgtime = time(0); 856394Sroot mailfor(msgbuf); 8616367Skarels sigsetmask(0); 871513Sroot } 881513Sroot } 891513Sroot 9016587Ssam reapchildren() 9116587Ssam { 9216587Ssam 9316587Ssam while (wait3((struct wait *)0, WNOHANG, (struct rusage *)0) > 0) 9416587Ssam ; 9516587Ssam } 9616587Ssam 971513Sroot onalrm() 981513Sroot { 991513Sroot struct stat statbf; 1001513Sroot struct utmp *utp; 1011513Sroot 10216367Skarels if (time(0) - lastmsgtime >= MAXIDLE) 103*16808Sralph exit(0); 1041513Sroot dprintf("alarm\n"); 1051513Sroot alarm(15); 106*16808Sralph fstat(uf, &statbf); 1071513Sroot if (statbf.st_mtime > utmpmtime) { 1081513Sroot dprintf(" changed\n"); 1091513Sroot utmpmtime = statbf.st_mtime; 1101513Sroot lseek(uf, 0, 0); 1111513Sroot nutmp = read(uf,utmp,sizeof(utmp))/sizeof(struct utmp); 1121513Sroot } else 1131513Sroot dprintf(" ok\n"); 1141513Sroot } 1151513Sroot 1161513Sroot mailfor(name) 1171513Sroot char *name; 1181513Sroot { 1191513Sroot register struct utmp *utp = &utmp[nutmp]; 1201513Sroot register char *cp; 1211513Sroot char *rindex(); 1221513Sroot int offset; 1231513Sroot 1241513Sroot dprintf("mailfor %s\n", name); 1251513Sroot cp = name; 1261513Sroot while (*cp && *cp != '@') 1271513Sroot cp++; 1281513Sroot if (*cp == 0) { 1291513Sroot dprintf("bad format\n"); 1301513Sroot return; 1311513Sroot } 1321513Sroot *cp = 0; 1331513Sroot offset = atoi(cp+1); 1341513Sroot while (--utp >= utmp) 1351513Sroot if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name))) 13616587Ssam notify(utp, offset); 1371513Sroot } 1381513Sroot 139*16808Sralph char *cr; 1401513Sroot 1411513Sroot notify(utp, offset) 1421513Sroot register struct utmp *utp; 1431513Sroot { 144*16808Sralph int fd, flags, n, err, msglen; 1451513Sroot struct sgttyb gttybuf; 146*16808Sralph char tty[20], msgbuf[BUFSIZ]; 147*16808Sralph char name[sizeof (utmp[0].ut_name) + 1]; 1481513Sroot struct stat stb; 1491513Sroot 1501513Sroot strcpy(tty, "/dev/"); 1511513Sroot strncat(tty, utp->ut_line, sizeof(utp->ut_line)); 1521513Sroot dprintf("notify %s on %s\n", utp->ut_name, tty); 1531513Sroot if (stat(tty, &stb) == 0 && (stb.st_mode & 0100) == 0) { 1541513Sroot dprintf("wrong mode\n"); 1551513Sroot return; 1561513Sroot } 157*16808Sralph if ((fd = open(tty, O_WRONLY|O_NDELAY)) < 0) { 158*16808Sralph dprintf("%s: open failed\n", tty); 15916587Ssam return; 1601513Sroot } 161*16808Sralph if ((flags = fcntl(fd, F_GETFL, 0)) == -1) { 162*16808Sralph dprintf("fcntl(F_GETFL) failed %d\n", errno); 163*16808Sralph return; 164*16808Sralph } 165*16808Sralph ioctl(fd, TIOCGETP, >tybuf); 1661513Sroot cr = (gttybuf.sg_flags & CRMOD) ? "" : "\r"; 1671513Sroot strncpy(name, utp->ut_name, sizeof (utp->ut_name)); 16816587Ssam name[sizeof (name) - 1] = '\0'; 169*16808Sralph sprintf(msgbuf, "%s\n\007New mail for %s@%s\007 has arrived:%s\n", 17012746Ssam cr, name, hostname, cr); 171*16808Sralph jkfprintf(msgbuf+strlen(msgbuf), name, offset); 172*16808Sralph if (fcntl(fd, F_SETFL, flags | FNDELAY) == -1) 173*16808Sralph goto oldway; 174*16808Sralph msglen = strlen(msgbuf); 175*16808Sralph n = write(fd, msgbuf, msglen); 176*16808Sralph err = errno; 177*16808Sralph (void) fcntl(fd, F_SETFL, flags); 178*16808Sralph (void) close(fd); 179*16808Sralph if (n == msglen) 180*16808Sralph return; 181*16808Sralph if (err != EWOULDBLOCK) { 182*16808Sralph dprintf("write failed %d\n", errno); 183*16808Sralph return; 184*16808Sralph } 185*16808Sralph oldway: 186*16808Sralph if (fork()) { 187*16808Sralph (void) close(fd); 188*16808Sralph return; 189*16808Sralph } 190*16808Sralph signal(SIGALRM, SIG_DFL); 191*16808Sralph alarm(30); 192*16808Sralph (void) write(fd, msgbuf, msglen); 19316587Ssam exit(0); 1941513Sroot } 1951513Sroot 196*16808Sralph jkfprintf(mp, name, offset) 197*16808Sralph register char *mp; 1981513Sroot { 1991513Sroot register FILE *fi; 2001513Sroot register int linecnt, charcnt; 20112746Ssam char line[BUFSIZ]; 20213783Ssam int inheader; 2031513Sroot 204*16808Sralph dprintf("HERE %s's mail starting at %d\n", name, offset); 205*16808Sralph 206*16808Sralph if ((fi = fopen(name, "r")) == NULL) { 2071513Sroot dprintf("Cant read the mail\n"); 2081513Sroot return; 2091513Sroot } 21016587Ssam fseek(fi, offset, L_SET); 21112746Ssam /* 21212746Ssam * Print the first 7 lines or 560 characters of the new mail 21312746Ssam * (whichever comes first). Skip header crap other than 21413783Ssam * From, Subject, To, and Date. 21512746Ssam */ 2161513Sroot linecnt = 7; 2171513Sroot charcnt = 560; 21813783Ssam inheader = 1; 21912746Ssam while (fgets(line, sizeof (line), fi) != NULL) { 22012746Ssam register char *cp; 22112746Ssam char *index(); 22213783Ssam int cnt; 2231513Sroot 22412746Ssam if (linecnt <= 0 || charcnt <= 0) { 225*16808Sralph sprintf(mp, "...more...%s\n", cr); 226*16808Sralph mp += strlen(mp); 22713022Ssam return; 2281513Sroot } 22913783Ssam if (strncmp(line, "From ", 5) == 0) 23013783Ssam continue; 23113783Ssam if (inheader && (line[0] == ' ' || line[0] == '\t')) 23213783Ssam continue; 23312746Ssam cp = index(line, ':'); 23413783Ssam if (cp == 0 || (index(line, ' ') && index(line, ' ') < cp)) 23513783Ssam inheader = 0; 23613783Ssam else 23713783Ssam cnt = cp - line; 23813783Ssam if (inheader && 23913783Ssam strncmp(line, "Date", cnt) && 24013783Ssam strncmp(line, "From", cnt) && 24113783Ssam strncmp(line, "Subject", cnt) && 24213783Ssam strncmp(line, "To", cnt)) 24312746Ssam continue; 24412746Ssam cp = index(line, '\n'); 24512746Ssam if (cp) 24612746Ssam *cp = '\0'; 247*16808Sralph sprintf(mp, "%s%s\n", line, cr); 248*16808Sralph mp += strlen(mp); 24912746Ssam linecnt--, charcnt -= strlen(line); 2501513Sroot } 251*16808Sralph sprintf(mp, "----%s\n", cr); 252*16808Sralph mp += strlen(mp); 2531513Sroot } 254