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