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