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: }

Defined functions

cleanup defined in line 157; used 18 times
convert defined in line 290; used 3 times
equal defined in line 331; used 4 times
getcopy defined in line 258; used 2 times
ioerror defined in line 152; never used
lock defined in line 306; used 4 times
main defined in line 38; never used
parse defined in line 163; used 1 times
perform defined in line 210; used 3 times
unlock defined in line 324; used 2 times

Defined variables

command defined in line 35; used 7 times
hdr defined in line 27; used 10 times
m defined in line 27; used 37 times
marks defined in line 30; used 6 times
nofile defined in line 15; used 3 times
norems defined in line 16; used 2 times
nrmds defined in line 31; used 6 times
reminders defined in line 12; used 4 times
rmdbuff defined in line 33; used 3 times
rmddata defined in line 34; used 5 times
rmdlock defined in line 11; used 2 times
rmdtemp defined in line 14; used 5 times
tempfile defined in line 13; used 6 times
user defined in line 36; used 3 times

Defined struct's

rmdblock defined in line 17; never used

Defined macros

DELETED defined in line 29; used 5 times
DIRSIZE defined in line 9; used 2 times
MAXMSG defined in line 8; used 2 times
MAXRCVRS defined in line 7; used 2 times
MAXREMS defined in line 10; used 3 times
PRIORITY defined in line 28; used 1 times
Last modified: 1981-09-29
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1282
Valid CSS Valid XHTML 1.0 Strict