19289Ssam #ifndef lint 2*13783Ssam static char *sccsid = "@(#)comsat.c 4.9 83/07/04"; 39289Ssam #endif 46394Sroot 59289Ssam #include <sys/types.h> 69289Ssam #include <sys/socket.h> 713549Ssam #include <sys/stat.h> 813549Ssam #include <sys/wait.h> 99289Ssam 109289Ssam #include <netinet/in.h> 119289Ssam 121513Sroot #include <stdio.h> 131513Sroot #include <sgtty.h> 141513Sroot #include <utmp.h> 151513Sroot #include <signal.h> 166394Sroot #include <errno.h> 179289Ssam #include <netdb.h> 181513Sroot 191513Sroot /* 201513Sroot * comsat 211513Sroot */ 2212746Ssam int debug = 0; 2312746Ssam #define dprintf if (debug) printf 241513Sroot 251513Sroot #define MAXUTMP 100 /* down from init */ 261513Sroot 279878Ssam struct sockaddr_in sin = { AF_INET }; 286394Sroot extern errno; 296394Sroot 301513Sroot struct utmp utmp[100]; 311513Sroot int nutmp; 321513Sroot int uf; 331513Sroot unsigned utmpmtime; /* last modification time for utmp */ 341513Sroot int onalrm(); 359289Ssam struct servent *sp; 361513Sroot 371513Sroot #define NAMLEN (sizeof (uts[0].ut_name) + 1) 381513Sroot 391513Sroot main(argc, argv) 401513Sroot char **argv; 411513Sroot { 421513Sroot register cc; 431513Sroot char buf[BUFSIZ]; 446394Sroot int s; 451513Sroot 469289Ssam sp = getservbyname("biff", "udp"); 479289Ssam if (sp == 0) { 489289Ssam fprintf(stderr, "comsat: biff/udp: unknown service\n"); 499289Ssam exit(1); 509289Ssam } 5112746Ssam if (!debug) 521513Sroot if (fork()) 531513Sroot exit(); 541513Sroot chdir("/usr/spool/mail"); 551513Sroot if((uf = open("/etc/utmp",0)) < 0) 561513Sroot perror("/etc/utmp"), exit(1); 571572Sbill sleep(10); 581513Sroot onalrm(); 5913022Ssam signal(SIGALRM, onalrm); 6013022Ssam signal(SIGTTOU, SIG_IGN); 619289Ssam s = socket(AF_INET, SOCK_DGRAM, 0, 0); 626394Sroot if (s < 0) { 636394Sroot perror("socket"); 641513Sroot exit(1); 651513Sroot } 669289Ssam sin.sin_port = sp->s_port; 679289Ssam if (bind(s, &sin, sizeof (sin), 0) < 0) { 689289Ssam perror("bind"); 699289Ssam exit(1); 709289Ssam } 716394Sroot for (;;) { 726394Sroot char msgbuf[100]; 736394Sroot int cc; 741513Sroot 759289Ssam cc = recv(s, msgbuf, sizeof (msgbuf) - 1, 0); 766394Sroot if (cc <= 0) { 776394Sroot if (errno != EINTR) 786394Sroot sleep(1); 796394Sroot errno = 0; 806394Sroot continue; 811513Sroot } 826394Sroot msgbuf[cc] = 0; 836394Sroot mailfor(msgbuf); 841513Sroot } 851513Sroot } 861513Sroot 871513Sroot onalrm() 881513Sroot { 891513Sroot struct stat statbf; 901513Sroot struct utmp *utp; 911513Sroot 921513Sroot dprintf("alarm\n"); 931513Sroot alarm(15); 941513Sroot fstat(uf,&statbf); 951513Sroot if (statbf.st_mtime > utmpmtime) { 961513Sroot dprintf(" changed\n"); 971513Sroot utmpmtime = statbf.st_mtime; 981513Sroot lseek(uf, 0, 0); 991513Sroot nutmp = read(uf,utmp,sizeof(utmp))/sizeof(struct utmp); 1001513Sroot } else 1011513Sroot dprintf(" ok\n"); 1021513Sroot } 1031513Sroot 1041513Sroot mailfor(name) 1051513Sroot char *name; 1061513Sroot { 1071513Sroot register struct utmp *utp = &utmp[nutmp]; 1081513Sroot register char *cp; 1091513Sroot char *rindex(); 1101513Sroot int offset; 1111513Sroot 1121513Sroot dprintf("mailfor %s\n", name); 1131513Sroot cp = name; 1141513Sroot while (*cp && *cp != '@') 1151513Sroot cp++; 1161513Sroot if (*cp == 0) { 1171513Sroot dprintf("bad format\n"); 1181513Sroot return; 1191513Sroot } 1201513Sroot *cp = 0; 1211513Sroot offset = atoi(cp+1); 1221513Sroot while (--utp >= utmp) 1231513Sroot if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name))) 1241513Sroot if (fork() == 0) { 1251513Sroot signal(SIGALRM, SIG_DFL); 1261513Sroot alarm(30); 1271513Sroot notify(utp, offset), exit(0); 1281513Sroot } else 1291513Sroot while (wait3(0, WNOHANG, 0) > 0) 1301513Sroot continue; 1311513Sroot } 1321513Sroot 1331513Sroot char *cr; 1341513Sroot 1351513Sroot notify(utp, offset) 1361513Sroot register struct utmp *utp; 1371513Sroot { 1381513Sroot FILE *tp; 1391513Sroot struct sgttyb gttybuf; 14012746Ssam char tty[20], hostname[32]; 1411513Sroot char name[sizeof (utmp[0].ut_name) + 1]; 1421513Sroot struct stat stb; 1431513Sroot 1441513Sroot strcpy(tty, "/dev/"); 1451513Sroot strncat(tty, utp->ut_line, sizeof(utp->ut_line)); 1461513Sroot dprintf("notify %s on %s\n", utp->ut_name, tty); 1471513Sroot if (stat(tty, &stb) == 0 && (stb.st_mode & 0100) == 0) { 1481513Sroot dprintf("wrong mode\n"); 1491513Sroot return; 1501513Sroot } 1511513Sroot if ((tp = fopen(tty,"w")) == 0) { 1521513Sroot dprintf("fopen failed\n"); 1531513Sroot return; 1541513Sroot } 15512746Ssam ioctl(fileno(tp), TIOCGETP, >tybuf); 1561513Sroot cr = (gttybuf.sg_flags & CRMOD) ? "" : "\r"; 15712746Ssam gethostname(hostname, sizeof (hostname)); 1581513Sroot strncpy(name, utp->ut_name, sizeof (utp->ut_name)); 1591513Sroot name[sizeof (name) - 1] = 0; 16012746Ssam fprintf(tp,"%s\n\007New mail for %s@%s\007 has arrived:%s\n", 16112746Ssam cr, name, hostname, cr); 1621513Sroot fprintf(tp,"----%s\n", cr); 1631513Sroot jkfprintf(tp, name, offset); 16412746Ssam fclose(tp); 1651513Sroot } 1661513Sroot 1671513Sroot jkfprintf(tp, name, offset) 1681513Sroot register FILE *tp; 1691513Sroot { 1701513Sroot register FILE *fi; 1711513Sroot register int linecnt, charcnt; 17212746Ssam char line[BUFSIZ]; 173*13783Ssam int inheader; 1741513Sroot 1751513Sroot dprintf("HERE %s's mail starting at %d\n", 1761513Sroot name, offset); 1771513Sroot if ((fi = fopen(name,"r")) == NULL) { 1781513Sroot dprintf("Cant read the mail\n"); 1791513Sroot return; 1801513Sroot } 1811513Sroot fseek(fi, offset, 0); 18212746Ssam /* 18312746Ssam * Print the first 7 lines or 560 characters of the new mail 18412746Ssam * (whichever comes first). Skip header crap other than 185*13783Ssam * From, Subject, To, and Date. 18612746Ssam */ 1871513Sroot linecnt = 7; 1881513Sroot charcnt = 560; 189*13783Ssam inheader = 1; 19012746Ssam while (fgets(line, sizeof (line), fi) != NULL) { 19112746Ssam register char *cp; 19212746Ssam char *index(); 193*13783Ssam int cnt; 1941513Sroot 19512746Ssam if (linecnt <= 0 || charcnt <= 0) { 1961513Sroot fprintf(tp,"...more...%s\n", cr); 19713022Ssam return; 1981513Sroot } 199*13783Ssam if (strncmp(line, "From ", 5) == 0) 200*13783Ssam continue; 201*13783Ssam if (inheader && (line[0] == ' ' || line[0] == '\t')) 202*13783Ssam continue; 20312746Ssam cp = index(line, ':'); 204*13783Ssam if (cp == 0 || (index(line, ' ') && index(line, ' ') < cp)) 205*13783Ssam inheader = 0; 206*13783Ssam else 207*13783Ssam cnt = cp - line; 208*13783Ssam if (inheader && 209*13783Ssam strncmp(line, "Date", cnt) && 210*13783Ssam strncmp(line, "From", cnt) && 211*13783Ssam strncmp(line, "Subject", cnt) && 212*13783Ssam strncmp(line, "To", cnt)) 21312746Ssam continue; 21412746Ssam cp = index(line, '\n'); 21512746Ssam if (cp) 21612746Ssam *cp = '\0'; 21712746Ssam fprintf(tp,"%s%s\n", line, cr); 21812746Ssam linecnt--, charcnt -= strlen(line); 2191513Sroot } 22012746Ssam fprintf(tp,"----%s\n", cr); 2211513Sroot } 222