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