1: /* DELREMIND command -- Steve Zucker, April, 1976 */ 2: /* Compile -i, as super user and set mode 04555 */ 3: #include <stdio.h> 4: #include <pwd.h> 5: #include <signal.h> 6: 7: #define MAXRCVRS 50 8: #define MAXMSG 1000 9: #define DIRSIZE 254 /* No bigger than 254 */ 10: #define MAXREMS 100 /* Maximum that this program can process at once */ 11: char *rmdlock = "/usr/spool/rmd/rmdlock"; /* exists while proc is busy */ 12: char *reminders = "/usr/spool/rmd/rmdfile"; 13: char *tempfile = "/usr/spool/rmd/d.XXXXXX"; 14: char *rmdtemp = "/usr/spool/rmd/rmdtemp"; 15: char *nofile = "Unable to open %s\n"; 16: char *norems = "No reminders\n"; 17: struct rmdblock 18: { int tdeliver[2]; 19: int nobytes; 20: int tsent[2]; 21: char sender[8]; 22: char bits; 23: char dirsize; 24: char nrcvrs; 25: int msgbytes; 26: char rcvr1[8]; 27: } m, hdr[MAXREMS]; 28: #define PRIORITY 01 /* bits */ 29: #define DELETED 01 /* mark bit */ 30: char marks[MAXREMS]; 31: int nrmds; 32: FILE *fdcopy, *fdrem, *fdtemp; 33: char rmdbuff[8*MAXRCVRS-8 + MAXMSG + DIRSIZE]; 34: char rmddata[8*MAXRCVRS-8 + MAXMSG + DIRSIZE]; 35: char command[160]; 36: char user[10]; /* user id null padded */ 37: 38: main() 39: { register int i; 40: register char *p; 41: register char c; 42: int j; 43: int uid; 44: struct passwd *pw; 45: struct passwd *getpwuid(); 46: extern errno; 47: /* Get user name if not superuser */ 48: uid = getuid(); 49: if((pw=getpwuid(uid))==NULL) 50: { 51: fprintf(stderr,nofile,"password file"); 52: exit(1); 53: } 54: strcpy(user,pw->pw_name); 55: /* Make tempfile name */ 56: p = index(tempfile,'X'); 57: j = getpid(); 58: for (i=18; i =- 3; ) 59: *p++ = ((j>>i)&07) + '0'; 60: lock(); 61: if ((fdcopy = fopen(tempfile,"w")) == NULL) 62: { fprintf(stderr,nofile, tempfile); 63: exit(1); 64: } 65: if ((fdrem = fopen(reminders,"r")) == NULL) 66: { fprintf(stderr,norems); 67: cleanup(); 68: } 69: for (i=0; i<MAXREMS; ) 70: { p = &hdr[i]; 71: if (fread(p,sizeof m,1,fdrem) != 1) break; 72: /* 73: if (errno) ioerror(); 74: */ 75: if (uid == 0 || equal(user,p->sender,8) || 76: (p->nrcvrs==1 && equal(user,p->rcvr1,8))) 77: { /* Copy relevant portions of reminder file */ 78: if(fread(rmddata,p->nobytes-8,1,fdrem)!=1) 79: fprintf(stderr,"Read error\n"); 80: else 81: if(fwrite(rmddata,p->nobytes-8,1,fdcopy)!=1) 82: fprintf(stderr,"write error\n"); 83: /* 84: if (errno) ioerror(); 85: */ 86: i++; 87: } 88: else 89: fseek(fdrem,(long)p->nobytes-8,1); 90: } 91: fclose(fdcopy); 92: fclose(fdrem); 93: unlock(); 94: if ((nrmds = i) == 0) 95: { printf(norems); 96: cleanup(); 97: } 98: printf ("%d messages\n",i); 99: /* Collect and execute one command at a time */ 100: for (;;) 101: { for (i=0; i < sizeof command; ) 102: { switch(c = getchar()) 103: { case ' ': 104: case '\t': 105: continue; /* Ignore blanks and tabs */ 106: case '\0': 107: cleanup(); /* Exit with no change on EOT */ 108: case '\n': 109: command[i++] = '\0'; 110: if (parse()) goto wrapup; 111: goto nextcom; 112: default: 113: command[i++] = c; 114: } 115: } 116: printf ("Line too long\n"); 117: while ((c = getchar()) != '\n' && c != '\0') ; 118: nextcom: ; /* Make C compiler happy */ 119: } 120: wrapup: /* Delete marked messages if any */ 121: for (i=0; i<nrmds; i++) 122: if (marks[i]&DELETED) break; 123: if (i >= nrmds) cleanup(); 124: printf ("Marked reminders are being deleted\n"); 125: lock(); 126: if ((fdrem = fopen(reminders,"r")) == NULL) 127: cleanup(); /* They're all gone anyway */ 128: if ((fdtemp = fopen(rmdtemp,"w")) == NULL) 129: { fprintf(stderr,nofile,rmdtemp); 130: cleanup(); 131: } 132: while (fread(&m, sizeof m, 1, fdrem) == 1) 133: { fread(rmddata,m.nobytes-8,1,fdrem); 134: for (i=0; i < nrmds; i++) 135: { if (marks[i]&DELETED && equal(&m,&hdr[i],sizeof m)) 136: { getcopy(i); 137: if (equal(rmdbuff,rmddata,m.nobytes-8)) 138: { /* delete (don't copy) it */ 139: marks[i] = 0; 140: goto nocopy; 141: } 142: } 143: } 144: fwrite (&m, sizeof m,1,fdtemp); 145: fwrite (rmddata,m.nobytes-8,1,fdtemp); 146: nocopy: ; /* Make C compiler happy */ 147: } 148: unlink(reminders); 149: link(rmdtemp,reminders); 150: cleanup(); 151: } 152: ioerror() 153: { 154: perror("I/O error"); 155: cleanup(); 156: } 157: cleanup() 158: { unlink(rmdtemp); 159: unlink(tempfile); 160: unlock(); 161: exit(0); 162: } 163: parse() 164: { /* Parse command and carry it out */ 165: register char *p; 166: register int i; 167: int first, last; 168: char *convert(); 169: p = command; 170: switch(*p++) 171: { default: printf ("Invalid command\nCommands are:\n"); 172: printf (" headers [list]\n show [list]\n"); 173: printf (" delete [list]\n keep [list]\n"); 174: printf (" write\n abort\n"); 175: return(0); 176: case 'w': /* Write */ 177: return(1); 178: case 'a': /* Abort */ 179: cleanup(); 180: case 'h': /* Headers */ 181: case 's': /* Show */ 182: printf ("%-5s%-9s%-9s%-26s%-25s%-5s\n", 183: " No","From","To","Sent","For delivery", 184: "Flags"); 185: case 'd': /* Delete */ 186: case 'k': /* Keep */ 187: ; /* Keep C compiler happy */ 188: } 189: /* Scan over other alphabetics */ 190: while (*p >= 'a' && *p <= 'z') p++; 191: if (*p == '\0') 192: { perform(command[0],1,nrmds); 193: return(0); 194: } 195: while (p = convert(p,&first)) 196: { if (*p == ',' || *p == '\0') 197: perform(command[0],first,first); 198: else if (*p++ == '-') 199: { if ((p = convert(p,&last)) && 200: (*p == ',' || *p == '\0')) 201: perform(command[0],first,last); 202: else break; 203: } 204: else break; 205: if (*p++ == '\0') return(0); 206: } 207: printf ("Syntax error or index out of range\n"); 208: return(0); 209: } 210: perform(cmnd,first,last) 211: char cmnd; int first, last; 212: { register int i, j; 213: register char *p; 214: int k, ii; 215: j = (--first <= --last ? 1 : -1); 216: for (i = first; (i-j) != last; i =+ j) 217: { p = &hdr[i]; 218: switch(cmnd) 219: { case 'd': marks[i] =| DELETED; 220: printf("%5d Marked for deletion\n",i+1); 221: break; 222: case 'k': marks[i] =& ~DELETED; 223: printf ("%5d Kept\n",i+1); 224: break; 225: case 's': 226: case 'h': 227: printf("%c%-4d%-8s %-8s %-26.24s", 228: (marks[i]&DELETED ? '*' : ' '), i+1, 229: p->sender, p->rcvr1, ctime(p->tsent)); 230: printf ("%-25.24s%c%c\n", ctime(p->tdeliver), 231: (p->dirsize ? 'E' : ' '), 232: (p->bits&PRIORITY ? 'P' : ' ')); 233: } 234: if (cmnd == 's') 235: { getcopy(i); 236: p = rmdbuff; 237: #ifdef DEBUG 238: fprintf(stderr,"nrcvrs = %d\n",hdr[i].nrcvrs); 239: #endif DEBUG 240: for (k = hdr[i].nrcvrs; --k>0; p =+ 8) 241: printf ("%14s%s\n", " ", p); 242: if (k = hdr[i].dirsize) 243: { printf ("Directory: "); 244: /* Skip over user id byte (++p) */ 245: for(ii=0,++p;ii<k-1;ii++) 246: putchar(*p++); 247: } 248: #ifdef DEBUG 249: fprintf(stderr,"msgbytes = %d\n",hdr[i].msgbytes); 250: #endif DEBUG 251: printf ("\nMessage:\n"); 252: for(ii=0;ii<hdr[i].msgbytes;ii++) 253: putchar(*p++); 254: putchar('\n'); 255: } 256: } 257: } 258: getcopy(item) 259: { register int i; 260: register FILE *f; 261: long ftell(); 262: 263: if((f=fopen(tempfile,"r"))==0) 264: { 265: fprintf(stderr,"Cannot open %s\n",tempfile); 266: cleanup(); 267: } 268: for (i=0; i<item; i++) 269: if(fseek(f,(long)(hdr[i].nobytes-8),1)==EOF) 270: { 271: perror("fseek"); 272: cleanup(); 273: } 274: if(fread(rmdbuff,hdr[i].nobytes-8,1,f) != 1) 275: { 276: if(feof(f)) 277: { 278: fprintf(stderr,"Unexpected EOF\n"); 279: cleanup(); 280: } 281: if(ferror(f)) 282: { 283: perror("fread"); 284: cleanup(); 285: } 286: fprintf(stderr,"HUH??\n"); 287: } 288: fclose(f); 289: } 290: char *convert(pp,an) 291: char *pp; int *an; 292: { register char *p; 293: register int i; 294: p = pp; 295: for (i=0; i <= nrmds; p++) 296: { if (*p >= '0' && *p <= '9') 297: i = 10*i + *p - '0'; 298: else 299: { if (*an = i) return(p); 300: else break; 301: } 302: } 303: return(0); 304: } 305: /* Use lock file as semaphore. Can't run as superuser, so forks. */ 306: lock() 307: { register int i; 308: int x; 309: #ifdef DEBUG 310: signal(SIGHUP,SIG_IGN); 311: signal(SIGINT,SIG_IGN); 312: signal(SIGQUIT,SIG_IGN); 313: #endif DEBUG 314: if (fork()) 315: wait(&x); 316: else 317: { setuid(3); /* 3 is bin, NOT root */ 318: while ((i = creat(rmdlock,0444)) == -1) 319: sleep(5); 320: close(i); 321: exit(0); 322: } 323: } 324: unlock() 325: { unlink(rmdlock); 326: unlink(rmdtemp); 327: signal(SIGHUP,&cleanup); 328: signal(SIGINT,&cleanup); 329: signal(SIGQUIT,&cleanup); 330: } 331: equal(pp,qq) 332: char *pp, *qq; 333: { register char *p, *q; 334: register int i; 335: p = pp; 336: q = qq; 337: for (i = 8; i--; ) 338: if (*p++ != *q++) return(0); 339: return(1); 340: }