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"; 1132638Sbostic #endif /* !lint */ 126394Sroot 1322550Sdist #ifndef lint 14*32646Sbostic static char sccsid[] = "@(#)comsat.c 5.8 (Berkeley) 11/19/87"; 1532638Sbostic #endif /* !lint */ 1622550Sdist 1732638Sbostic #include <sys/param.h> 189289Ssam #include <sys/socket.h> 1913549Ssam #include <sys/stat.h> 2032638Sbostic #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> 3232638Sbostic #include <strings.h> 331513Sroot 341513Sroot /* 351513Sroot * comsat 361513Sroot */ 3712746Ssam int debug = 0; 3832638Sbostic #define dsyslog if (debug) syslog 391513Sroot 4032638Sbostic #define MAXIDLE 120 416394Sroot 4232638Sbostic char hostname[MAXHOSTNAMELEN]; 4322545Sbloom struct utmp *utmp = NULL; 4432638Sbostic time_t lastmsgtime, time(); 4532638Sbostic int nutmp, uf; 461513Sroot 471513Sroot main(argc, argv) 4816367Skarels int argc; 4932638Sbostic char **argv; 501513Sroot { 5132638Sbostic extern int errno; 5216367Skarels register int cc; 5316367Skarels char msgbuf[100]; 5416367Skarels struct sockaddr_in from; 5532638Sbostic 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"); 62*32646Sbostic exit(1); 6316367Skarels } 6432008Smarc openlog("comsat", LOG_PID, LOG_DAEMON); 6532638Sbostic if (chdir("/usr/spool/mail")) { 6632638Sbostic syslog(LOG_ERR, "chdir: /usr/spool/mail"); 6732638Sbostic exit(1); 6832638Sbostic } 6932638Sbostic 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 } 7432638Sbostic (void)time(&lastmsgtime); 7532638Sbostic (void)gethostname(hostname, sizeof (hostname)); 761513Sroot onalrm(); 7732638Sbostic (void)signal(SIGALRM, onalrm); 7832638Sbostic (void)signal(SIGTTOU, SIG_IGN); 7932638Sbostic (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 } 8832638Sbostic if (!nutmp) /* no one has logged in yet */ 8932638Sbostic continue; 9022596Sbloom sigblock(sigmask(SIGALRM)); 916394Sroot msgbuf[cc] = 0; 9232638Sbostic (void)time(&lastmsgtime); 936394Sroot mailfor(msgbuf); 9432638Sbostic sigsetmask(0L); 951513Sroot } 961513Sroot } 971513Sroot 9816587Ssam reapchildren() 9916587Ssam { 10032638Sbostic while (wait3((struct wait *)NULL, WNOHANG, (struct rusage *)NULL) > 0); 10116587Ssam } 10216587Ssam 1031513Sroot onalrm() 1041513Sroot { 10532638Sbostic static u_int utmpsize; /* last malloced size for utmp */ 10632638Sbostic static u_int utmpmtime; /* last modification time for utmp */ 1071513Sroot struct stat statbf; 10832638Sbostic off_t lseek(); 10932638Sbostic char *malloc(), *realloc(); 1101513Sroot 11132638Sbostic if (time((time_t *)NULL) - lastmsgtime >= MAXIDLE) 11216808Sralph exit(0); 11332638Sbostic (void)alarm((u_int)15); 11432638Sbostic (void)fstat(uf, &statbf); 1151513Sroot if (statbf.st_mtime > utmpmtime) { 1161513Sroot utmpmtime = statbf.st_mtime; 11722545Sbloom if (statbf.st_size > utmpsize) { 11822545Sbloom utmpsize = statbf.st_size + 10 * sizeof(struct utmp); 11922545Sbloom if (utmp) 12032638Sbostic utmp = (struct utmp *)realloc((char *)utmp, utmpsize); 12122545Sbloom else 12222545Sbloom utmp = (struct utmp *)malloc(utmpsize); 12332638Sbostic if (!utmp) { 124*32646Sbostic syslog(LOG_ERR, "malloc failed"); 12522545Sbloom exit(1); 12622545Sbloom } 12722545Sbloom } 12832638Sbostic (void)lseek(uf, 0L, L_SET); 12932638Sbostic nutmp = read(uf, utmp, statbf.st_size)/sizeof(struct utmp); 13032638Sbostic } 1311513Sroot } 1321513Sroot 1331513Sroot mailfor(name) 1341513Sroot char *name; 1351513Sroot { 1361513Sroot register struct utmp *utp = &utmp[nutmp]; 1371513Sroot register char *cp; 1381513Sroot int offset; 1391513Sroot 140*32646Sbostic if (!(cp = index(name, '@'))) 1411513Sroot return; 14232638Sbostic *cp = '\0'; 14332638Sbostic offset = atoi(cp + 1); 1441513Sroot while (--utp >= utmp) 1451513Sroot if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name))) 14616587Ssam notify(utp, offset); 1471513Sroot } 1481513Sroot 14932638Sbostic static char *cr; 1501513Sroot 1511513Sroot notify(utp, offset) 1521513Sroot register struct utmp *utp; 15332638Sbostic int offset; 1541513Sroot { 155*32646Sbostic static char tty[20] = "/dev/"; 156*32646Sbostic struct sgttyb gttybuf; 15717189Sralph FILE *tp; 158*32646Sbostic char name[sizeof (utmp[0].ut_name) + 1]; 1591513Sroot struct stat stb; 1601513Sroot 16132638Sbostic (void)strncpy(tty + 5, utp->ut_line, sizeof(utp->ut_line)); 16232638Sbostic if (stat(tty, &stb) || !(stb.st_mode & S_IEXEC)) { 163*32646Sbostic dsyslog(LOG_DEBUG, "%s: wrong mode on %s", utp->ut_name, tty); 1641513Sroot return; 1651513Sroot } 166*32646Sbostic dsyslog(LOG_DEBUG, "notify %s on %s\n", utp->ut_name, tty); 16717189Sralph if (fork()) 16816587Ssam return; 16932638Sbostic (void)signal(SIGALRM, SIG_DFL); 17032638Sbostic (void)alarm((u_int)30); 17132638Sbostic if ((tp = fopen(tty, "w")) == NULL) { 172*32646Sbostic dsyslog(LOG_ERR, "fopen of tty %s failed", tty); 173*32646Sbostic _exit(-1); 1741513Sroot } 17532638Sbostic (void)ioctl(fileno(tp), TIOCGETP, >tybuf); 17624523Sbloom cr = (gttybuf.sg_flags&CRMOD) && !(gttybuf.sg_flags&RAW) ? "" : "\r"; 17732638Sbostic (void)strncpy(name, utp->ut_name, sizeof (utp->ut_name)); 17816587Ssam name[sizeof (name) - 1] = '\0'; 17932638Sbostic fprintf(tp, "%s\n\007New mail for %s@%.*s\007 has arrived:%s\n----%s\n", 18032638Sbostic cr, name, sizeof (hostname), hostname, cr, cr); 18117189Sralph jkfprintf(tp, name, offset); 182*32646Sbostic fclose(tp); 183*32646Sbostic _exit(0); 1841513Sroot } 1851513Sroot 18617189Sralph jkfprintf(tp, name, offset) 18717189Sralph register FILE *tp; 18832638Sbostic char name[]; 18932638Sbostic int offset; 1901513Sroot { 19132638Sbostic register char *cp; 1921513Sroot register FILE *fi; 19332638Sbostic register int linecnt, charcnt, inheader; 19412746Ssam char line[BUFSIZ]; 19532638Sbostic off_t fseek(); 1961513Sroot 197*32646Sbostic if ((fi = fopen(name, "r")) == NULL) 1981513Sroot return; 19932638Sbostic (void)fseek(fi, (long)offset, L_SET); 20012746Ssam /* 20112746Ssam * Print the first 7 lines or 560 characters of the new mail 20212746Ssam * (whichever comes first). Skip header crap other than 20313783Ssam * From, Subject, To, and Date. 20412746Ssam */ 2051513Sroot linecnt = 7; 2061513Sroot charcnt = 560; 20713783Ssam inheader = 1; 20812746Ssam while (fgets(line, sizeof (line), fi) != NULL) { 20932638Sbostic if (inheader) { 210*32646Sbostic if (line[0] == '\n') { 211*32646Sbostic inheader = 0; 21232638Sbostic continue; 213*32646Sbostic } 214*32646Sbostic if (line[0] == ' ' || line[0] == '\t' || 215*32646Sbostic strncmp(line, "From:", 5) && 21632638Sbostic strncmp(line, "Subject:", 8)) 21732638Sbostic continue; 21832638Sbostic } 21932638Sbostic if (cp = index(line, '\n')) 22012746Ssam *cp = '\0'; 22132638Sbostic fprintf(tp, "%s%s\n", line, cr); 222*32646Sbostic charcnt -= strlen(line); 223*32646Sbostic if (--linecnt <= 0 || charcnt <= 0) { 22432638Sbostic fprintf(tp, "...more...%s\n", cr); 22532638Sbostic return; 22632638Sbostic } 2271513Sroot } 22832638Sbostic fprintf(tp, "----%s\n", cr); 2291513Sroot } 230