122550Sdist /* 222550Sdist * Copyright (c) 1980 Regents of the University of California. 3*32756Sbostic * All rights reserved. 4*32756Sbostic * 5*32756Sbostic * Redistribution and use in source and binary forms are permitted 6*32756Sbostic * provided that this notice is preserved and that due credit is given 7*32756Sbostic * to the University of California at Berkeley. The name of the University 8*32756Sbostic * may not be used to endorse or promote products derived from this 9*32756Sbostic * software without specific written prior permission. This software 10*32756Sbostic * is provided ``as is'' without express or implied warranty. 1122550Sdist */ 1222550Sdist 139289Ssam #ifndef lint 1422550Sdist char copyright[] = 1522550Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1622550Sdist All rights reserved.\n"; 17*32756Sbostic #endif /* not lint */ 186394Sroot 1922550Sdist #ifndef lint 20*32756Sbostic static char sccsid[] = "@(#)comsat.c 5.9 (Berkeley) 12/04/87"; 21*32756Sbostic #endif /* not lint */ 2222550Sdist 2332638Sbostic #include <sys/param.h> 249289Ssam #include <sys/socket.h> 2513549Ssam #include <sys/stat.h> 2632638Sbostic #include <sys/file.h> 2713549Ssam #include <sys/wait.h> 289289Ssam 299289Ssam #include <netinet/in.h> 309289Ssam 311513Sroot #include <stdio.h> 321513Sroot #include <sgtty.h> 331513Sroot #include <utmp.h> 341513Sroot #include <signal.h> 356394Sroot #include <errno.h> 369289Ssam #include <netdb.h> 3716808Sralph #include <syslog.h> 3832638Sbostic #include <strings.h> 391513Sroot 401513Sroot /* 411513Sroot * comsat 421513Sroot */ 4312746Ssam int debug = 0; 4432638Sbostic #define dsyslog if (debug) syslog 451513Sroot 4632638Sbostic #define MAXIDLE 120 476394Sroot 4832638Sbostic char hostname[MAXHOSTNAMELEN]; 4922545Sbloom struct utmp *utmp = NULL; 5032638Sbostic time_t lastmsgtime, time(); 5132638Sbostic int nutmp, uf; 521513Sroot 531513Sroot main(argc, argv) 5416367Skarels int argc; 5532638Sbostic char **argv; 561513Sroot { 5732638Sbostic extern int errno; 5816367Skarels register int cc; 5916367Skarels char msgbuf[100]; 6016367Skarels struct sockaddr_in from; 6132638Sbostic int fromlen, reapchildren(), onalrm(); 621513Sroot 6316367Skarels /* verify proper invocation */ 6416367Skarels fromlen = sizeof (from); 6516367Skarels if (getsockname(0, &from, &fromlen) < 0) { 6616367Skarels fprintf(stderr, "%s: ", argv[0]); 6716367Skarels perror("getsockname"); 6832646Sbostic exit(1); 6916367Skarels } 7032008Smarc openlog("comsat", LOG_PID, LOG_DAEMON); 7132638Sbostic if (chdir("/usr/spool/mail")) { 7232638Sbostic syslog(LOG_ERR, "chdir: /usr/spool/mail"); 7332638Sbostic exit(1); 7432638Sbostic } 7532638Sbostic if ((uf = open("/etc/utmp", O_RDONLY, 0)) < 0) { 7632008Smarc syslog(LOG_ERR, ".main: /etc/utmp: %m"); 7716367Skarels (void) recv(0, msgbuf, sizeof (msgbuf) - 1, 0); 789289Ssam exit(1); 799289Ssam } 8032638Sbostic (void)time(&lastmsgtime); 8132638Sbostic (void)gethostname(hostname, sizeof (hostname)); 821513Sroot onalrm(); 8332638Sbostic (void)signal(SIGALRM, onalrm); 8432638Sbostic (void)signal(SIGTTOU, SIG_IGN); 8532638Sbostic (void)signal(SIGCHLD, reapchildren); 866394Sroot for (;;) { 8716367Skarels cc = recv(0, msgbuf, sizeof (msgbuf) - 1, 0); 886394Sroot if (cc <= 0) { 896394Sroot if (errno != EINTR) 906394Sroot sleep(1); 916394Sroot errno = 0; 926394Sroot continue; 931513Sroot } 9432638Sbostic if (!nutmp) /* no one has logged in yet */ 9532638Sbostic continue; 9622596Sbloom sigblock(sigmask(SIGALRM)); 976394Sroot msgbuf[cc] = 0; 9832638Sbostic (void)time(&lastmsgtime); 996394Sroot mailfor(msgbuf); 10032638Sbostic sigsetmask(0L); 1011513Sroot } 1021513Sroot } 1031513Sroot 10416587Ssam reapchildren() 10516587Ssam { 10632638Sbostic while (wait3((struct wait *)NULL, WNOHANG, (struct rusage *)NULL) > 0); 10716587Ssam } 10816587Ssam 1091513Sroot onalrm() 1101513Sroot { 11132638Sbostic static u_int utmpsize; /* last malloced size for utmp */ 11232638Sbostic static u_int utmpmtime; /* last modification time for utmp */ 1131513Sroot struct stat statbf; 11432638Sbostic off_t lseek(); 11532638Sbostic char *malloc(), *realloc(); 1161513Sroot 11732638Sbostic if (time((time_t *)NULL) - lastmsgtime >= MAXIDLE) 11816808Sralph exit(0); 11932638Sbostic (void)alarm((u_int)15); 12032638Sbostic (void)fstat(uf, &statbf); 1211513Sroot if (statbf.st_mtime > utmpmtime) { 1221513Sroot utmpmtime = statbf.st_mtime; 12322545Sbloom if (statbf.st_size > utmpsize) { 12422545Sbloom utmpsize = statbf.st_size + 10 * sizeof(struct utmp); 12522545Sbloom if (utmp) 12632638Sbostic utmp = (struct utmp *)realloc((char *)utmp, utmpsize); 12722545Sbloom else 12822545Sbloom utmp = (struct utmp *)malloc(utmpsize); 12932638Sbostic if (!utmp) { 13032646Sbostic syslog(LOG_ERR, "malloc failed"); 13122545Sbloom exit(1); 13222545Sbloom } 13322545Sbloom } 13432638Sbostic (void)lseek(uf, 0L, L_SET); 13532638Sbostic nutmp = read(uf, utmp, statbf.st_size)/sizeof(struct utmp); 13632638Sbostic } 1371513Sroot } 1381513Sroot 1391513Sroot mailfor(name) 1401513Sroot char *name; 1411513Sroot { 1421513Sroot register struct utmp *utp = &utmp[nutmp]; 1431513Sroot register char *cp; 1441513Sroot int offset; 1451513Sroot 14632646Sbostic if (!(cp = index(name, '@'))) 1471513Sroot return; 14832638Sbostic *cp = '\0'; 14932638Sbostic offset = atoi(cp + 1); 1501513Sroot while (--utp >= utmp) 1511513Sroot if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name))) 15216587Ssam notify(utp, offset); 1531513Sroot } 1541513Sroot 15532638Sbostic static char *cr; 1561513Sroot 1571513Sroot notify(utp, offset) 1581513Sroot register struct utmp *utp; 15932638Sbostic int offset; 1601513Sroot { 16132646Sbostic static char tty[20] = "/dev/"; 16232646Sbostic struct sgttyb gttybuf; 16317189Sralph FILE *tp; 16432646Sbostic char name[sizeof (utmp[0].ut_name) + 1]; 1651513Sroot struct stat stb; 1661513Sroot 16732638Sbostic (void)strncpy(tty + 5, utp->ut_line, sizeof(utp->ut_line)); 16832638Sbostic if (stat(tty, &stb) || !(stb.st_mode & S_IEXEC)) { 16932646Sbostic dsyslog(LOG_DEBUG, "%s: wrong mode on %s", utp->ut_name, tty); 1701513Sroot return; 1711513Sroot } 17232646Sbostic dsyslog(LOG_DEBUG, "notify %s on %s\n", utp->ut_name, tty); 17317189Sralph if (fork()) 17416587Ssam return; 17532638Sbostic (void)signal(SIGALRM, SIG_DFL); 17632638Sbostic (void)alarm((u_int)30); 17732638Sbostic if ((tp = fopen(tty, "w")) == NULL) { 17832646Sbostic dsyslog(LOG_ERR, "fopen of tty %s failed", tty); 17932646Sbostic _exit(-1); 1801513Sroot } 18132638Sbostic (void)ioctl(fileno(tp), TIOCGETP, >tybuf); 18224523Sbloom cr = (gttybuf.sg_flags&CRMOD) && !(gttybuf.sg_flags&RAW) ? "" : "\r"; 18332638Sbostic (void)strncpy(name, utp->ut_name, sizeof (utp->ut_name)); 18416587Ssam name[sizeof (name) - 1] = '\0'; 18532638Sbostic fprintf(tp, "%s\n\007New mail for %s@%.*s\007 has arrived:%s\n----%s\n", 18632638Sbostic cr, name, sizeof (hostname), hostname, cr, cr); 18717189Sralph jkfprintf(tp, name, offset); 18832646Sbostic fclose(tp); 18932646Sbostic _exit(0); 1901513Sroot } 1911513Sroot 19217189Sralph jkfprintf(tp, name, offset) 19317189Sralph register FILE *tp; 19432638Sbostic char name[]; 19532638Sbostic int offset; 1961513Sroot { 19732638Sbostic register char *cp; 1981513Sroot register FILE *fi; 19932638Sbostic register int linecnt, charcnt, inheader; 20012746Ssam char line[BUFSIZ]; 20132638Sbostic off_t fseek(); 2021513Sroot 20332646Sbostic if ((fi = fopen(name, "r")) == NULL) 2041513Sroot return; 20532638Sbostic (void)fseek(fi, (long)offset, L_SET); 20612746Ssam /* 20712746Ssam * Print the first 7 lines or 560 characters of the new mail 20812746Ssam * (whichever comes first). Skip header crap other than 20913783Ssam * From, Subject, To, and Date. 21012746Ssam */ 2111513Sroot linecnt = 7; 2121513Sroot charcnt = 560; 21313783Ssam inheader = 1; 21412746Ssam while (fgets(line, sizeof (line), fi) != NULL) { 21532638Sbostic if (inheader) { 21632646Sbostic if (line[0] == '\n') { 21732646Sbostic inheader = 0; 21832638Sbostic continue; 21932646Sbostic } 22032646Sbostic if (line[0] == ' ' || line[0] == '\t' || 22132646Sbostic strncmp(line, "From:", 5) && 22232638Sbostic strncmp(line, "Subject:", 8)) 22332638Sbostic continue; 22432638Sbostic } 22532638Sbostic if (cp = index(line, '\n')) 22612746Ssam *cp = '\0'; 22732638Sbostic fprintf(tp, "%s%s\n", line, cr); 22832646Sbostic charcnt -= strlen(line); 22932646Sbostic if (--linecnt <= 0 || charcnt <= 0) { 23032638Sbostic fprintf(tp, "...more...%s\n", cr); 23132638Sbostic return; 23232638Sbostic } 2331513Sroot } 23432638Sbostic fprintf(tp, "----%s\n", cr); 2351513Sroot } 236