122550Sdist /* 222550Sdist * Copyright (c) 1980 Regents of the University of California. 332756Sbostic * All rights reserved. 432756Sbostic * 5*42663Sbostic * %sccs.include.redist.c% 622550Sdist */ 722550Sdist 89289Ssam #ifndef lint 922550Sdist char copyright[] = 1022550Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1122550Sdist All rights reserved.\n"; 1232756Sbostic #endif /* not lint */ 136394Sroot 1422550Sdist #ifndef lint 15*42663Sbostic static char sccsid[] = "@(#)comsat.c 5.20 (Berkeley) 06/01/90"; 1632756Sbostic #endif /* not lint */ 1722550Sdist 1832638Sbostic #include <sys/param.h> 199289Ssam #include <sys/socket.h> 2013549Ssam #include <sys/stat.h> 2132638Sbostic #include <sys/file.h> 2213549Ssam #include <sys/wait.h> 239289Ssam 249289Ssam #include <netinet/in.h> 259289Ssam 261513Sroot #include <stdio.h> 271513Sroot #include <sgtty.h> 281513Sroot #include <utmp.h> 291513Sroot #include <signal.h> 306394Sroot #include <errno.h> 319289Ssam #include <netdb.h> 3216808Sralph #include <syslog.h> 3342032Sbostic #include <string.h> 3441506Sbostic #include <ctype.h> 351513Sroot 3637257Sbostic #include "pathnames.h" 3737257Sbostic 381513Sroot /* 391513Sroot * comsat 401513Sroot */ 4112746Ssam int debug = 0; 4232638Sbostic #define dsyslog if (debug) syslog 431513Sroot 4432638Sbostic #define MAXIDLE 120 456394Sroot 4632638Sbostic char hostname[MAXHOSTNAMELEN]; 4722545Sbloom struct utmp *utmp = NULL; 4832638Sbostic time_t lastmsgtime, time(); 4932638Sbostic int nutmp, uf; 501513Sroot 5141506Sbostic /* ARGSUSED */ 521513Sroot main(argc, argv) 5316367Skarels int argc; 5432638Sbostic char **argv; 551513Sroot { 5632638Sbostic extern int errno; 5716367Skarels register int cc; 5816367Skarels char msgbuf[100]; 5916367Skarels struct sockaddr_in from; 6041506Sbostic int fromlen; 6141506Sbostic void onalrm(), reapchildren(); 621513Sroot 6316367Skarels /* verify proper invocation */ 6441506Sbostic fromlen = sizeof(from); 6516367Skarels if (getsockname(0, &from, &fromlen) < 0) { 6641506Sbostic (void)fprintf(stderr, 6741506Sbostic "comsat: getsockname: %s.\n", strerror(errno)); 6832646Sbostic exit(1); 6916367Skarels } 7032008Smarc openlog("comsat", LOG_PID, LOG_DAEMON); 7137257Sbostic if (chdir(_PATH_MAIL)) { 7237257Sbostic syslog(LOG_ERR, "chdir: %s: %m", _PATH_MAIL); 7332638Sbostic exit(1); 7432638Sbostic } 7537257Sbostic if ((uf = open(_PATH_UTMP, O_RDONLY, 0)) < 0) { 7637257Sbostic syslog(LOG_ERR, ".main: %s: %m", _PATH_UTMP); 7741531Sbostic (void) recv(0, msgbuf, sizeof(msgbuf) - 1, 0); 789289Ssam exit(1); 799289Ssam } 8032638Sbostic (void)time(&lastmsgtime); 8141531Sbostic (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 (;;) { 8741531Sbostic 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 10441506Sbostic void 10516587Ssam reapchildren() 10616587Ssam { 10733135Sbostic while (wait3((union wait *)NULL, WNOHANG, (struct rusage *)NULL) > 0); 10816587Ssam } 10916587Ssam 11041506Sbostic void 1111513Sroot onalrm() 1121513Sroot { 11332638Sbostic static u_int utmpsize; /* last malloced size for utmp */ 11432638Sbostic static u_int utmpmtime; /* last modification time for utmp */ 1151513Sroot struct stat statbf; 11632638Sbostic off_t lseek(); 11732638Sbostic char *malloc(), *realloc(); 1181513Sroot 11932638Sbostic if (time((time_t *)NULL) - lastmsgtime >= MAXIDLE) 12016808Sralph exit(0); 12132638Sbostic (void)alarm((u_int)15); 12232638Sbostic (void)fstat(uf, &statbf); 1231513Sroot if (statbf.st_mtime > utmpmtime) { 1241513Sroot utmpmtime = statbf.st_mtime; 12522545Sbloom if (statbf.st_size > utmpsize) { 12622545Sbloom utmpsize = statbf.st_size + 10 * sizeof(struct utmp); 12722545Sbloom if (utmp) 12832638Sbostic utmp = (struct utmp *)realloc((char *)utmp, utmpsize); 12922545Sbloom else 13022545Sbloom utmp = (struct utmp *)malloc(utmpsize); 13132638Sbostic if (!utmp) { 13232646Sbostic syslog(LOG_ERR, "malloc failed"); 13322545Sbloom exit(1); 13422545Sbloom } 13522545Sbloom } 13632638Sbostic (void)lseek(uf, 0L, L_SET); 13733824Sbostic nutmp = read(uf, utmp, (int)statbf.st_size)/sizeof(struct utmp); 13832638Sbostic } 1391513Sroot } 1401513Sroot 1411513Sroot mailfor(name) 1421513Sroot char *name; 1431513Sroot { 1441513Sroot register struct utmp *utp = &utmp[nutmp]; 1451513Sroot register char *cp; 14641564Sleres off_t offset; 1471513Sroot 14832646Sbostic if (!(cp = index(name, '@'))) 1491513Sroot return; 15032638Sbostic *cp = '\0'; 15132638Sbostic offset = atoi(cp + 1); 1521513Sroot while (--utp >= utmp) 1531513Sroot if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name))) 15416587Ssam notify(utp, offset); 1551513Sroot } 1561513Sroot 15741506Sbostic static char *cr; 1581513Sroot 1591513Sroot notify(utp, offset) 1601513Sroot register struct utmp *utp; 16133824Sbostic off_t offset; 1621513Sroot { 16337986Sbostic static char tty[20] = _PATH_DEV; 16432646Sbostic struct sgttyb gttybuf; 16541531Sbostic struct stat stb; 16617189Sralph FILE *tp; 16741531Sbostic char name[sizeof(utmp[0].ut_name) + 1]; 1681513Sroot 16941531Sbostic (void)strncpy(tty + sizeof(_PATH_DEV) - 1, utp->ut_line, 17041531Sbostic sizeof(utp->ut_line)); 17132638Sbostic if (stat(tty, &stb) || !(stb.st_mode & S_IEXEC)) { 17232646Sbostic dsyslog(LOG_DEBUG, "%s: wrong mode on %s", utp->ut_name, tty); 1731513Sroot return; 1741513Sroot } 17532646Sbostic dsyslog(LOG_DEBUG, "notify %s on %s\n", utp->ut_name, tty); 17617189Sralph if (fork()) 17716587Ssam return; 17832638Sbostic (void)signal(SIGALRM, SIG_DFL); 17932638Sbostic (void)alarm((u_int)30); 18032638Sbostic if ((tp = fopen(tty, "w")) == NULL) { 18132646Sbostic dsyslog(LOG_ERR, "fopen of tty %s failed", tty); 18232646Sbostic _exit(-1); 1831513Sroot } 18432638Sbostic (void)ioctl(fileno(tp), TIOCGETP, >tybuf); 18541506Sbostic cr = (gttybuf.sg_flags&CRMOD) && !(gttybuf.sg_flags&RAW) ? 18641506Sbostic "\n" : "\n\r"; 18741531Sbostic (void)strncpy(name, utp->ut_name, sizeof(utp->ut_name)); 18841531Sbostic name[sizeof(name) - 1] = '\0'; 18941506Sbostic (void)fprintf(tp, "%s\007New mail for %s@%.*s\007 has arrived:%s----%s", 19041506Sbostic cr, name, sizeof(hostname), hostname, cr, cr); 19117189Sralph jkfprintf(tp, name, offset); 19241506Sbostic (void)fclose(tp); 19332646Sbostic _exit(0); 1941513Sroot } 1951513Sroot 19617189Sralph jkfprintf(tp, name, offset) 19717189Sralph register FILE *tp; 19832638Sbostic char name[]; 19933824Sbostic off_t offset; 2001513Sroot { 20141506Sbostic register char *cp, ch; 2021513Sroot register FILE *fi; 20332638Sbostic register int linecnt, charcnt, inheader; 20412746Ssam char line[BUFSIZ]; 20532638Sbostic off_t fseek(); 2061513Sroot 20732646Sbostic if ((fi = fopen(name, "r")) == NULL) 2081513Sroot return; 20933824Sbostic (void)fseek(fi, offset, L_SET); 21041564Sleres /* 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; 21841531Sbostic while (fgets(line, sizeof(line), fi) != NULL) { 21932638Sbostic if (inheader) { 22032646Sbostic if (line[0] == '\n') { 22132646Sbostic inheader = 0; 22232638Sbostic continue; 22332646Sbostic } 22432646Sbostic if (line[0] == ' ' || line[0] == '\t' || 22532646Sbostic strncmp(line, "From:", 5) && 22632638Sbostic strncmp(line, "Subject:", 8)) 22732638Sbostic continue; 22832638Sbostic } 22935389Smckusick if (linecnt <= 0 || charcnt <= 0) { 23041506Sbostic (void)fprintf(tp, "...more...%s", cr); 23135389Smckusick return; 23235389Smckusick } 23341506Sbostic /* strip weird stuff so can't trojan horse stupid terminals */ 23441506Sbostic for (cp = line; (ch = *cp) && ch != '\n'; ++cp, --charcnt) { 23541564Sleres ch = toascii(ch); 23641506Sbostic if (!isprint(ch) && !isspace(ch)) 23741506Sbostic ch |= 0x40; 23841506Sbostic (void)fputc(ch, tp); 23941506Sbostic } 24041506Sbostic (void)fputs(cr, tp); 24141506Sbostic --linecnt; 2421513Sroot } 24341506Sbostic (void)fprintf(tp, "----%s\n", cr); 2441513Sroot } 245