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 634777Sbostic * provided that the above copyright notice and this paragraph are 734777Sbostic * duplicated in all such forms and that any documentation, 834777Sbostic * advertising materials, and other materials related to such 934777Sbostic * distribution and use acknowledge that the software was developed 1034777Sbostic * by the University of California, Berkeley. The name of the 1134777Sbostic * University may not be used to endorse or promote products derived 1234777Sbostic * from this software without specific prior written permission. 1334777Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434777Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534777Sbostic * 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*37986Sbostic static char sccsid[] = "@(#)comsat.c 5.15 (Berkeley) 05/11/89"; 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 4537257Sbostic #include "pathnames.h" 4637257Sbostic 471513Sroot /* 481513Sroot * comsat 491513Sroot */ 5012746Ssam int debug = 0; 5132638Sbostic #define dsyslog if (debug) syslog 521513Sroot 5332638Sbostic #define MAXIDLE 120 546394Sroot 5532638Sbostic char hostname[MAXHOSTNAMELEN]; 5622545Sbloom struct utmp *utmp = NULL; 5732638Sbostic time_t lastmsgtime, time(); 5832638Sbostic int nutmp, uf; 591513Sroot 601513Sroot main(argc, argv) 6116367Skarels int argc; 6232638Sbostic char **argv; 631513Sroot { 6432638Sbostic extern int errno; 6516367Skarels register int cc; 6616367Skarels char msgbuf[100]; 6716367Skarels struct sockaddr_in from; 6832638Sbostic int fromlen, reapchildren(), onalrm(); 691513Sroot 7016367Skarels /* verify proper invocation */ 7116367Skarels fromlen = sizeof (from); 7216367Skarels if (getsockname(0, &from, &fromlen) < 0) { 7316367Skarels fprintf(stderr, "%s: ", argv[0]); 7416367Skarels perror("getsockname"); 7532646Sbostic exit(1); 7616367Skarels } 7732008Smarc openlog("comsat", LOG_PID, LOG_DAEMON); 7837257Sbostic if (chdir(_PATH_MAIL)) { 7937257Sbostic syslog(LOG_ERR, "chdir: %s: %m", _PATH_MAIL); 8032638Sbostic exit(1); 8132638Sbostic } 8237257Sbostic if ((uf = open(_PATH_UTMP, O_RDONLY, 0)) < 0) { 8337257Sbostic syslog(LOG_ERR, ".main: %s: %m", _PATH_UTMP); 8416367Skarels (void) recv(0, msgbuf, sizeof (msgbuf) - 1, 0); 859289Ssam exit(1); 869289Ssam } 8732638Sbostic (void)time(&lastmsgtime); 8832638Sbostic (void)gethostname(hostname, sizeof (hostname)); 891513Sroot onalrm(); 9032638Sbostic (void)signal(SIGALRM, onalrm); 9132638Sbostic (void)signal(SIGTTOU, SIG_IGN); 9232638Sbostic (void)signal(SIGCHLD, reapchildren); 936394Sroot for (;;) { 9416367Skarels cc = recv(0, msgbuf, sizeof (msgbuf) - 1, 0); 956394Sroot if (cc <= 0) { 966394Sroot if (errno != EINTR) 976394Sroot sleep(1); 986394Sroot errno = 0; 996394Sroot continue; 1001513Sroot } 10132638Sbostic if (!nutmp) /* no one has logged in yet */ 10232638Sbostic continue; 10322596Sbloom sigblock(sigmask(SIGALRM)); 1046394Sroot msgbuf[cc] = 0; 10532638Sbostic (void)time(&lastmsgtime); 1066394Sroot mailfor(msgbuf); 10732638Sbostic sigsetmask(0L); 1081513Sroot } 1091513Sroot } 1101513Sroot 11116587Ssam reapchildren() 11216587Ssam { 11333135Sbostic while (wait3((union wait *)NULL, WNOHANG, (struct rusage *)NULL) > 0); 11416587Ssam } 11516587Ssam 1161513Sroot onalrm() 1171513Sroot { 11832638Sbostic static u_int utmpsize; /* last malloced size for utmp */ 11932638Sbostic static u_int utmpmtime; /* last modification time for utmp */ 1201513Sroot struct stat statbf; 12132638Sbostic off_t lseek(); 12232638Sbostic char *malloc(), *realloc(); 1231513Sroot 12432638Sbostic if (time((time_t *)NULL) - lastmsgtime >= MAXIDLE) 12516808Sralph exit(0); 12632638Sbostic (void)alarm((u_int)15); 12732638Sbostic (void)fstat(uf, &statbf); 1281513Sroot if (statbf.st_mtime > utmpmtime) { 1291513Sroot utmpmtime = statbf.st_mtime; 13022545Sbloom if (statbf.st_size > utmpsize) { 13122545Sbloom utmpsize = statbf.st_size + 10 * sizeof(struct utmp); 13222545Sbloom if (utmp) 13332638Sbostic utmp = (struct utmp *)realloc((char *)utmp, utmpsize); 13422545Sbloom else 13522545Sbloom utmp = (struct utmp *)malloc(utmpsize); 13632638Sbostic if (!utmp) { 13732646Sbostic syslog(LOG_ERR, "malloc failed"); 13822545Sbloom exit(1); 13922545Sbloom } 14022545Sbloom } 14132638Sbostic (void)lseek(uf, 0L, L_SET); 14233824Sbostic nutmp = read(uf, utmp, (int)statbf.st_size)/sizeof(struct utmp); 14332638Sbostic } 1441513Sroot } 1451513Sroot 1461513Sroot mailfor(name) 1471513Sroot char *name; 1481513Sroot { 1491513Sroot register struct utmp *utp = &utmp[nutmp]; 1501513Sroot register char *cp; 15133824Sbostic off_t offset, atol(); 1521513Sroot 15332646Sbostic if (!(cp = index(name, '@'))) 1541513Sroot return; 15532638Sbostic *cp = '\0'; 15632638Sbostic offset = atoi(cp + 1); 1571513Sroot while (--utp >= utmp) 1581513Sroot if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name))) 15916587Ssam notify(utp, offset); 1601513Sroot } 1611513Sroot 16232638Sbostic static char *cr; 1631513Sroot 1641513Sroot notify(utp, offset) 1651513Sroot register struct utmp *utp; 16633824Sbostic off_t offset; 1671513Sroot { 168*37986Sbostic static char tty[20] = _PATH_DEV; 16932646Sbostic struct sgttyb gttybuf; 17017189Sralph FILE *tp; 17132646Sbostic char name[sizeof (utmp[0].ut_name) + 1]; 1721513Sroot struct stat stb; 1731513Sroot 17432638Sbostic (void)strncpy(tty + 5, utp->ut_line, sizeof(utp->ut_line)); 17532638Sbostic if (stat(tty, &stb) || !(stb.st_mode & S_IEXEC)) { 17632646Sbostic dsyslog(LOG_DEBUG, "%s: wrong mode on %s", utp->ut_name, tty); 1771513Sroot return; 1781513Sroot } 17932646Sbostic dsyslog(LOG_DEBUG, "notify %s on %s\n", utp->ut_name, tty); 18017189Sralph if (fork()) 18116587Ssam return; 18232638Sbostic (void)signal(SIGALRM, SIG_DFL); 18332638Sbostic (void)alarm((u_int)30); 18432638Sbostic if ((tp = fopen(tty, "w")) == NULL) { 18532646Sbostic dsyslog(LOG_ERR, "fopen of tty %s failed", tty); 18632646Sbostic _exit(-1); 1871513Sroot } 18832638Sbostic (void)ioctl(fileno(tp), TIOCGETP, >tybuf); 18924523Sbloom cr = (gttybuf.sg_flags&CRMOD) && !(gttybuf.sg_flags&RAW) ? "" : "\r"; 19032638Sbostic (void)strncpy(name, utp->ut_name, sizeof (utp->ut_name)); 19116587Ssam name[sizeof (name) - 1] = '\0'; 19232638Sbostic fprintf(tp, "%s\n\007New mail for %s@%.*s\007 has arrived:%s\n----%s\n", 19332638Sbostic cr, name, sizeof (hostname), hostname, cr, cr); 19417189Sralph jkfprintf(tp, name, offset); 19532646Sbostic fclose(tp); 19632646Sbostic _exit(0); 1971513Sroot } 1981513Sroot 19917189Sralph jkfprintf(tp, name, offset) 20017189Sralph register FILE *tp; 20132638Sbostic char name[]; 20233824Sbostic off_t offset; 2031513Sroot { 20432638Sbostic register char *cp; 2051513Sroot register FILE *fi; 20632638Sbostic register int linecnt, charcnt, inheader; 20712746Ssam char line[BUFSIZ]; 20832638Sbostic off_t fseek(); 2091513Sroot 21032646Sbostic if ((fi = fopen(name, "r")) == NULL) 2111513Sroot return; 21233824Sbostic (void)fseek(fi, offset, L_SET); 21312746Ssam /* 21412746Ssam * Print the first 7 lines or 560 characters of the new mail 21512746Ssam * (whichever comes first). Skip header crap other than 21613783Ssam * From, Subject, To, and Date. 21712746Ssam */ 2181513Sroot linecnt = 7; 2191513Sroot charcnt = 560; 22013783Ssam inheader = 1; 22112746Ssam while (fgets(line, sizeof (line), fi) != NULL) { 22232638Sbostic if (inheader) { 22332646Sbostic if (line[0] == '\n') { 22432646Sbostic inheader = 0; 22532638Sbostic continue; 22632646Sbostic } 22732646Sbostic if (line[0] == ' ' || line[0] == '\t' || 22832646Sbostic strncmp(line, "From:", 5) && 22932638Sbostic strncmp(line, "Subject:", 8)) 23032638Sbostic continue; 23132638Sbostic } 23235389Smckusick if (linecnt <= 0 || charcnt <= 0) { 23335389Smckusick fprintf(tp, "...more...%s\n", cr); 23435389Smckusick return; 23535389Smckusick } 23632638Sbostic if (cp = index(line, '\n')) 23712746Ssam *cp = '\0'; 23832638Sbostic fprintf(tp, "%s%s\n", line, cr); 23932646Sbostic charcnt -= strlen(line); 24035389Smckusick linecnt--; 2411513Sroot } 24232638Sbostic fprintf(tp, "----%s\n", cr); 2431513Sroot } 244