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