|
|
1.1 ! root 1: /* ! 2: * msgs - system wide messages program ! 3: */ ! 4: ! 5: #include <stdio.h> ! 6: #include <sys/stat.h> ! 7: #include <sys/dir.h> ! 8: #include <ctype.h> ! 9: #include <signal.h> ! 10: ! 11: #define BSIZE 512 ! 12: #define NLINE 512 ! 13: #define PAGELEN 20 ! 14: ! 15: char mline[NLINE]; /* line of mail file */ ! 16: ! 17: int qflag; /* query new messages */ ! 18: int msgsnum; /* command line numeric argument */ ! 19: int exstat; /* exit status */ ! 20: ! 21: FILE *boundfp; /* file pointer for boundname */ ! 22: char *boundformat = "LOWMSG=%d\tHIGHMSG=%d\n"; ! 23: unsigned int lowmsg; /* lowest number message in msgsdir */ ! 24: unsigned int highmsg; /* highest number message in msgsdir */ ! 25: ! 26: FILE *mailfp; /* file pointer to mailfile */ ! 27: char *mailfile = "/usr/spool/mail/msgs"; ! 28: char *msgsdir = "/usr/msgs"; ! 29: char *rcname = ".msgsrc"; ! 30: char *rcformat = "MSGSNUM=%d\n"; ! 31: char *boundname = "/usr/msgs/bounds"; ! 32: char *home; ! 33: char *scatname; ! 34: ! 35: #define FATAL 1 /* used by badmsg() */ ! 36: #define NONFATAL 0 ! 37: ! 38: extern char *getenv(); ! 39: ! 40: main(argc, argv) ! 41: int argc; ! 42: char *argv[]; ! 43: { ! 44: int rcnum, num; ! 45: ! 46: if ( argc > 1 ) ! 47: doargs(argc, argv); ! 48: dobounds(); ! 49: readmail(); ! 50: rcnum = readrc(); ! 51: num = (msgsnum<=0) ? rcnum+msgsnum : msgsnum; ! 52: if ( (num=domsgs(num)) > rcnum ) ! 53: writerc(num); ! 54: exit(exstat); ! 55: } ! 56: ! 57: /* ! 58: * Fix the boundname file and set the global variables ! 59: * lowmsg and highmsg to the appropriate values. ! 60: */ ! 61: ! 62: dobounds() ! 63: { ! 64: struct stat st; ! 65: ! 66: if ( stat(boundname, &st) < 0 ) { ! 67: calcbounds(); ! 68: return; ! 69: } ! 70: ! 71: if ( (boundfp=fopen(boundname,"rw")) == NULL ) ! 72: badmsg(FATAL, "Can't open read/write: %s", boundname); ! 73: ! 74: if ( fscanf(boundfp, boundformat, &lowmsg, &highmsg) != 2 ) ! 75: calcbounds(); ! 76: } ! 77: ! 78: /* ! 79: * Recreate the boundname file ! 80: */ ! 81: ! 82: calcbounds() ! 83: { ! 84: int dirfd; ! 85: char buf[BSIZE]; ! 86: int num, size; ! 87: struct direct *dentry; ! 88: ! 89: if ( (boundfp=fopen(boundname,"w")) == NULL ) ! 90: badmsg(FATAL, "Can't open: %s", boundname); ! 91: ! 92: if ( chmod(boundname, 0666) < 0 ) ! 93: badmsg(FATAL, "Can't chmod: %s", boundname); ! 94: ! 95: if ( (dirfd=open(msgsdir, 0)) < 0 ) ! 96: badmsg(FATAL, "Can't open: %s", msgsdir); ! 97: ! 98: highmsg = 0; ! 99: lowmsg = ~000; ! 100: ! 101: while ( (size=read(dirfd, buf, BSIZE)) != 0 ) { ! 102: dentry = (struct direct *) buf; ! 103: while ( (size-=sizeof(struct direct)) >= 0 ) { ! 104: ! 105: if ( dentry->d_ino && ! 106: (num=decode(dentry->d_name)) > 0 ) { ! 107: if ( num > highmsg ) ! 108: highmsg = num; ! 109: if ( num < lowmsg ) ! 110: lowmsg = num; ! 111: } ! 112: dentry++; ! 113: } ! 114: } ! 115: ! 116: if ( highmsg==0 ) ! 117: lowmsg = 0; ! 118: ! 119: fprintf(boundfp, boundformat, lowmsg, highmsg); ! 120: } ! 121: ! 122: /* ! 123: * Does an atoi of the given string once it is certain that ! 124: * it is all digits. ! 125: */ ! 126: ! 127: decode(str) ! 128: char *str; ! 129: { ! 130: register int i; ! 131: ! 132: for (i=0; i<DIRSIZ; i++) { ! 133: if ( str[i] == '\0' ) ! 134: break; ! 135: if ( i==0 && str[0] == '-' ) ! 136: continue; ! 137: if ( !isascii(str[i]) || !isdigit(str[i]) ) ! 138: return(0); ! 139: } ! 140: ! 141: return(atoi(str)); ! 142: } ! 143: ! 144: /* ! 145: * Process the mail in mailfile, and put it in the msgsdir. ! 146: */ ! 147: ! 148: readmail() ! 149: { ! 150: struct stat st; ! 151: int fd; ! 152: ! 153: if ( stat(mailfile, &st) < 0 ) { ! 154: badmsg(NONFATAL,"Can't stat: %s", mailfile); ! 155: return; ! 156: } ! 157: ! 158: if ( st.st_size == 0 ) { ! 159: fclose(boundfp); ! 160: return; ! 161: } ! 162: ! 163: if ( (mailfp=fopen(mailfile, "rw")) == NULL ) { ! 164: badmsg(NONFATAL,"Can't open read/write: %s", mailfile); ! 165: return; ! 166: } ! 167: ! 168: if ( chdir(msgsdir) < 0 ) ! 169: badmsg(FATAL, "Can't chdir: %s", msgsdir); ! 170: ! 171: while ( dumpmsg() ) ; ! 172: ! 173: fclose(mailfp); ! 174: if ( (fd=creat(mailfile, 0644)) < 0 ) ! 175: badmsg(FATAL, "Can't creat: %s", mailfile); ! 176: close(fd); ! 177: ! 178: rewind(boundfp); ! 179: fprintf(boundfp, boundformat, lowmsg, highmsg); ! 180: fclose(boundfp); ! 181: } ! 182: ! 183: /* ! 184: * Dump the current message from the mailfile into the msgsdir ! 185: */ ! 186: ! 187: dumpmsg() ! 188: { ! 189: char *tmp; ! 190: char numname[10]; ! 191: FILE *fp; ! 192: ! 193: while ( (tmp=fgets(mline, NLINE, mailfp)) != NULL ) ! 194: if ( strcmp(mline, "\1\1\n") ) ! 195: break; ! 196: ! 197: if ( tmp == NULL ) ! 198: return(0); ! 199: ! 200: sprintf(numname, "%d", ++highmsg); ! 201: ! 202: if ( (fp=fopen(numname,"w")) == NULL ) ! 203: badmsg(FATAL, "Can't open to write: %s/%s", msgsdir, numname); ! 204: ! 205: do { ! 206: fputs(mline, fp); ! 207: if ( strcmp(mline, "\1\1\n") == 0 ) ! 208: break; ! 209: } while ( fgets(mline, NLINE, mailfp) != NULL ); ! 210: ! 211: fclose(fp); ! 212: if ( lowmsg == 0 ) ! 213: lowmsg = 1; ! 214: return(1); ! 215: } ! 216: ! 217: /* ! 218: * Display the messages in msgsdir beginning with ! 219: * message number (num) ! 220: */ ! 221: ! 222: domsgs(num) ! 223: int num; ! 224: { ! 225: int intexit(); ! 226: ! 227: signal(SIGINT, intexit); ! 228: signal(SIGPIPE, intexit); ! 229: ! 230: if ( chdir(msgsdir) < 0 ) ! 231: badmsg(FATAL, "Can't chdir: %s", msgsdir); ! 232: ! 233: if ( num < 1 || num < lowmsg ) ! 234: num = lowmsg; ! 235: ! 236: if ( qflag ) { ! 237: if (num <= highmsg) ! 238: printf("There are new messages.\n"); ! 239: else ! 240: printf("No new messages.\n"); ! 241: return(num); ! 242: } ! 243: ! 244: if ( ((scatname=getenv("PAGER")) != NULL) && ! 245: (strlen(scatname) == 0) ) ! 246: scatname = NULL; ! 247: ! 248: while ( num <= highmsg ) { ! 249: if (do_one(num) < 0) ! 250: break; ! 251: num += 1; ! 252: } ! 253: ! 254: return(num); ! 255: } ! 256: ! 257: /* ! 258: * Display a single message, return (-1) if user ! 259: * requests to quit. ! 260: */ ! 261: ! 262: do_one(num) ! 263: int num; ! 264: { ! 265: FILE *fp; ! 266: char numname[10]; ! 267: char ch, inputchar(); ! 268: long offset = 0; ! 269: int newnum; ! 270: struct stat st; ! 271: ! 272: sprintf(numname, "%d", num); ! 273: ! 274: if ( stat(numname, &st) < 0 ) ! 275: return(0); ! 276: ! 277: if ( (fp=fopen(numname, "r")) == NULL ) ! 278: return(0); ! 279: ! 280: printf("\nMessage Number %d [%ld chars]\n", num, st.st_size); ! 281: ! 282: while ( fgets(mline, NLINE, fp) != NULL ) { ! 283: if ( (strncmp(mline, "Date: ", 6) == 0) || ! 284: (strncmp(mline, "From: ", 6) == 0) || ! 285: (strncmp(mline, "To: ", 4 ) == 0) || ! 286: (strncmp(mline, "cc: ", 4 ) == 0) || ! 287: havesubject() ) { ! 288: printf("%s", mline); ! 289: offset = ftell(fp); ! 290: continue; ! 291: } ! 292: if (offset) ! 293: break; ! 294: } ! 295: ! 296: if ( !offset ) { ! 297: fclose(fp); ! 298: return(0); ! 299: } ! 300: fseek(fp, offset, 0); ! 301: ! 302: switch( ch=inputchar() ) { ! 303: case 'Y': ! 304: dumpit(fp); ! 305: case 'N': ! 306: fclose(fp); ! 307: return(0); ! 308: case 'Q': ! 309: fclose(fp); ! 310: return(-1); ! 311: default: ! 312: ungetc(ch, stdin); ! 313: scanf("%d", &newnum); ! 314: while ( getchar() != '\n' ) ; ! 315: break; ! 316: case '-': ! 317: newnum = num - 1; ! 318: break; ! 319: } ! 320: fclose(fp); ! 321: if ( do_one(newnum) < 0 ) ! 322: return(-1); ! 323: return(do_one(num)); ! 324: } ! 325: ! 326: /* ! 327: * Determine if we have a subject in mline. ! 328: */ ! 329: ! 330: havesubject() ! 331: { ! 332: static char *subject="subject:"; ! 333: register char *x = subject; ! 334: register char *y = mline; ! 335: ! 336: while ( *x ) ! 337: if ( tolower(*y++)!=*x++ ) ! 338: return(0); ! 339: ! 340: return(1); ! 341: } ! 342: ! 343: /* ! 344: * Print out the text of the message in a scat like ! 345: * manner. ! 346: */ ! 347: ! 348: dumpit(fp) ! 349: FILE *fp; ! 350: { ! 351: FILE *xfp; ! 352: char ch, *cmdname; ! 353: ! 354: if ( scatname != NULL ) { ! 355: sprintf(cmdname=&mline[0], "%s", scatname); ! 356: if ( (xfp=popen(cmdname, "w")) == NULL ) ! 357: badmsg(FATAL, "Can't open pipe for writing: %s", ! 358: cmdname); ! 359: while ( (ch=getc(fp)) != EOF ) ! 360: if ( putc(ch, xfp) == EOF ) ! 361: intexit(SIGPIPE); ! 362: if ( ((pclose(xfp)>>8)&0xFF) == SIGINT ) ! 363: intexit(SIGINT); ! 364: } else { ! 365: while ( (ch=getc(fp)) != EOF ) ! 366: putc(ch, stdout); ! 367: } ! 368: } ! 369: ! 370: intexit(status) ! 371: { ! 372: putc('\n', stdout); ! 373: _exit(status); ! 374: } ! 375: ! 376: char ! 377: inputchar() ! 378: { ! 379: char ch; ! 380: ! 381: for (;;) { ! 382: printf("[ynq]: "); ! 383: while ( (ch=getchar()) == ' ' || ch == '\t' ) ; ! 384: if ( isalpha(ch) ) ! 385: ch = toupper(ch); ! 386: ! 387: if ( ch == '\n' ) ! 388: return('Y'); ! 389: ! 390: if ( isdigit(ch) ) ! 391: return(ch); ! 392: ! 393: while (getchar() != '\n') ; ! 394: ! 395: if ( ch == 'N' || ch == 'Y' || ch == 'Q' || ch == '-') ! 396: return(ch); ! 397: } ! 398: } ! 399: ! 400: /* ! 401: * Returns the next message number to read according the the ! 402: * file (.msgsrc) in the HOME directory. Returns message ! 403: * number (1) if any problems. ! 404: */ ! 405: ! 406: readrc() ! 407: { ! 408: FILE *msgsrc; ! 409: struct stat st; ! 410: int num; ! 411: ! 412: if ( (home=getenv("HOME")) == NULL ) { ! 413: badmsg(NONFATAL,"No HOME variable in environment."); ! 414: return(1); ! 415: } ! 416: ! 417: if ( chdir(home) < 0 ) { ! 418: badmsg(NONFATAL,"Can't chdir to %s", home); ! 419: return(1); ! 420: } ! 421: ! 422: if ( stat(rcname, &st) < 0 ) ! 423: return(1); ! 424: ! 425: if ( (msgsrc=fopen(rcname,"r")) == NULL ) { ! 426: badmsg(NONFATAL, "Can't open to read: %s/%s", home, rcname); ! 427: return(1); ! 428: } ! 429: ! 430: if ( fscanf(msgsrc, rcformat, &num) != 1 ) { ! 431: badmsg(NONFATAL, "Badly formatted file: %s/%s", home, rcname); ! 432: return(1); ! 433: } ! 434: ! 435: fclose(msgsrc); ! 436: return(num); ! 437: } ! 438: ! 439: /* ! 440: * Update the rcname file in the user's home directory. ! 441: */ ! 442: ! 443: writerc(num) ! 444: int num; ! 445: { ! 446: FILE *msgsrc; ! 447: ! 448: if ( chdir(home) < 0 ) ! 449: badmsg(FATAL,"Can't chdir to %s", home); ! 450: ! 451: if (setuid(getuid())< 0) ! 452: badmsg(FATAL, "Can't setuid to %d\n", getuid()); ! 453: ! 454: if ( (msgsrc=fopen(rcname,"w")) == NULL ) ! 455: badmsg(FATAL, "Can't open to write: %s/%s", home, rcname); ! 456: ! 457: fprintf(msgsrc, rcformat, num); ! 458: fclose(msgsrc); ! 459: } ! 460: ! 461: /* ! 462: * Process command line arguments. ! 463: */ ! 464: ! 465: doargs(argc, argv) ! 466: register int argc; ! 467: register char *argv[]; ! 468: { ! 469: if ( argc > 2 ) ! 470: usage(); ! 471: ! 472: if ( strcmp(argv[1], "-q") == 0 ) ! 473: qflag = 1; ! 474: else if ( (msgsnum=decode(argv[1])) == 0 ) ! 475: usage(); ! 476: } ! 477: ! 478: /* ! 479: * Issue error message. flag is either NONFATAL or FATAL ! 480: */ ! 481: ! 482: badmsg(flag, x) ! 483: int flag; ! 484: char *x; ! 485: { ! 486: fprintf(stderr, "msgs: %r\n", &x); ! 487: if ( flag == FATAL) ! 488: exit(1); ! 489: else ! 490: exstat = 1; ! 491: } ! 492: ! 493: char *usemsg = "\n\ ! 494: Usage: msgs [ -q ] [ number ]\n\ ! 495: -q : query existence of new messages\n\ ! 496: number: greater than zero, start with that message number\n\ ! 497: less than zero, start backward that many from current\n\n"; ! 498: ! 499: usage() ! 500: { ! 501: fprintf(stderr, usemsg); ! 502: exit(1); ! 503: } ! 504:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.