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