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