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*54200Sbostic static char sccsid[] = "@(#)comsat.c 5.25 (Berkeley) 06/22/92"; 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 26*54200Sbostic #include <signal.h> 271513Sroot #include <sgtty.h> 281513Sroot #include <utmp.h> 296394Sroot #include <errno.h> 309289Ssam #include <netdb.h> 3116808Sralph #include <syslog.h> 32*54200Sbostic #include <stdio.h> 33*54200Sbostic #include <unistd.h> 34*54200Sbostic #include <stdlib.h> 3543859Sbostic #include <ctype.h> 3642032Sbostic #include <string.h> 3743859Sbostic #include <paths.h> 381513Sroot 3912746Ssam int debug = 0; 4032638Sbostic #define dsyslog if (debug) syslog 411513Sroot 4232638Sbostic #define MAXIDLE 120 436394Sroot 4432638Sbostic char hostname[MAXHOSTNAMELEN]; 4522545Sbloom struct utmp *utmp = NULL; 46*54200Sbostic time_t lastmsgtime; 4732638Sbostic int nutmp, uf; 481513Sroot 49*54200Sbostic void jkfprintf __P((FILE *, char[], off_t)); 50*54200Sbostic void mailfor __P((char *)); 51*54200Sbostic void notify __P((struct utmp *, off_t)); 52*54200Sbostic void onalrm __P((int)); 53*54200Sbostic void reapchildren __P((int)); 54*54200Sbostic 55*54200Sbostic int 561513Sroot main(argc, argv) 5716367Skarels int argc; 58*54200Sbostic char *argv[]; 591513Sroot { 60*54200Sbostic struct sockaddr_in from; 6116367Skarels register int cc; 62*54200Sbostic int fromlen; 6316367Skarels char msgbuf[100]; 641513Sroot 6516367Skarels /* verify proper invocation */ 6641506Sbostic fromlen = sizeof(from); 6746668Sbostic if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0) { 6841506Sbostic (void)fprintf(stderr, 6941506Sbostic "comsat: getsockname: %s.\n", strerror(errno)); 7032646Sbostic exit(1); 7116367Skarels } 7232008Smarc openlog("comsat", LOG_PID, LOG_DAEMON); 7343860Sbostic if (chdir(_PATH_MAILDIR)) { 7443860Sbostic syslog(LOG_ERR, "chdir: %s: %m", _PATH_MAILDIR); 7532638Sbostic exit(1); 7632638Sbostic } 7737257Sbostic if ((uf = open(_PATH_UTMP, O_RDONLY, 0)) < 0) { 7837257Sbostic syslog(LOG_ERR, ".main: %s: %m", _PATH_UTMP); 7941531Sbostic (void) recv(0, msgbuf, sizeof(msgbuf) - 1, 0); 809289Ssam exit(1); 819289Ssam } 8232638Sbostic (void)time(&lastmsgtime); 8341531Sbostic (void)gethostname(hostname, sizeof(hostname)); 84*54200Sbostic onalrm(0); 8532638Sbostic (void)signal(SIGALRM, onalrm); 8632638Sbostic (void)signal(SIGTTOU, SIG_IGN); 8732638Sbostic (void)signal(SIGCHLD, reapchildren); 886394Sroot for (;;) { 8941531Sbostic cc = recv(0, msgbuf, sizeof(msgbuf) - 1, 0); 906394Sroot if (cc <= 0) { 916394Sroot if (errno != EINTR) 926394Sroot sleep(1); 936394Sroot errno = 0; 946394Sroot continue; 951513Sroot } 9632638Sbostic if (!nutmp) /* no one has logged in yet */ 9732638Sbostic continue; 9822596Sbloom sigblock(sigmask(SIGALRM)); 996394Sroot msgbuf[cc] = 0; 10032638Sbostic (void)time(&lastmsgtime); 1016394Sroot mailfor(msgbuf); 10232638Sbostic sigsetmask(0L); 1031513Sroot } 1041513Sroot } 1051513Sroot 10641506Sbostic void 107*54200Sbostic reapchildren(signo) 108*54200Sbostic int signo; 10916587Ssam { 110*54200Sbostic while (wait3(NULL, WNOHANG, NULL) > 0); 11116587Ssam } 11216587Ssam 11341506Sbostic void 114*54200Sbostic onalrm(signo) 115*54200Sbostic int signo; 1161513Sroot { 11732638Sbostic static u_int utmpsize; /* last malloced size for utmp */ 11832638Sbostic static u_int utmpmtime; /* last modification time for utmp */ 1191513Sroot struct stat statbf; 1201513Sroot 121*54200Sbostic if (time(NULL) - lastmsgtime >= MAXIDLE) 12216808Sralph exit(0); 12332638Sbostic (void)alarm((u_int)15); 12432638Sbostic (void)fstat(uf, &statbf); 1251513Sroot if (statbf.st_mtime > utmpmtime) { 1261513Sroot utmpmtime = statbf.st_mtime; 12722545Sbloom if (statbf.st_size > utmpsize) { 12822545Sbloom utmpsize = statbf.st_size + 10 * sizeof(struct utmp); 129*54200Sbostic if ((utmp = realloc(utmp, utmpsize)) == NULL) { 130*54200Sbostic syslog(LOG_ERR, "%s", strerror(errno)); 13122545Sbloom exit(1); 13222545Sbloom } 13322545Sbloom } 134*54200Sbostic (void)lseek(uf, (off_t)0, L_SET); 13533824Sbostic nutmp = read(uf, utmp, (int)statbf.st_size)/sizeof(struct utmp); 13632638Sbostic } 1371513Sroot } 1381513Sroot 139*54200Sbostic void 1401513Sroot mailfor(name) 1411513Sroot char *name; 1421513Sroot { 1431513Sroot register struct utmp *utp = &utmp[nutmp]; 1441513Sroot register char *cp; 14541564Sleres off_t offset; 1461513Sroot 14732646Sbostic if (!(cp = index(name, '@'))) 1481513Sroot return; 14932638Sbostic *cp = '\0'; 15032638Sbostic offset = atoi(cp + 1); 1511513Sroot while (--utp >= utmp) 1521513Sroot if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name))) 15316587Ssam notify(utp, offset); 1541513Sroot } 1551513Sroot 15641506Sbostic static char *cr; 1571513Sroot 158*54200Sbostic void 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) { 181*54200Sbostic dsyslog(LOG_ERR, "%s: %s", tty, strerror(errno)); 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 196*54200Sbostic void 19717189Sralph jkfprintf(tp, name, offset) 19817189Sralph register FILE *tp; 19932638Sbostic char name[]; 20033824Sbostic off_t offset; 2011513Sroot { 20241506Sbostic register char *cp, ch; 2031513Sroot register FILE *fi; 20432638Sbostic register int linecnt, charcnt, inheader; 20512746Ssam char line[BUFSIZ]; 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