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