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