122550Sdist /* 222550Sdist * Copyright (c) 1980 Regents of the University of California. 332756Sbostic * All rights reserved. 432756Sbostic * 542663Sbostic * %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*46668Sbostic static char sccsid[] = "@(#)comsat.c 5.24 (Berkeley) 02/25/91"; 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> 3343859Sbostic #include <ctype.h> 3442032Sbostic #include <string.h> 3543859Sbostic #include <paths.h> 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 4741506Sbostic /* ARGSUSED */ 481513Sroot main(argc, argv) 4916367Skarels int argc; 5032638Sbostic char **argv; 511513Sroot { 5232638Sbostic extern int errno; 5316367Skarels register int cc; 5416367Skarels char msgbuf[100]; 5516367Skarels struct sockaddr_in from; 5641506Sbostic int fromlen; 5741506Sbostic void onalrm(), reapchildren(); 581513Sroot 5916367Skarels /* verify proper invocation */ 6041506Sbostic fromlen = sizeof(from); 61*46668Sbostic if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0) { 6241506Sbostic (void)fprintf(stderr, 6341506Sbostic "comsat: getsockname: %s.\n", strerror(errno)); 6432646Sbostic exit(1); 6516367Skarels } 6632008Smarc openlog("comsat", LOG_PID, LOG_DAEMON); 6743860Sbostic if (chdir(_PATH_MAILDIR)) { 6843860Sbostic syslog(LOG_ERR, "chdir: %s: %m", _PATH_MAILDIR); 6932638Sbostic exit(1); 7032638Sbostic } 7137257Sbostic if ((uf = open(_PATH_UTMP, O_RDONLY, 0)) < 0) { 7237257Sbostic syslog(LOG_ERR, ".main: %s: %m", _PATH_UTMP); 7341531Sbostic (void) recv(0, msgbuf, sizeof(msgbuf) - 1, 0); 749289Ssam exit(1); 759289Ssam } 7632638Sbostic (void)time(&lastmsgtime); 7741531Sbostic (void)gethostname(hostname, sizeof(hostname)); 781513Sroot onalrm(); 7932638Sbostic (void)signal(SIGALRM, onalrm); 8032638Sbostic (void)signal(SIGTTOU, SIG_IGN); 8132638Sbostic (void)signal(SIGCHLD, reapchildren); 826394Sroot for (;;) { 8341531Sbostic cc = recv(0, msgbuf, sizeof(msgbuf) - 1, 0); 846394Sroot if (cc <= 0) { 856394Sroot if (errno != EINTR) 866394Sroot sleep(1); 876394Sroot errno = 0; 886394Sroot continue; 891513Sroot } 9032638Sbostic if (!nutmp) /* no one has logged in yet */ 9132638Sbostic continue; 9222596Sbloom sigblock(sigmask(SIGALRM)); 936394Sroot msgbuf[cc] = 0; 9432638Sbostic (void)time(&lastmsgtime); 956394Sroot mailfor(msgbuf); 9632638Sbostic sigsetmask(0L); 971513Sroot } 981513Sroot } 991513Sroot 10041506Sbostic void 10116587Ssam reapchildren() 10216587Ssam { 103*46668Sbostic while (wait3((int *)NULL, WNOHANG, (struct rusage *)NULL) > 0); 10416587Ssam } 10516587Ssam 10641506Sbostic void 1071513Sroot onalrm() 1081513Sroot { 10932638Sbostic static u_int utmpsize; /* last malloced size for utmp */ 11032638Sbostic static u_int utmpmtime; /* last modification time for utmp */ 1111513Sroot struct stat statbf; 11232638Sbostic off_t lseek(); 11332638Sbostic char *malloc(), *realloc(); 1141513Sroot 11532638Sbostic if (time((time_t *)NULL) - lastmsgtime >= MAXIDLE) 11616808Sralph exit(0); 11732638Sbostic (void)alarm((u_int)15); 11832638Sbostic (void)fstat(uf, &statbf); 1191513Sroot if (statbf.st_mtime > utmpmtime) { 1201513Sroot utmpmtime = statbf.st_mtime; 12122545Sbloom if (statbf.st_size > utmpsize) { 12222545Sbloom utmpsize = statbf.st_size + 10 * sizeof(struct utmp); 12322545Sbloom if (utmp) 12432638Sbostic utmp = (struct utmp *)realloc((char *)utmp, utmpsize); 12522545Sbloom else 12622545Sbloom utmp = (struct utmp *)malloc(utmpsize); 12732638Sbostic if (!utmp) { 12832646Sbostic syslog(LOG_ERR, "malloc failed"); 12922545Sbloom exit(1); 13022545Sbloom } 13122545Sbloom } 13232638Sbostic (void)lseek(uf, 0L, L_SET); 13333824Sbostic nutmp = read(uf, utmp, (int)statbf.st_size)/sizeof(struct utmp); 13432638Sbostic } 1351513Sroot } 1361513Sroot 1371513Sroot mailfor(name) 1381513Sroot char *name; 1391513Sroot { 1401513Sroot register struct utmp *utp = &utmp[nutmp]; 1411513Sroot register char *cp; 14241564Sleres off_t offset; 1431513Sroot 14432646Sbostic if (!(cp = index(name, '@'))) 1451513Sroot return; 14632638Sbostic *cp = '\0'; 14732638Sbostic offset = atoi(cp + 1); 1481513Sroot while (--utp >= utmp) 1491513Sroot if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name))) 15016587Ssam notify(utp, offset); 1511513Sroot } 1521513Sroot 15341506Sbostic static char *cr; 1541513Sroot 1551513Sroot notify(utp, offset) 1561513Sroot register struct utmp *utp; 15733824Sbostic off_t offset; 1581513Sroot { 15937986Sbostic static char tty[20] = _PATH_DEV; 16032646Sbostic struct sgttyb gttybuf; 16141531Sbostic struct stat stb; 16217189Sralph FILE *tp; 16341531Sbostic char name[sizeof(utmp[0].ut_name) + 1]; 1641513Sroot 16541531Sbostic (void)strncpy(tty + sizeof(_PATH_DEV) - 1, utp->ut_line, 16641531Sbostic sizeof(utp->ut_line)); 16732638Sbostic if (stat(tty, &stb) || !(stb.st_mode & S_IEXEC)) { 16832646Sbostic dsyslog(LOG_DEBUG, "%s: wrong mode on %s", utp->ut_name, tty); 1691513Sroot return; 1701513Sroot } 17132646Sbostic dsyslog(LOG_DEBUG, "notify %s on %s\n", utp->ut_name, tty); 17217189Sralph if (fork()) 17316587Ssam return; 17432638Sbostic (void)signal(SIGALRM, SIG_DFL); 17532638Sbostic (void)alarm((u_int)30); 17632638Sbostic if ((tp = fopen(tty, "w")) == NULL) { 17732646Sbostic dsyslog(LOG_ERR, "fopen of tty %s failed", tty); 17832646Sbostic _exit(-1); 1791513Sroot } 18032638Sbostic (void)ioctl(fileno(tp), TIOCGETP, >tybuf); 18141506Sbostic cr = (gttybuf.sg_flags&CRMOD) && !(gttybuf.sg_flags&RAW) ? 18241506Sbostic "\n" : "\n\r"; 18341531Sbostic (void)strncpy(name, utp->ut_name, sizeof(utp->ut_name)); 18441531Sbostic name[sizeof(name) - 1] = '\0'; 18541506Sbostic (void)fprintf(tp, "%s\007New mail for %s@%.*s\007 has arrived:%s----%s", 18641506Sbostic cr, name, sizeof(hostname), hostname, cr, cr); 18717189Sralph jkfprintf(tp, name, offset); 18841506Sbostic (void)fclose(tp); 18932646Sbostic _exit(0); 1901513Sroot } 1911513Sroot 19217189Sralph jkfprintf(tp, name, offset) 19317189Sralph register FILE *tp; 19432638Sbostic char name[]; 19533824Sbostic off_t offset; 1961513Sroot { 19741506Sbostic register char *cp, ch; 1981513Sroot register FILE *fi; 19932638Sbostic register int linecnt, charcnt, inheader; 20012746Ssam char line[BUFSIZ]; 2011513Sroot 20232646Sbostic if ((fi = fopen(name, "r")) == NULL) 2031513Sroot return; 20433824Sbostic (void)fseek(fi, offset, L_SET); 20541564Sleres /* 20612746Ssam * Print the first 7 lines or 560 characters of the new mail 20712746Ssam * (whichever comes first). Skip header crap other than 20813783Ssam * From, Subject, To, and Date. 20912746Ssam */ 2101513Sroot linecnt = 7; 2111513Sroot charcnt = 560; 21213783Ssam inheader = 1; 21341531Sbostic while (fgets(line, sizeof(line), fi) != NULL) { 21432638Sbostic if (inheader) { 21532646Sbostic if (line[0] == '\n') { 21632646Sbostic inheader = 0; 21732638Sbostic continue; 21832646Sbostic } 21932646Sbostic if (line[0] == ' ' || line[0] == '\t' || 22032646Sbostic strncmp(line, "From:", 5) && 22132638Sbostic strncmp(line, "Subject:", 8)) 22232638Sbostic continue; 22332638Sbostic } 22435389Smckusick if (linecnt <= 0 || charcnt <= 0) { 22541506Sbostic (void)fprintf(tp, "...more...%s", cr); 22635389Smckusick return; 22735389Smckusick } 22841506Sbostic /* strip weird stuff so can't trojan horse stupid terminals */ 22941506Sbostic for (cp = line; (ch = *cp) && ch != '\n'; ++cp, --charcnt) { 23041564Sleres ch = toascii(ch); 23141506Sbostic if (!isprint(ch) && !isspace(ch)) 23241506Sbostic ch |= 0x40; 23341506Sbostic (void)fputc(ch, tp); 23441506Sbostic } 23541506Sbostic (void)fputs(cr, tp); 23641506Sbostic --linecnt; 2371513Sroot } 23841506Sbostic (void)fprintf(tp, "----%s\n", cr); 2391513Sroot } 240