1 #ifndef lint 2 static char sccsid[] = "@(#)comsat.c 4.13 (Berkeley) 09/13/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 #include <syslog.h> 20 21 /* 22 * comsat 23 */ 24 int debug = 0; 25 #define dprintf if (debug) printf 26 27 #define MAXUTMP 100 /* down from init */ 28 29 struct sockaddr_in sin = { AF_INET }; 30 extern errno; 31 32 char hostname[32]; 33 struct utmp utmp[100]; 34 int nutmp; 35 int uf; 36 unsigned utmpmtime; /* last modification time for utmp */ 37 int onalrm(); 38 int reapchildren(); 39 long lastmsgtime; 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 struct utmp *utp; 101 102 if (time(0) - lastmsgtime >= MAXIDLE) 103 exit(0); 104 dprintf("alarm\n"); 105 alarm(15); 106 fstat(uf, &statbf); 107 if (statbf.st_mtime > utmpmtime) { 108 dprintf(" changed\n"); 109 utmpmtime = statbf.st_mtime; 110 lseek(uf, 0, 0); 111 nutmp = read(uf,utmp,sizeof(utmp))/sizeof(struct utmp); 112 } else 113 dprintf(" ok\n"); 114 } 115 116 mailfor(name) 117 char *name; 118 { 119 register struct utmp *utp = &utmp[nutmp]; 120 register char *cp; 121 char *rindex(); 122 int offset; 123 124 dprintf("mailfor %s\n", name); 125 cp = name; 126 while (*cp && *cp != '@') 127 cp++; 128 if (*cp == 0) { 129 dprintf("bad format\n"); 130 return; 131 } 132 *cp = 0; 133 offset = atoi(cp+1); 134 while (--utp >= utmp) 135 if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name))) 136 notify(utp, offset); 137 } 138 139 char *cr; 140 141 notify(utp, offset) 142 register struct utmp *utp; 143 { 144 FILE *tp; 145 struct sgttyb gttybuf; 146 char tty[20], name[sizeof (utmp[0].ut_name) + 1]; 147 struct stat stb; 148 149 strcpy(tty, "/dev/"); 150 strncat(tty, utp->ut_line, sizeof(utp->ut_line)); 151 dprintf("notify %s on %s\n", utp->ut_name, tty); 152 if (stat(tty, &stb) == 0 && (stb.st_mode & 0100) == 0) { 153 dprintf("wrong mode\n"); 154 return; 155 } 156 if (fork()) 157 return; 158 signal(SIGALRM, SIG_DFL); 159 alarm(30); 160 if ((tp = fopen(tty,"w")) == 0) { 161 dprintf("fopen failed\n"); 162 exit(-1); 163 } 164 ioctl(fileno(tp), TIOCGETP, >tybuf); 165 cr = (gttybuf.sg_flags & CRMOD) ? "" : "\r"; 166 strncpy(name, utp->ut_name, sizeof (utp->ut_name)); 167 name[sizeof (name) - 1] = '\0'; 168 fprintf(tp,"%s\n\007New mail for %s@%s\007 has arrived:%s\n", 169 cr, name, hostname, cr); 170 fprintf(tp,"----%s\n", cr); 171 jkfprintf(tp, name, offset); 172 exit(0); 173 } 174 175 jkfprintf(tp, name, offset) 176 register FILE *tp; 177 { 178 register FILE *fi; 179 register int linecnt, charcnt; 180 char line[BUFSIZ]; 181 int inheader; 182 183 dprintf("HERE %s's mail starting at %d\n", 184 name, offset); 185 if ((fi = fopen(name,"r")) == NULL) { 186 dprintf("Cant read the mail\n"); 187 return; 188 } 189 fseek(fi, offset, L_SET); 190 /* 191 * Print the first 7 lines or 560 characters of the new mail 192 * (whichever comes first). Skip header crap other than 193 * From, Subject, To, and Date. 194 */ 195 linecnt = 7; 196 charcnt = 560; 197 inheader = 1; 198 while (fgets(line, sizeof (line), fi) != NULL) { 199 register char *cp; 200 char *index(); 201 int cnt; 202 203 if (linecnt <= 0 || charcnt <= 0) { 204 fprintf(tp,"...more...%s\n", cr); 205 return; 206 } 207 if (strncmp(line, "From ", 5) == 0) 208 continue; 209 if (inheader && (line[0] == ' ' || line[0] == '\t')) 210 continue; 211 cp = index(line, ':'); 212 if (cp == 0 || (index(line, ' ') && index(line, ' ') < cp)) 213 inheader = 0; 214 else 215 cnt = cp - line; 216 if (inheader && 217 strncmp(line, "Date", cnt) && 218 strncmp(line, "From", cnt) && 219 strncmp(line, "Subject", cnt) && 220 strncmp(line, "To", cnt)) 221 continue; 222 cp = index(line, '\n'); 223 if (cp) 224 *cp = '\0'; 225 fprintf(tp,"%s%s\n", line, cr); 226 linecnt--, charcnt -= strlen(line); 227 } 228 fprintf(tp,"----%s\n", cr); 229 } 230