1: /* 2: * fancied up comsat program..... 3: */ 4: 5: #ifndef lint 6: static char *rcsid_comsat_c = "$Header: comsat.c,v 10.3 86/02/01 15:18:47 tony Rel $"; 7: #endif lint 8: 9: #define XWIND 10: #define SHORTSWEET 11: 12: #ifndef lint 13: static char sccsid[] = "@(#)comsat.c 4.12 (Berkeley) 8/1/84"; 14: #endif 15: 16: #ifndef XWIND 17: #include <sys/types.h> 18: #include <sys/socket.h> 19: #else 20: #include <X/Xlib.h> 21: #include <ttyent.h> 22: #include <pwd.h> 23: char *indexs(); 24: extern char **environ; 25: #endif 26: #include <sys/stat.h> 27: #include <sys/wait.h> 28: #include <sys/file.h> 29: 30: #include <netinet/in.h> 31: 32: #include <stdio.h> 33: #include <sgtty.h> 34: #include <utmp.h> 35: #include <signal.h> 36: #include <errno.h> 37: #include <netdb.h> 38: #include <syslog.h> 39: 40: char *index(), *rindex(); 41: 42: /* 43: * comsat 44: */ 45: int debug = 0; 46: #define dprintf if (debug) printf 47: 48: #define MAXUTMP 100 /* down from init */ 49: 50: struct sockaddr_in sin = { AF_INET }; 51: extern errno; 52: 53: char hostname[32]; 54: struct utmp utmp[100]; 55: int nutmp; 56: int uf; 57: unsigned utmpmtime; /* last modification time for utmp */ 58: int onalrm(); 59: int reapchildren(); 60: long lastmsgtime; 61: 62: #define MAXIDLE 120 63: #define NAMLEN (sizeof (uts[0].ut_name) + 1) 64: 65: main(argc, argv) 66: int argc; 67: char *argv[]; 68: { 69: register int cc; 70: char buf[BUFSIZ]; 71: char msgbuf[100]; 72: struct sockaddr_in from; 73: int fromlen; 74: 75: /* verify proper invocation */ 76: fromlen = sizeof (from); 77: if (getsockname(0, &from, &fromlen) < 0) { 78: fprintf(stderr, "%s: ", argv[0]); 79: perror("getsockname"); 80: _exit(1); 81: } 82: chdir("/usr/spool/mail"); 83: if ((uf = open("/etc/utmp",0)) < 0) { 84: openlog("comsat", 0, 0); 85: syslog(LOG_ERR, "/etc/utmp: %m"); 86: (void) recv(0, msgbuf, sizeof (msgbuf) - 1, 0); 87: exit(1); 88: } 89: lastmsgtime = time(0); 90: gethostname(hostname, sizeof (hostname)); 91: onalrm(); 92: signal(SIGALRM, onalrm); 93: signal(SIGTTOU, SIG_IGN); 94: signal(SIGCHLD, reapchildren); 95: for (;;) { 96: cc = recv(0, msgbuf, sizeof (msgbuf) - 1, 0); 97: if (cc <= 0) { 98: if (errno != EINTR) 99: sleep(1); 100: errno = 0; 101: continue; 102: } 103: sigblock(1<<SIGALRM); 104: msgbuf[cc] = 0; 105: lastmsgtime = time(0); 106: mailfor(msgbuf); 107: sigsetmask(0); 108: } 109: } 110: 111: reapchildren() 112: { 113: 114: while (wait3((struct wait *)0, WNOHANG, (struct rusage *)0) > 0) 115: ; 116: } 117: 118: onalrm() 119: { 120: struct stat statbf; 121: struct utmp *utp; 122: 123: if (time(0) - lastmsgtime >= MAXIDLE) 124: exit(0); 125: dprintf("alarm\n"); 126: alarm(15); 127: fstat(uf, &statbf); 128: if (statbf.st_mtime > utmpmtime) { 129: dprintf(" changed\n"); 130: utmpmtime = statbf.st_mtime; 131: lseek(uf, 0, 0); 132: nutmp = read(uf,utmp,sizeof(utmp))/sizeof(struct utmp); 133: } else 134: dprintf(" ok\n"); 135: } 136: 137: mailfor(name) 138: char *name; 139: { 140: register struct utmp *utp = &utmp[nutmp]; 141: register char *cp; 142: int offset; 143: 144: dprintf("mailfor %s\n", name); 145: cp = name; 146: while (*cp && *cp != '@') 147: cp++; 148: if (*cp == 0) { 149: dprintf("bad format\n"); 150: return; 151: } 152: *cp = 0; 153: offset = atoi(cp+1); 154: while (--utp >= utmp) 155: if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name))) 156: notify(utp, offset); 157: } 158: 159: char *cr; 160: 161: notify(utp, offset) 162: register struct utmp *utp; 163: { 164: int fd, flags, n, err, msglen; 165: struct sgttyb gttybuf; 166: char tty[sizeof (utmp[0].ut_line) + 6], msgbuf[BUFSIZ]; 167: char name[sizeof (utmp[0].ut_name) + 1]; 168: struct stat stb; 169: #ifdef XWIND 170: struct ttyent *te; 171: char *s; 172: char dname[260]; 173: #endif 174: 175: strcpy(tty, "/dev/"); 176: strncat(tty, utp->ut_line, sizeof(utp->ut_line)); 177: dprintf("notify %s on %s\n", utp->ut_name, tty); 178: if (stat(tty, &stb) == 0 && (stb.st_mode & 0100) == 0) { 179: dprintf("wrong mode\n"); 180: return; 181: } 182: strncpy(name, utp->ut_name, sizeof (utp->ut_name)); 183: name[sizeof (name) - 1] = '\0'; 184: #ifdef XWIND 185: te = getttynam(tty+5); 186: if ((s = indexs(te->ty_getty, "xterm")) && 187: (s = indexs(s, " -L ")) && 188: (s = index(s, ':'))) { 189: while (*(--s) != ' ') ; 190: s++; 191: if (*s == ':') { 192: gethostname(dname, sizeof (dname)); 193: strcat(dname, s); 194: } else 195: strcpy(dname, s); 196: Xprintf(msgbuf, name, offset); 197: if (fork()) 198: return; 199: Xnotify(name, dname, msgbuf); 200: } 201: #endif 202: if ((fd = open(tty, O_WRONLY|O_NDELAY)) < 0) { 203: dprintf("%s: open failed\n", tty); 204: return; 205: } 206: if ((flags = fcntl(fd, F_GETFL, 0)) == -1) { 207: dprintf("fcntl(F_GETFL) failed %d\n", errno); 208: return; 209: } 210: ioctl(fd, TIOCGETP, >tybuf); 211: cr = (gttybuf.sg_flags & CRMOD) ? "" : "\r"; 212: #ifdef SHORTSWEET 213: sprintf(msgbuf, "%s\n\007New mail from ", cr); 214: #else 215: sprintf(msgbuf, "%s\n\007New mail for %s@%s\007 has arrived:%s\n", 216: cr, name, hostname, cr); 217: #endif 218: jkfprintf(msgbuf+strlen(msgbuf), name, offset); 219: if (fcntl(fd, F_SETFL, flags | FNDELAY) == -1) 220: goto oldway; 221: msglen = strlen(msgbuf); 222: n = write(fd, msgbuf, msglen); 223: err = errno; 224: (void) fcntl(fd, F_SETFL, flags); 225: (void) close(fd); 226: if (n == msglen) 227: return; 228: if (err != EWOULDBLOCK) { 229: dprintf("write failed %d\n", errno); 230: return; 231: } 232: oldway: 233: if (fork()) { 234: (void) close(fd); 235: return; 236: } 237: signal(SIGALRM, SIG_DFL); 238: alarm(30); 239: (void) write(fd, msgbuf, msglen); 240: exit(0); 241: } 242: 243: #ifdef SHORTSWEET 244: jkfprintf(mp, name, offset) 245: register char *mp; 246: { 247: register FILE *fi; 248: char line[BUFSIZ]; 249: 250: dprintf("HERE %s's mail starting at %d\n", name, offset); 251: 252: if ((fi = fopen(name, "r")) == NULL) { 253: dprintf("Cant read the mail\n"); 254: return; 255: } 256: fseek(fi, offset, L_SET); 257: /* 258: * put the contents of the From: line into mp buffer 259: */ 260: while (fgets(line, sizeof (line), fi) != NULL) { 261: register char *cp; 262: 263: if (strncmp (line, "From:", 5) != 0) 264: continue; 265: cp = index(line, '\n'); 266: if (cp) 267: *cp = '\0'; 268: for (cp = line+5; (*cp == ' ' || *cp == '\t'); cp++); 269: sprintf(mp, "%s%s\n", cp, cr); 270: return; 271: } 272: /* didn't find the From: line */ 273: sprintf (mp, "???%s\n", cr); 274: } 275: #else 276: jkfprintf(mp, name, offset) 277: register char *mp; 278: { 279: register FILE *fi; 280: register int linecnt, charcnt; 281: char line[BUFSIZ]; 282: int inheader; 283: 284: dprintf("HERE %s's mail starting at %d\n", name, offset); 285: 286: if ((fi = fopen(name, "r")) == NULL) { 287: dprintf("Cant read the mail\n"); 288: return; 289: } 290: fseek(fi, offset, L_SET); 291: /* 292: * Print the first 7 lines or 560 characters of the new mail 293: * (whichever comes first). Skip header crap other than 294: * From, Subject, To, and Date. 295: */ 296: linecnt = 7; 297: charcnt = 560; 298: inheader = 1; 299: while (fgets(line, sizeof (line), fi) != NULL) { 300: register char *cp; 301: int cnt; 302: 303: if (linecnt <= 0 || charcnt <= 0) { 304: sprintf(mp, "...more...%s\n", cr); 305: mp += strlen(mp); 306: return; 307: } 308: if (strncmp(line, "From ", 5) == 0) 309: continue; 310: if (inheader && (line[0] == ' ' || line[0] == '\t')) 311: continue; 312: cp = index(line, ':'); 313: if (cp == 0 || (index(line, ' ') && index(line, ' ') < cp)) 314: inheader = 0; 315: else 316: cnt = cp - line; 317: if (inheader && 318: strncmp(line, "Date", cnt) && 319: strncmp(line, "From", cnt) && 320: strncmp(line, "Subject", cnt) && 321: strncmp(line, "To", cnt)) 322: continue; 323: cp = index(line, '\n'); 324: if (cp) 325: *cp = '\0'; 326: sprintf(mp, "%s%s\n", line, cr); 327: mp += strlen(mp); 328: linecnt--, charcnt -= strlen(line); 329: } 330: sprintf(mp, "----%s\n", cr); 331: mp += strlen(mp); 332: } 333: #endif 334: 335: #ifdef XWIND 336: char *indexs(s1, s2) 337: register char *s1, *s2; 338: { 339: register int z = strlen(s2); 340: while (*s1 && strncmp(s1, s2, z)) 341: s1++; 342: return(s1); 343: } 344: 345: Xprintf(mp, name, offset) 346: register char *mp; 347: { 348: register FILE *fi; 349: char line[BUFSIZ]; 350: 351: dprintf("HERE %s's mail starting at %d\n", name, offset); 352: 353: sprintf(mp, "You have new mail."); 354: if ((fi = fopen(name, "r")) == NULL) { 355: dprintf("Cant read the mail\n"); 356: return; 357: } 358: fseek(fi, offset, L_SET); 359: /* 360: * put the contents of the From: line into mp buffer 361: */ 362: while (fgets(line, sizeof (line), fi) != NULL) { 363: register char *cp; 364: 365: if (strncmp (line, "From:", 5) != 0) 366: continue; 367: cp = index(line, '\n'); 368: if (cp) 369: *cp = '\0'; 370: for (cp = line+5; (*cp == ' ' || *cp == '\t'); cp++); 371: sprintf(mp, "Mail from %s", cp); 372: break; 373: } 374: fclose(fi); 375: } 376: 377: short cursor[] = {0x0000, 0x7ffe, 0x4fc2, 0x4ffe, 0x7ffe, 378: 0x7ffe, 0x781e, 0x7ffe , 0x7ffe, 0x0000}; 379: 380: Xnotify (name, dname, notice) 381: char *name; 382: char *dname; 383: char *notice; 384: { 385: struct passwd *pwent; 386: char *envbuf[2]; 387: char homebuf[280]; 388: Display *dpy; 389: WindowInfo winfo; 390: FontInfo finfo; 391: Font font; 392: int width, height; 393: Window w; 394: XEvent rep; 395: int timeout = 0; 396: int reverse = 0; 397: int bwidth = 2; 398: int inner = 2; 399: int vertical = 2; 400: int volume = 0; 401: int forepix = BlackPixel; 402: int backpix = WhitePixel; 403: int brdrpix = BlackPixel; 404: int mouspix = BlackPixel; 405: char *option; 406: char *font_name = "8x13"; 407: char *fore_color = NULL; 408: char *back_color = NULL; 409: char *brdr_color = NULL; 410: char *mous_color = NULL; 411: Color cdef; 412: 413: if (!XOpenDisplay(dname)) 414: exit(0); 415: if (pwent = getpwnam(name)) { 416: strcpy(homebuf, "HOME="); 417: strcat(homebuf, pwent->pw_dir); 418: envbuf[0] = homebuf; 419: envbuf[1] = NULL; 420: environ = envbuf; 421: if (option = XGetDefault("biff", "BodyFont")) 422: font_name = option; 423: fore_color = XGetDefault("biff", "Foreground"); 424: back_color = XGetDefault("biff", "Background"); 425: brdr_color = XGetDefault("biff", "Border"); 426: mous_color = XGetDefault("biff", "Mouse"); 427: if (option = XGetDefault("biff", "BorderWidth")) 428: bwidth = atoi(option); 429: if (option = XGetDefault("biff", "InternalBorder")) 430: inner = atoi(option); 431: if (option = XGetDefault("biff", "Timeout")) 432: timeout = atoi(option); 433: if (option = XGetDefault("biff", "Volume")) 434: volume = atoi(option); 435: if (option = XGetDefault("biff", "Offset")) 436: vertical = atoi(option); 437: if ((option = XGetDefault("biff", "ReverseVideo")) && 438: strcmp(option, "on") == 0) 439: reverse = 1; 440: } 441: if (reverse) { 442: brdrpix = backpix; 443: backpix = forepix; 444: forepix = brdrpix; 445: mouspix = forepix; 446: } 447: 448: if ((font = XGetFont(font_name)) == NULL) 449: exit(0); 450: if (DisplayCells() > 2) { 451: if (back_color && XParseColor(back_color, &cdef) && 452: XGetHardwareColor(&cdef)) 453: backpix = cdef.pixel; 454: if (fore_color && XParseColor(fore_color, &cdef) && 455: XGetHardwareColor(&cdef)) 456: forepix = cdef.pixel; 457: if (brdr_color && XParseColor(brdr_color, &cdef) && 458: XGetHardwareColor(&cdef)) 459: brdrpix = cdef.pixel; 460: if (mous_color && XParseColor(mous_color, &cdef) && 461: XGetHardwareColor(&cdef)) 462: mouspix = cdef.pixel; 463: } 464: XQueryFont(font, &finfo); 465: XQueryWindow (RootWindow, &winfo); 466: width = XQueryWidth (notice, font) + (inner << 1); 467: height = finfo.height + (inner << 1); 468: if (vertical < 0) 469: vertical += winfo.height - height - (bwidth << 1); 470: w = XCreateWindow(RootWindow, (winfo.width - width - (bwidth << 1)) / 2, 471: vertical, width, height, bwidth, 472: XMakeTile(brdrpix), XMakeTile(backpix)); 473: XStoreName(w, notice); 474: XSelectInput(w, ButtonPressed|ButtonReleased|ExposeWindow); 475: XDefineCursor(w, XCreateCursor(16, 10, cursor, NULL, 7, 5, 476: mouspix, backpix, GXcopy)); 477: XMapWindow(w); 478: XFeep(volume); 479: if (timeout > 0) { 480: signal(SIGALRM, exit); 481: alarm(timeout * 60); 482: } 483: if (inner) inner--; 484: while (1) { 485: XText(w, inner, inner, notice, strlen(notice), 486: font, forepix, backpix); 487: XNextEvent(&rep); 488: if (rep.type == ButtonPressed) 489: exit(0); 490: } 491: } 492: #endif