122550Sdist /* 222550Sdist * Copyright (c) 1980 Regents of the University of California. 332756Sbostic * All rights reserved. 432756Sbostic * 532756Sbostic * Redistribution and use in source and binary forms are permitted 6*34777Sbostic * provided that the above copyright notice and this paragraph are 7*34777Sbostic * duplicated in all such forms and that any documentation, 8*34777Sbostic * advertising materials, and other materials related to such 9*34777Sbostic * distribution and use acknowledge that the software was developed 10*34777Sbostic * by the University of California, Berkeley. The name of the 11*34777Sbostic * University may not be used to endorse or promote products derived 12*34777Sbostic * from this software without specific prior written permission. 13*34777Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*34777Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*34777Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1622550Sdist */ 1722550Sdist 189289Ssam #ifndef lint 1922550Sdist char copyright[] = 2022550Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 2122550Sdist All rights reserved.\n"; 2232756Sbostic #endif /* not lint */ 236394Sroot 2422550Sdist #ifndef lint 25*34777Sbostic static char sccsid[] = "@(#)comsat.c 5.12 (Berkeley) 06/18/88"; 2632756Sbostic #endif /* not lint */ 2722550Sdist 2832638Sbostic #include <sys/param.h> 299289Ssam #include <sys/socket.h> 3013549Ssam #include <sys/stat.h> 3132638Sbostic #include <sys/file.h> 3213549Ssam #include <sys/wait.h> 339289Ssam 349289Ssam #include <netinet/in.h> 359289Ssam 361513Sroot #include <stdio.h> 371513Sroot #include <sgtty.h> 381513Sroot #include <utmp.h> 391513Sroot #include <signal.h> 406394Sroot #include <errno.h> 419289Ssam #include <netdb.h> 4216808Sralph #include <syslog.h> 4332638Sbostic #include <strings.h> 441513Sroot 451513Sroot /* 461513Sroot * comsat 471513Sroot */ 4812746Ssam int debug = 0; 4932638Sbostic #define dsyslog if (debug) syslog 501513Sroot 5132638Sbostic #define MAXIDLE 120 526394Sroot 5332638Sbostic char hostname[MAXHOSTNAMELEN]; 5422545Sbloom struct utmp *utmp = NULL; 5532638Sbostic time_t lastmsgtime, time(); 5632638Sbostic int nutmp, uf; 571513Sroot 581513Sroot main(argc, argv) 5916367Skarels int argc; 6032638Sbostic char **argv; 611513Sroot { 6232638Sbostic extern int errno; 6316367Skarels register int cc; 6416367Skarels char msgbuf[100]; 6516367Skarels struct sockaddr_in from; 6632638Sbostic int fromlen, reapchildren(), onalrm(); 671513Sroot 6816367Skarels /* verify proper invocation */ 6916367Skarels fromlen = sizeof (from); 7016367Skarels if (getsockname(0, &from, &fromlen) < 0) { 7116367Skarels fprintf(stderr, "%s: ", argv[0]); 7216367Skarels perror("getsockname"); 7332646Sbostic exit(1); 7416367Skarels } 7532008Smarc openlog("comsat", LOG_PID, LOG_DAEMON); 7632638Sbostic if (chdir("/usr/spool/mail")) { 7732638Sbostic syslog(LOG_ERR, "chdir: /usr/spool/mail"); 7832638Sbostic exit(1); 7932638Sbostic } 8032638Sbostic if ((uf = open("/etc/utmp", O_RDONLY, 0)) < 0) { 8132008Smarc syslog(LOG_ERR, ".main: /etc/utmp: %m"); 8216367Skarels (void) recv(0, msgbuf, sizeof (msgbuf) - 1, 0); 839289Ssam exit(1); 849289Ssam } 8532638Sbostic (void)time(&lastmsgtime); 8632638Sbostic (void)gethostname(hostname, sizeof (hostname)); 871513Sroot onalrm(); 8832638Sbostic (void)signal(SIGALRM, onalrm); 8932638Sbostic (void)signal(SIGTTOU, SIG_IGN); 9032638Sbostic (void)signal(SIGCHLD, reapchildren); 916394Sroot for (;;) { 9216367Skarels cc = recv(0, msgbuf, sizeof (msgbuf) - 1, 0); 936394Sroot if (cc <= 0) { 946394Sroot if (errno != EINTR) 956394Sroot sleep(1); 966394Sroot errno = 0; 976394Sroot continue; 981513Sroot } 9932638Sbostic if (!nutmp) /* no one has logged in yet */ 10032638Sbostic continue; 10122596Sbloom sigblock(sigmask(SIGALRM)); 1026394Sroot msgbuf[cc] = 0; 10332638Sbostic (void)time(&lastmsgtime); 1046394Sroot mailfor(msgbuf); 10532638Sbostic sigsetmask(0L); 1061513Sroot } 1071513Sroot } 1081513Sroot 10916587Ssam reapchildren() 11016587Ssam { 11133135Sbostic while (wait3((union wait *)NULL, WNOHANG, (struct rusage *)NULL) > 0); 11216587Ssam } 11316587Ssam 1141513Sroot onalrm() 1151513Sroot { 11632638Sbostic static u_int utmpsize; /* last malloced size for utmp */ 11732638Sbostic static u_int utmpmtime; /* last modification time for utmp */ 1181513Sroot struct stat statbf; 11932638Sbostic off_t lseek(); 12032638Sbostic char *malloc(), *realloc(); 1211513Sroot 12232638Sbostic if (time((time_t *)NULL) - lastmsgtime >= MAXIDLE) 12316808Sralph exit(0); 12432638Sbostic (void)alarm((u_int)15); 12532638Sbostic (void)fstat(uf, &statbf); 1261513Sroot if (statbf.st_mtime > utmpmtime) { 1271513Sroot utmpmtime = statbf.st_mtime; 12822545Sbloom if (statbf.st_size > utmpsize) { 12922545Sbloom utmpsize = statbf.st_size + 10 * sizeof(struct utmp); 13022545Sbloom if (utmp) 13132638Sbostic utmp = (struct utmp *)realloc((char *)utmp, utmpsize); 13222545Sbloom else 13322545Sbloom utmp = (struct utmp *)malloc(utmpsize); 13432638Sbostic if (!utmp) { 13532646Sbostic syslog(LOG_ERR, "malloc failed"); 13622545Sbloom exit(1); 13722545Sbloom } 13822545Sbloom } 13932638Sbostic (void)lseek(uf, 0L, L_SET); 14033824Sbostic nutmp = read(uf, utmp, (int)statbf.st_size)/sizeof(struct utmp); 14132638Sbostic } 1421513Sroot } 1431513Sroot 1441513Sroot mailfor(name) 1451513Sroot char *name; 1461513Sroot { 1471513Sroot register struct utmp *utp = &utmp[nutmp]; 1481513Sroot register char *cp; 14933824Sbostic off_t offset, atol(); 1501513Sroot 15132646Sbostic if (!(cp = index(name, '@'))) 1521513Sroot return; 15332638Sbostic *cp = '\0'; 15432638Sbostic offset = atoi(cp + 1); 1551513Sroot while (--utp >= utmp) 1561513Sroot if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name))) 15716587Ssam notify(utp, offset); 1581513Sroot } 1591513Sroot 16032638Sbostic static char *cr; 1611513Sroot 1621513Sroot notify(utp, offset) 1631513Sroot register struct utmp *utp; 16433824Sbostic off_t offset; 1651513Sroot { 16632646Sbostic static char tty[20] = "/dev/"; 16732646Sbostic struct sgttyb gttybuf; 16817189Sralph FILE *tp; 16932646Sbostic char name[sizeof (utmp[0].ut_name) + 1]; 1701513Sroot struct stat stb; 1711513Sroot 17232638Sbostic (void)strncpy(tty + 5, utp->ut_line, sizeof(utp->ut_line)); 17332638Sbostic if (stat(tty, &stb) || !(stb.st_mode & S_IEXEC)) { 17432646Sbostic dsyslog(LOG_DEBUG, "%s: wrong mode on %s", utp->ut_name, tty); 1751513Sroot return; 1761513Sroot } 17732646Sbostic dsyslog(LOG_DEBUG, "notify %s on %s\n", utp->ut_name, tty); 17817189Sralph if (fork()) 17916587Ssam return; 18032638Sbostic (void)signal(SIGALRM, SIG_DFL); 18132638Sbostic (void)alarm((u_int)30); 18232638Sbostic if ((tp = fopen(tty, "w")) == NULL) { 18332646Sbostic dsyslog(LOG_ERR, "fopen of tty %s failed", tty); 18432646Sbostic _exit(-1); 1851513Sroot } 18632638Sbostic (void)ioctl(fileno(tp), TIOCGETP, >tybuf); 18724523Sbloom cr = (gttybuf.sg_flags&CRMOD) && !(gttybuf.sg_flags&RAW) ? "" : "\r"; 18832638Sbostic (void)strncpy(name, utp->ut_name, sizeof (utp->ut_name)); 18916587Ssam name[sizeof (name) - 1] = '\0'; 19032638Sbostic fprintf(tp, "%s\n\007New mail for %s@%.*s\007 has arrived:%s\n----%s\n", 19132638Sbostic cr, name, sizeof (hostname), hostname, cr, cr); 19217189Sralph jkfprintf(tp, name, offset); 19332646Sbostic fclose(tp); 19432646Sbostic _exit(0); 1951513Sroot } 1961513Sroot 19717189Sralph jkfprintf(tp, name, offset) 19817189Sralph register FILE *tp; 19932638Sbostic char name[]; 20033824Sbostic off_t offset; 2011513Sroot { 20232638Sbostic register char *cp; 2031513Sroot register FILE *fi; 20432638Sbostic register int linecnt, charcnt, inheader; 20512746Ssam char line[BUFSIZ]; 20632638Sbostic off_t fseek(); 2071513Sroot 20832646Sbostic if ((fi = fopen(name, "r")) == NULL) 2091513Sroot return; 21033824Sbostic (void)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) { 22032638Sbostic if (inheader) { 22132646Sbostic if (line[0] == '\n') { 22232646Sbostic inheader = 0; 22332638Sbostic continue; 22432646Sbostic } 22532646Sbostic if (line[0] == ' ' || line[0] == '\t' || 22632646Sbostic strncmp(line, "From:", 5) && 22732638Sbostic strncmp(line, "Subject:", 8)) 22832638Sbostic continue; 22932638Sbostic } 23032638Sbostic if (cp = index(line, '\n')) 23112746Ssam *cp = '\0'; 23232638Sbostic fprintf(tp, "%s%s\n", line, cr); 23332646Sbostic charcnt -= strlen(line); 23432646Sbostic if (--linecnt <= 0 || charcnt <= 0) { 23532638Sbostic fprintf(tp, "...more...%s\n", cr); 23632638Sbostic return; 23732638Sbostic } 2381513Sroot } 23932638Sbostic fprintf(tp, "----%s\n", cr); 2401513Sroot } 241