1 #ifndef lint 2 static char *sccsid = "@(#)comsat.c 4.6 83/05/27"; 3 #endif 4 5 #include <sys/types.h> 6 #include <sys/socket.h> 7 8 #include <netinet/in.h> 9 10 #include <stdio.h> 11 #include <sgtty.h> 12 #include <utmp.h> 13 #include <stat.h> 14 #include <wait.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 if (!debug) 58 while (fork()) 59 wait(0); 60 sleep(10); 61 onalrm(); 62 sigset(SIGALRM, onalrm); 63 sigignore(SIGTTOU); 64 s = socket(AF_INET, SOCK_DGRAM, 0, 0); 65 if (s < 0) { 66 perror("socket"); 67 exit(1); 68 } 69 sin.sin_port = sp->s_port; 70 if (bind(s, &sin, sizeof (sin), 0) < 0) { 71 perror("bind"); 72 exit(1); 73 } 74 for (;;) { 75 char msgbuf[100]; 76 int cc; 77 78 cc = recv(s, msgbuf, sizeof (msgbuf) - 1, 0); 79 if (cc <= 0) { 80 if (errno != EINTR) 81 sleep(1); 82 errno = 0; 83 continue; 84 } 85 msgbuf[cc] = 0; 86 mailfor(msgbuf); 87 } 88 } 89 90 onalrm() 91 { 92 struct stat statbf; 93 struct utmp *utp; 94 95 dprintf("alarm\n"); 96 alarm(15); 97 fstat(uf,&statbf); 98 if (statbf.st_mtime > utmpmtime) { 99 dprintf(" changed\n"); 100 utmpmtime = statbf.st_mtime; 101 lseek(uf, 0, 0); 102 nutmp = read(uf,utmp,sizeof(utmp))/sizeof(struct utmp); 103 } else 104 dprintf(" ok\n"); 105 } 106 107 mailfor(name) 108 char *name; 109 { 110 register struct utmp *utp = &utmp[nutmp]; 111 register char *cp; 112 char *rindex(); 113 int offset; 114 115 dprintf("mailfor %s\n", name); 116 cp = name; 117 while (*cp && *cp != '@') 118 cp++; 119 if (*cp == 0) { 120 dprintf("bad format\n"); 121 return; 122 } 123 *cp = 0; 124 offset = atoi(cp+1); 125 while (--utp >= utmp) 126 if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name))) 127 if (fork() == 0) { 128 signal(SIGALRM, SIG_DFL); 129 alarm(30); 130 notify(utp, offset), exit(0); 131 } else 132 while (wait3(0, WNOHANG, 0) > 0) 133 continue; 134 } 135 136 char *cr; 137 138 notify(utp, offset) 139 register struct utmp *utp; 140 { 141 FILE *tp; 142 struct sgttyb gttybuf; 143 char tty[20], hostname[32]; 144 char 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 ((tp = fopen(tty,"w")) == 0) { 155 dprintf("fopen failed\n"); 156 return; 157 } 158 ioctl(fileno(tp), TIOCGETP, >tybuf); 159 cr = (gttybuf.sg_flags & CRMOD) ? "" : "\r"; 160 gethostname(hostname, sizeof (hostname)); 161 strncpy(name, utp->ut_name, sizeof (utp->ut_name)); 162 name[sizeof (name) - 1] = 0; 163 fprintf(tp,"%s\n\007New mail for %s@%s\007 has arrived:%s\n", 164 cr, name, hostname, cr); 165 fprintf(tp,"----%s\n", cr); 166 jkfprintf(tp, name, offset); 167 fclose(tp); 168 } 169 170 jkfprintf(tp, name, offset) 171 register FILE *tp; 172 { 173 register FILE *fi; 174 register int linecnt, charcnt; 175 char line[BUFSIZ]; 176 177 dprintf("HERE %s's mail starting at %d\n", 178 name, offset); 179 if ((fi = fopen(name,"r")) == NULL) { 180 dprintf("Cant read the mail\n"); 181 return; 182 } 183 fseek(fi, offset, 0); 184 /* 185 * Print the first 7 lines or 560 characters of the new mail 186 * (whichever comes first). Skip header crap other than 187 * From: and Subject:. 188 */ 189 linecnt = 7; 190 charcnt = 560; 191 while (fgets(line, sizeof (line), fi) != NULL) { 192 register char *cp; 193 char *index(); 194 195 if (linecnt <= 0 || charcnt <= 0) { 196 fprintf(tp,"...more...%s\n", cr); 197 break; 198 } 199 cp = index(line, ':'); 200 if (cp && 201 strncmp(line, "Date", cp - line) && 202 strncmp(line, "From", cp - line) && 203 strncmp(line, "Subject", cp - line) && 204 strncmp(line, "To", cp - line)) 205 continue; 206 cp = index(line, '\n'); 207 if (cp) 208 *cp = '\0'; 209 fprintf(tp,"%s%s\n", line, cr); 210 linecnt--, charcnt -= strlen(line); 211 } 212 fprintf(tp,"----%s\n", cr); 213 } 214