1 static char *sccsid = "@(#)comsat.c 4.2 (Berkeley) 10/20/80"; 2 #include <stdio.h> 3 #include <sys/mx.h> 4 #include <sgtty.h> 5 #include <utmp.h> 6 #include <sys/types.h> 7 #include <stat.h> 8 #include <wait.h> 9 #include <signal.h> 10 11 /* 12 * comsat 13 */ 14 #define dprintf if (0) printf 15 int xd; 16 17 struct ctp { 18 short ctrl; 19 short ctrlarg; 20 struct sgttyb ctrlv; 21 } ctp; 22 23 #define MAXUTMP 100 /* down from init */ 24 25 struct utmp utmp[100]; 26 int nutmp; 27 int uf; 28 unsigned utmpmtime; /* last modification time for utmp */ 29 int onalrm(); 30 31 #define NAMLEN (sizeof (uts[0].ut_name) + 1) 32 33 main(argc, argv) 34 char **argv; 35 { 36 register cc; 37 char buf[BUFSIZ]; 38 39 if (fork()) 40 exit(); 41 chdir("/usr/spool/mail"); 42 if((uf = open("/etc/utmp",0)) < 0) 43 perror("/etc/utmp"), exit(1); 44 while (fork()) 45 wait(0); 46 sleep(10); 47 onalrm(); 48 sigset(SIGALRM, onalrm); 49 sigignore(SIGTTOU); 50 unlink("/dev/mail"); 51 xd = mpx("/dev/mail", 0666); 52 if (xd < 0) { 53 close(2); 54 open("/dev/console", 1); 55 perror("/dev/mail"); 56 exit(1); 57 } 58 while((cc=read(xd, buf, BUFSIZ)) >= 0) { 59 dprintf("0: got %d bytes\n", cc); 60 unpack(buf, cc); 61 } 62 _exit(1); 63 } 64 65 #define skip(rp, c) ((struct rh *)(((char *)rp)+c)) 66 67 unpack(rp, cc) 68 register struct rh *rp; 69 { 70 register struct rh *end; 71 int i; 72 73 i = 0; 74 end = skip(rp, cc); 75 while (rp < end) { 76 dprintf("%d: ", ++i); 77 if (rp->count==0) { 78 dprintf("%d byte control message\n", rp->ccount); 79 control(rp->index, rp+1, rp->ccount); 80 } else { 81 dprintf("%*.*s\n", rp->count, rp->count, rp+1); 82 sighold(SIGALRM); 83 mailfor(rp+1); 84 sigrelse(SIGALRM); 85 } 86 rp->count += rp->ccount; 87 if (rp->count & 1) 88 rp->count++; 89 rp = skip(rp, rp->count); 90 rp++; 91 } 92 } 93 94 control(x, cb, cc) 95 register char *cb; 96 { 97 register char *end; 98 int cmd; 99 short *sp; 100 struct wh or; 101 102 end = cb + cc; 103 cmd = *cb++; 104 sp = (short *)cb+1; 105 switch (cmd) { 106 107 case M_WATCH: 108 dprintf("attach %x, uid %d\n", x, *sp); 109 attach(x, xd); 110 break; 111 112 case M_CLOSE: 113 sp = (short *)cb; 114 dprintf("detach %x, uid %d\n", x, *sp); 115 detach(x, xd); 116 break; 117 118 case M_IOCTL: 119 dprintf("ioctl %x\n", x); 120 or.index = x; 121 or.count = 0; 122 or.ccount = sizeof ctp; 123 or.data = (char *) &ctp.ctrlarg; 124 ctp.ctrlarg = M_IOANS; 125 write(xd, &or, sizeof or); 126 break; 127 128 default: 129 dprintf("unknown command %d\n", cmd); 130 return; 131 } 132 } 133 134 onalrm() 135 { 136 struct stat statbf; 137 struct utmp *utp; 138 139 dprintf("alarm\n"); 140 alarm(15); 141 fstat(uf,&statbf); 142 if (statbf.st_mtime > utmpmtime) { 143 dprintf(" changed\n"); 144 utmpmtime = statbf.st_mtime; 145 lseek(uf, 0, 0); 146 nutmp = read(uf,utmp,sizeof(utmp))/sizeof(struct utmp); 147 } else 148 dprintf(" ok\n"); 149 } 150 151 mailfor(name) 152 char *name; 153 { 154 register struct utmp *utp = &utmp[nutmp]; 155 register char *cp; 156 char *rindex(); 157 int offset; 158 159 dprintf("mailfor %s\n", name); 160 cp = name; 161 while (*cp && *cp != '@') 162 cp++; 163 if (*cp == 0) { 164 dprintf("bad format\n"); 165 return; 166 } 167 *cp = 0; 168 offset = atoi(cp+1); 169 while (--utp >= utmp) 170 if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name))) 171 if (fork() == 0) { 172 signal(SIGALRM, SIG_DFL); 173 alarm(30); 174 notify(utp, offset), exit(0); 175 } else 176 while (wait3(0, WNOHANG, 0) > 0) 177 continue; 178 } 179 180 char *cr; 181 182 notify(utp, offset) 183 register struct utmp *utp; 184 { 185 FILE *tp; 186 struct sgttyb gttybuf; 187 char tty[20]; 188 char name[sizeof (utmp[0].ut_name) + 1]; 189 struct stat stb; 190 191 strcpy(tty, "/dev/"); 192 strncat(tty, utp->ut_line, sizeof(utp->ut_line)); 193 dprintf("notify %s on %s\n", utp->ut_name, tty); 194 if (stat(tty, &stb) == 0 && (stb.st_mode & 0100) == 0) { 195 dprintf("wrong mode\n"); 196 return; 197 } 198 if ((tp = fopen(tty,"w")) == 0) { 199 dprintf("fopen failed\n"); 200 return; 201 } 202 gtty(fileno(tp),>tybuf); 203 cr = (gttybuf.sg_flags & CRMOD) ? "" : "\r"; 204 strncpy(name, utp->ut_name, sizeof (utp->ut_name)); 205 name[sizeof (name) - 1] = 0; 206 fprintf(tp,"%s\n\007New mail for %s\007 has arrived:%s\n", 207 cr, name, cr); 208 fprintf(tp,"----%s\n", cr); 209 jkfprintf(tp, name, offset); 210 fclose(tp); 211 } 212 213 jkfprintf(tp, name, offset) 214 register FILE *tp; 215 { 216 register FILE *fi; 217 register int linecnt, charcnt; 218 219 dprintf("HERE %s's mail starting at %d\n", 220 name, offset); 221 if ((fi = fopen(name,"r")) == NULL) { 222 dprintf("Cant read the mail\n"); 223 return; 224 } 225 fseek(fi, offset, 0); 226 linecnt = 7; 227 charcnt = 560; 228 /* 229 * print the first 7 lines or 560 characters of the new mail 230 * (whichever comes first) 231 */ 232 for (;;) { 233 register ch; 234 235 if ((ch = getc(fi)) == EOF) { 236 fprintf(tp,"----%s\n", cr); 237 break; 238 } 239 if (ch == '\n') { 240 fprintf(tp,"%s\n", cr); 241 if (linecnt-- < 0) { 242 fprintf(tp,"...more...%s\n", cr); 243 break; 244 } 245 } else if(linecnt <= 0) { 246 fprintf(tp,"...more...%s\n", cr); 247 break; 248 } else 249 putc(ch, tp); 250 if (charcnt-- == 0) { 251 fprintf(tp, "%s\n", cr); 252 break; 253 } 254 } 255 } 256