122550Sdist /* 222550Sdist * Copyright (c) 1980 Regents of the University of California. 322550Sdist * All rights reserved. The Berkeley software License Agreement 422550Sdist * specifies the terms and conditions for redistribution. 522550Sdist */ 622550Sdist 79289Ssam #ifndef lint 822550Sdist char copyright[] = 922550Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1022550Sdist All rights reserved.\n"; 11*32638Sbostic #endif /* !lint */ 126394Sroot 1322550Sdist #ifndef lint 14*32638Sbostic static char sccsid[] = "@(#)comsat.c 5.7 (Berkeley) 11/18/87"; 15*32638Sbostic #endif /* !lint */ 1622550Sdist 17*32638Sbostic #include <sys/param.h> 189289Ssam #include <sys/socket.h> 1913549Ssam #include <sys/stat.h> 20*32638Sbostic #include <sys/file.h> 2113549Ssam #include <sys/wait.h> 229289Ssam 239289Ssam #include <netinet/in.h> 249289Ssam 251513Sroot #include <stdio.h> 261513Sroot #include <sgtty.h> 271513Sroot #include <utmp.h> 281513Sroot #include <signal.h> 296394Sroot #include <errno.h> 309289Ssam #include <netdb.h> 3116808Sralph #include <syslog.h> 32*32638Sbostic #include <strings.h> 331513Sroot 341513Sroot /* 351513Sroot * comsat 361513Sroot */ 3712746Ssam int debug = 0; 38*32638Sbostic #define dsyslog if (debug) syslog 391513Sroot 40*32638Sbostic #define MAXIDLE 120 416394Sroot 42*32638Sbostic char hostname[MAXHOSTNAMELEN]; 4322545Sbloom struct utmp *utmp = NULL; 44*32638Sbostic time_t lastmsgtime, time(); 45*32638Sbostic int nutmp, uf; 461513Sroot 471513Sroot main(argc, argv) 4816367Skarels int argc; 49*32638Sbostic char **argv; 501513Sroot { 51*32638Sbostic extern int errno; 5216367Skarels register int cc; 5316367Skarels char msgbuf[100]; 5416367Skarels struct sockaddr_in from; 55*32638Sbostic int fromlen, reapchildren(), onalrm(); 561513Sroot 5716367Skarels /* verify proper invocation */ 5816367Skarels fromlen = sizeof (from); 5916367Skarels if (getsockname(0, &from, &fromlen) < 0) { 6016367Skarels fprintf(stderr, "%s: ", argv[0]); 6116367Skarels perror("getsockname"); 6216367Skarels _exit(1); 6316367Skarels } 6432008Smarc openlog("comsat", LOG_PID, LOG_DAEMON); 65*32638Sbostic if (chdir("/usr/spool/mail")) { 66*32638Sbostic syslog(LOG_ERR, "chdir: /usr/spool/mail"); 67*32638Sbostic exit(1); 68*32638Sbostic } 69*32638Sbostic if ((uf = open("/etc/utmp", O_RDONLY, 0)) < 0) { 7032008Smarc syslog(LOG_ERR, ".main: /etc/utmp: %m"); 7116367Skarels (void) recv(0, msgbuf, sizeof (msgbuf) - 1, 0); 729289Ssam exit(1); 739289Ssam } 74*32638Sbostic (void)time(&lastmsgtime); 75*32638Sbostic (void)gethostname(hostname, sizeof (hostname)); 761513Sroot onalrm(); 77*32638Sbostic (void)signal(SIGALRM, onalrm); 78*32638Sbostic (void)signal(SIGTTOU, SIG_IGN); 79*32638Sbostic (void)signal(SIGCHLD, reapchildren); 806394Sroot for (;;) { 8116367Skarels cc = recv(0, msgbuf, sizeof (msgbuf) - 1, 0); 826394Sroot if (cc <= 0) { 836394Sroot if (errno != EINTR) 846394Sroot sleep(1); 856394Sroot errno = 0; 866394Sroot continue; 871513Sroot } 88*32638Sbostic if (!nutmp) /* no one has logged in yet */ 89*32638Sbostic continue; 9022596Sbloom sigblock(sigmask(SIGALRM)); 916394Sroot msgbuf[cc] = 0; 92*32638Sbostic (void)time(&lastmsgtime); 936394Sroot mailfor(msgbuf); 94*32638Sbostic sigsetmask(0L); 951513Sroot } 961513Sroot } 971513Sroot 9816587Ssam reapchildren() 9916587Ssam { 100*32638Sbostic while (wait3((struct wait *)NULL, WNOHANG, (struct rusage *)NULL) > 0); 10116587Ssam } 10216587Ssam 1031513Sroot onalrm() 1041513Sroot { 105*32638Sbostic static u_int utmpsize; /* last malloced size for utmp */ 106*32638Sbostic static u_int utmpmtime; /* last modification time for utmp */ 1071513Sroot struct stat statbf; 108*32638Sbostic off_t lseek(); 109*32638Sbostic char *malloc(), *realloc(); 1101513Sroot 111*32638Sbostic if (time((time_t *)NULL) - lastmsgtime >= MAXIDLE) 11216808Sralph exit(0); 113*32638Sbostic dsyslog(LOG_DEBUG, ".onalrm: alarm"); 114*32638Sbostic (void)alarm((u_int)15); 115*32638Sbostic (void)fstat(uf, &statbf); 1161513Sroot if (statbf.st_mtime > utmpmtime) { 117*32638Sbostic dsyslog(LOG_DEBUG, ".onalrm: changed\n"); 1181513Sroot utmpmtime = statbf.st_mtime; 11922545Sbloom if (statbf.st_size > utmpsize) { 12022545Sbloom utmpsize = statbf.st_size + 10 * sizeof(struct utmp); 12122545Sbloom if (utmp) 122*32638Sbostic utmp = (struct utmp *)realloc((char *)utmp, utmpsize); 12322545Sbloom else 12422545Sbloom utmp = (struct utmp *)malloc(utmpsize); 125*32638Sbostic if (!utmp) { 126*32638Sbostic dsyslog(LOG_DEBUG, ".onalrm: malloc failed"); 12722545Sbloom exit(1); 12822545Sbloom } 12922545Sbloom } 130*32638Sbostic (void)lseek(uf, 0L, L_SET); 131*32638Sbostic nutmp = read(uf, utmp, statbf.st_size)/sizeof(struct utmp); 132*32638Sbostic } 133*32638Sbostic else 13432008Smarc dsyslog(LOG_DEBUG, ".onalrm: ok\n"); 1351513Sroot } 1361513Sroot 1371513Sroot mailfor(name) 1381513Sroot char *name; 1391513Sroot { 1401513Sroot register struct utmp *utp = &utmp[nutmp]; 1411513Sroot register char *cp; 1421513Sroot int offset; 1431513Sroot 144*32638Sbostic dsyslog(LOG_DEBUG, ".mailfor: mailfor %s\n", name); 145*32638Sbostic if (!(cp = index(name, '@'))) { 146*32638Sbostic dsyslog(LOG_DEBUG, ".mailfor: bad format\n"); 1471513Sroot return; 1481513Sroot } 149*32638Sbostic *cp = '\0'; 150*32638Sbostic offset = atoi(cp + 1); 1511513Sroot while (--utp >= utmp) 1521513Sroot if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name))) 15316587Ssam notify(utp, offset); 1541513Sroot } 1551513Sroot 156*32638Sbostic static char *cr; 1571513Sroot 1581513Sroot notify(utp, offset) 1591513Sroot register struct utmp *utp; 160*32638Sbostic int offset; 1611513Sroot { 16217189Sralph FILE *tp; 1631513Sroot struct sgttyb gttybuf; 16417189Sralph char tty[20], name[sizeof (utmp[0].ut_name) + 1]; 1651513Sroot struct stat stb; 1661513Sroot 167*32638Sbostic (void)strcpy(tty, "/dev/"); 168*32638Sbostic (void)strncpy(tty + 5, utp->ut_line, sizeof(utp->ut_line)); 169*32638Sbostic dsyslog(LOG_DEBUG, ".notify: notify %s on %s\n", utp->ut_name, tty); 170*32638Sbostic if (stat(tty, &stb) || !(stb.st_mode & S_IEXEC)) { 171*32638Sbostic dsyslog(LOG_DEBUG, ".notify: wrong mode on tty"); 1721513Sroot return; 1731513Sroot } 17417189Sralph if (fork()) 17516587Ssam return; 176*32638Sbostic (void)signal(SIGALRM, SIG_DFL); 177*32638Sbostic (void)alarm((u_int)30); 178*32638Sbostic if ((tp = fopen(tty, "w")) == NULL) { 179*32638Sbostic dsyslog(LOG_DEBUG, ".notify: fopen of tty failed"); 18017189Sralph exit(-1); 1811513Sroot } 182*32638Sbostic (void)ioctl(fileno(tp), TIOCGETP, >tybuf); 18324523Sbloom cr = (gttybuf.sg_flags&CRMOD) && !(gttybuf.sg_flags&RAW) ? "" : "\r"; 184*32638Sbostic (void)strncpy(name, utp->ut_name, sizeof (utp->ut_name)); 18516587Ssam name[sizeof (name) - 1] = '\0'; 186*32638Sbostic fprintf(tp, "%s\n\007New mail for %s@%.*s\007 has arrived:%s\n----%s\n", 187*32638Sbostic cr, name, sizeof (hostname), hostname, cr, cr); 18817189Sralph jkfprintf(tp, name, offset); 18916587Ssam exit(0); 1901513Sroot } 1911513Sroot 19217189Sralph jkfprintf(tp, name, offset) 19317189Sralph register FILE *tp; 194*32638Sbostic char name[]; 195*32638Sbostic int offset; 1961513Sroot { 197*32638Sbostic register char *cp; 1981513Sroot register FILE *fi; 199*32638Sbostic register int linecnt, charcnt, inheader; 20012746Ssam char line[BUFSIZ]; 201*32638Sbostic off_t fseek(); 2021513Sroot 203*32638Sbostic dsyslog(LOG_DEBUG, ".jkfprint: HERE %s's mail starting at %d\n", 20417189Sralph name, offset); 205*32638Sbostic if ((fi = fopen(name, "r")) == NULL) { 206*32638Sbostic dsyslog(LOG_DEBUG, ".jkfprintf: Can't read the mail\n"); 2071513Sroot return; 2081513Sroot } 209*32638Sbostic (void)fseek(fi, (long)offset, L_SET); 21012746Ssam /* 21112746Ssam * Print the first 7 lines or 560 characters of the new mail 21212746Ssam * (whichever comes first). Skip header crap other than 21313783Ssam * From, Subject, To, and Date. 21412746Ssam */ 2151513Sroot linecnt = 7; 2161513Sroot charcnt = 560; 21713783Ssam inheader = 1; 21812746Ssam while (fgets(line, sizeof (line), fi) != NULL) { 21913783Ssam if (strncmp(line, "From ", 5) == 0) 22013783Ssam continue; 221*32638Sbostic if (inheader) { 222*32638Sbostic if (line[0] == ' ' || line[0] == '\t') 223*32638Sbostic continue; 224*32638Sbostic if (!(cp = strpbrk(line, ": ")) || *cp == ' ') 225*32638Sbostic inheader = 0; 226*32638Sbostic else if (strncmp(line, "From:", 5) && 227*32638Sbostic strncmp(line, "Subject:", 8)) 228*32638Sbostic continue; 229*32638Sbostic } 230*32638Sbostic if (cp = index(line, '\n')) 23112746Ssam *cp = '\0'; 232*32638Sbostic fprintf(tp, "%s%s\n", line, cr); 233*32638Sbostic if (--linecnt <= 0 || (charcnt -= strlen(line)) <= 0) { 234*32638Sbostic fprintf(tp, "...more...%s\n", cr); 235*32638Sbostic return; 236*32638Sbostic } 2371513Sroot } 238*32638Sbostic fprintf(tp, "----%s\n", cr); 2391513Sroot } 240