1: /* 2: * Copyright (c) 1980 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: char copyright[] = 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10: All rights reserved.\n"; 11: #endif not lint 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)comsat.c 5.5 (Berkeley) 10/24/85"; 15: #endif not lint 16: 17: #include <sys/types.h> 18: #include <sys/socket.h> 19: #include <sys/stat.h> 20: #include <sys/wait.h> 21: #include <sys/file.h> 22: 23: #include <netinet/in.h> 24: 25: #include <stdio.h> 26: #include <sgtty.h> 27: #include <utmp.h> 28: #include <signal.h> 29: #include <errno.h> 30: #include <netdb.h> 31: #include <syslog.h> 32: 33: /* 34: * comsat 35: */ 36: int debug = 0; 37: #define dprintf if (debug) printf 38: 39: struct sockaddr_in sin = { AF_INET }; 40: extern errno; 41: 42: char hostname[32]; 43: struct utmp *utmp = NULL; 44: int nutmp; 45: int uf; 46: unsigned utmpmtime = 0; /* last modification time for utmp */ 47: unsigned utmpsize = 0; /* last malloced size for utmp */ 48: int onalrm(); 49: int reapchildren(); 50: long lastmsgtime; 51: char *malloc(), *realloc(); 52: 53: #define MAXIDLE 120 54: #define NAMLEN (sizeof (uts[0].ut_name) + 1) 55: 56: main(argc, argv) 57: int argc; 58: char *argv[]; 59: { 60: register int cc; 61: char buf[BUFSIZ]; 62: char msgbuf[100]; 63: struct sockaddr_in from; 64: int fromlen; 65: 66: /* verify proper invocation */ 67: fromlen = sizeof (from); 68: if (getsockname(0, &from, &fromlen) < 0) { 69: fprintf(stderr, "%s: ", argv[0]); 70: perror("getsockname"); 71: _exit(1); 72: } 73: chdir("/usr/spool/mail"); 74: if ((uf = open("/etc/utmp",0)) < 0) { 75: openlog("comsat", 0, LOG_DAEMON); 76: syslog(LOG_ERR, "/etc/utmp: %m"); 77: (void) recv(0, msgbuf, sizeof (msgbuf) - 1, 0); 78: exit(1); 79: } 80: lastmsgtime = time(0); 81: gethostname(hostname, sizeof (hostname)); 82: onalrm(); 83: signal(SIGALRM, onalrm); 84: signal(SIGTTOU, SIG_IGN); 85: signal(SIGCHLD, reapchildren); 86: for (;;) { 87: cc = recv(0, msgbuf, sizeof (msgbuf) - 1, 0); 88: if (cc <= 0) { 89: if (errno != EINTR) 90: sleep(1); 91: errno = 0; 92: continue; 93: } 94: sigblock(sigmask(SIGALRM)); 95: msgbuf[cc] = 0; 96: lastmsgtime = time(0); 97: mailfor(msgbuf); 98: sigsetmask(0); 99: } 100: } 101: 102: reapchildren() 103: { 104: 105: while (wait3((struct wait *)0, WNOHANG, (struct rusage *)0) > 0) 106: ; 107: } 108: 109: onalrm() 110: { 111: struct stat statbf; 112: 113: if (time(0) - lastmsgtime >= MAXIDLE) 114: exit(0); 115: dprintf("alarm\n"); 116: alarm(15); 117: fstat(uf, &statbf); 118: if (statbf.st_mtime > utmpmtime) { 119: dprintf(" changed\n"); 120: utmpmtime = statbf.st_mtime; 121: if (statbf.st_size > utmpsize) { 122: utmpsize = statbf.st_size + 10 * sizeof(struct utmp); 123: if (utmp) 124: utmp = (struct utmp *)realloc(utmp, utmpsize); 125: else 126: utmp = (struct utmp *)malloc(utmpsize); 127: if (! utmp) { 128: dprintf("malloc failed\n"); 129: exit(1); 130: } 131: } 132: lseek(uf, 0, 0); 133: nutmp = read(uf,utmp,statbf.st_size)/sizeof(struct utmp); 134: } else 135: dprintf(" ok\n"); 136: } 137: 138: mailfor(name) 139: char *name; 140: { 141: register struct utmp *utp = &utmp[nutmp]; 142: register char *cp; 143: char *rindex(); 144: int offset; 145: 146: dprintf("mailfor %s\n", name); 147: cp = name; 148: while (*cp && *cp != '@') 149: cp++; 150: if (*cp == 0) { 151: dprintf("bad format\n"); 152: return; 153: } 154: *cp = 0; 155: offset = atoi(cp+1); 156: while (--utp >= utmp) 157: if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name))) 158: notify(utp, offset); 159: } 160: 161: char *cr; 162: 163: notify(utp, offset) 164: register struct utmp *utp; 165: { 166: FILE *tp; 167: struct sgttyb gttybuf; 168: char tty[20], name[sizeof (utmp[0].ut_name) + 1]; 169: struct stat stb; 170: 171: strcpy(tty, "/dev/"); 172: strncat(tty, utp->ut_line, sizeof(utp->ut_line)); 173: dprintf("notify %s on %s\n", utp->ut_name, tty); 174: if (stat(tty, &stb) == 0 && (stb.st_mode & 0100) == 0) { 175: dprintf("wrong mode\n"); 176: return; 177: } 178: if (fork()) 179: return; 180: signal(SIGALRM, SIG_DFL); 181: alarm(30); 182: if ((tp = fopen(tty,"w")) == 0) { 183: dprintf("fopen failed\n"); 184: exit(-1); 185: } 186: ioctl(fileno(tp), TIOCGETP, >tybuf); 187: cr = (gttybuf.sg_flags&CRMOD) && !(gttybuf.sg_flags&RAW) ? "" : "\r"; 188: strncpy(name, utp->ut_name, sizeof (utp->ut_name)); 189: name[sizeof (name) - 1] = '\0'; 190: fprintf(tp,"%s\n\007New mail for %s@%.*s\007 has arrived:%s\n", 191: cr, name, sizeof (hostname), hostname, cr); 192: fprintf(tp,"----%s\n", cr); 193: jkfprintf(tp, name, offset); 194: exit(0); 195: } 196: 197: jkfprintf(tp, name, offset) 198: register FILE *tp; 199: { 200: register FILE *fi; 201: register int linecnt, charcnt; 202: char line[BUFSIZ]; 203: int inheader; 204: 205: dprintf("HERE %s's mail starting at %d\n", 206: name, offset); 207: if ((fi = fopen(name,"r")) == NULL) { 208: dprintf("Cant read the mail\n"); 209: return; 210: } 211: fseek(fi, offset, L_SET); 212: /* 213: * Print the first 7 lines or 560 characters of the new mail 214: * (whichever comes first). Skip header crap other than 215: * From, Subject, To, and Date. 216: */ 217: linecnt = 7; 218: charcnt = 560; 219: inheader = 1; 220: while (fgets(line, sizeof (line), fi) != NULL) { 221: register char *cp; 222: char *index(); 223: int cnt; 224: 225: if (linecnt <= 0 || charcnt <= 0) { 226: fprintf(tp,"...more...%s\n", cr); 227: return; 228: } 229: if (strncmp(line, "From ", 5) == 0) 230: continue; 231: if (inheader && (line[0] == ' ' || line[0] == '\t')) 232: continue; 233: cp = index(line, ':'); 234: if (cp == 0 || (index(line, ' ') && index(line, ' ') < cp)) 235: inheader = 0; 236: else 237: cnt = cp - line; 238: if (inheader && 239: strncmp(line, "Date", cnt) && 240: strncmp(line, "From", cnt) && 241: strncmp(line, "Subject", cnt) && 242: strncmp(line, "To", cnt)) 243: continue; 244: cp = index(line, '\n'); 245: if (cp) 246: *cp = '\0'; 247: fprintf(tp,"%s%s\n", line, cr); 248: linecnt--, charcnt -= strlen(line); 249: } 250: fprintf(tp,"----%s\n", cr); 251: }