1: #include "parms.h"
   2: #include "structs.h"
   3: 
   4: #ifdef  RCSIDENT
   5: static char rcsid[] = "$Header: archiver.c,v 1.7.0.6 86/01/25 22:54:08 notes Rel $";
   6: #endif	RCSIDENT
   7: 
   8: /*
   9:  *	archiver - archives a notesfile. Takes all articles older
  10:  *	than 'daysold' days and places them, in generic format, in
  11:  *	a sub-directory in the archie directory. The files are marked
  12:  *	by the time that they were created.
  13:  *	The deleteonly parameter is normally zero. If it is non-zero,
  14:  *	no archive is taken; the old notes are merely thrown away.
  15:  *
  16:  *	Ray Essick			March 1982
  17:  *
  18:  *	modified so that could also toggle on the director message.
  19:  *	in addition to the days untouched.
  20:  *				Ray Essick	June 1982
  21:  *
  22:  *	Now grabs an expiration threshold and a "working set size"
  23:  *	from the notesfile itself.  If zero, the values passed
  24:  *	in as paramaters are used.
  25:  */
  26: 
  27: archiver (nfname, daysold, worksetsize, deleteonly, dirmsgflag)
  28: char   *nfname;
  29: int     daysold;
  30: int     worksetsize;
  31: int     deleteonly;
  32: int     dirmsgflag;
  33: {
  34:     struct io_f io,
  35:                 archio;
  36:     struct when_f   zaptime;                /* boundary time */
  37:     struct note_f   note;
  38:     struct note_f   note2;
  39:     int     i,
  40:             ncount,
  41:             rcount;
  42:     int     dnotes,                 /* duplicates */
  43:             dresps,                 /* in the archive */
  44:             adopts;                 /* and adoptions */
  45:     int     deletable;                  /* how many can zap */
  46:     int     presps;
  47:     char    line[WDLEN];
  48:     char    archdest[WDLEN];                /* target notesfile */
  49:     char    archbase[WDLEN];                /* target directory */
  50:     char    archend[WDLEN];             /* and nf name */
  51:     char    timeline[DATELEN];
  52:     char   *endname;
  53:     FILE * log;
  54:     int     wasopen;
  55:     int     locktarget;                 /* whether to */
  56:     struct daddr_f  where;
  57:     int     rnum;                   /* copy responses */
  58:     int     newnum;                 /* note place in arch */
  59:     int     rblock,
  60:             roffset;
  61:     struct resp_f   resp;
  62:     FILE * txtfile;                 /* for saving text */
  63:     char    txtfn[WDLEN];               /* its name */
  64:     int     dup_place;                  /* is in archive? */
  65:     int     dup_resp;                   /* dup supression */
  66: 
  67:     if (init (&io, nfname) < 0)
  68:     return (-1);                    /* no notesfile */
  69: 
  70: 
  71:     if (allow (&io, DRCTOK) == 0 && globuid != Notesuid)
  72:     {
  73:     closenf (&io);
  74:     printf ("Archiver: %s: You don't have permission to archive\n",
  75:         io.fullname);
  76:     fflush (stdout);
  77:     return (-1);
  78:     }
  79: 
  80:     if (io.descr.d_stat & ISARCH)           /* can't archive an archive */
  81:     {
  82:     closenf (&io);
  83:     printf ("Archiver: %s: You can't archive an archive\n", io.fullname);
  84:     fflush (stdout);
  85:     return (-1);
  86:     }
  87: 
  88: /*
  89:  *	select the archive name
  90:  */
  91: 
  92:     switch (nfalias (io.fullname, archdest, ARCHALIAS))
  93:     {
  94:     case -1:                    /* no file */
  95:     case 0:                     /* no match */
  96:         if (*nfname == '/')             /* absolute path name */
  97:         {
  98:         strcpy (archend, io.nf);        /* get nf */
  99:         strcpy (archbase, ARCHDIR);     /* base directory */
 100:         printf ("Archiver: WARNING: possible naming conflict in %s (%s)\n",
 101:             nfname, io.fullname);
 102:         fflush (stdout);
 103:         }
 104:         else
 105:         {
 106:         strcpy (archend, io.nf);
 107:         strcpy (archbase, ARCHDIR);     /* base directory */
 108:         }
 109:         break;
 110: 
 111:     case 1:                     /* an alias! */
 112:         if (archdest[0] != '/')         /* expand it */
 113:         {
 114:         strcpy (archbase, ARCHDIR);
 115:         strcpy (archend, archdest);     /* hold it */
 116:         }
 117:         else
 118:         {
 119:         endname = rindex (archdest, '/');
 120:         *endname++ = '\0';          /* split */
 121:         strcpy (archbase, archdest);        /* directory */
 122:         strcpy (archend, endname);      /* and nf */
 123:         }
 124:         break;
 125: 
 126:     }
 127: 
 128:     sprintf (archdest, "%s/%s", archbase, archend); /* full name */
 129:     sprintf (txtfn, "/tmp/nfa%d", getpid ());       /* hold texts */
 130:     ncount = rcount = 0;                /* count archived */
 131:     dnotes = dresps = adopts = 0;           /* duplicates */
 132:     locktarget = 0;                 /* changed if should */
 133: 
 134: /*
 135:  *	check notesfile specific thresholds, sizes and other options
 136:  */
 137: 
 138:     if (io.descr.d_archtime == NEVER)           /* don't archive */
 139:     {
 140:     printf ("Archiver: %s has archive threshold of `never'\n",
 141:         nfname);
 142:     fflush (stdout);
 143:     goto docompress;                /* compress anyway */
 144:     }
 145: 
 146:     if (io.descr.d_archtime != 0)           /* non-default */
 147:     {
 148:     daysold = (int) io.descr.d_archtime;        /* use this one */
 149:     printf ("Archiver: %s specifies threshold of %d days\n",
 150:         nfname, daysold);
 151:     fflush (stdout);
 152:     }
 153: 
 154:     if (io.descr.d_workset != 0)
 155:     {
 156:     worksetsize = (int) io.descr.d_workset;
 157:     printf ("Archiver: %s specifies working set size of %d\n",
 158:         nfname, worksetsize);
 159:     fflush (stdout);
 160:     }
 161: 
 162:     if (io.descr.d_dmesgstat != DIRDFLT)        /* specific */
 163:     {
 164:     dirmsgflag = (int) io.descr.d_dmesgstat;    /* set it */
 165:     printf ("Archiver: %s specifies dirmsg status of %s for expiring\n",
 166:         nfname,
 167:         dirmsgflag == DIRON ? "ON" :
 168:         dirmsgflag == DIROFF ? "OFF" :
 169:         dirmsgflag == DIRANYON ? "ANYON" :
 170:         "NOCARE");
 171:     fflush (stdout);
 172:     }
 173: 
 174:     if (io.descr.d_archkeep != KEEPDFLT)        /* keep/delete */
 175:     {
 176:     if (io.descr.d_archkeep == KEEPYES)
 177:         deleteonly = 0;
 178:     else
 179:         deleteonly = 1;
 180:     printf ("Archiver: %s specifies %s expired notes\n",
 181:         nfname,
 182:         deleteonly ? "deleting" : "archiving");
 183:     fflush (stdout);
 184:     }
 185: 
 186:     deletable = ((int) io.descr.d_nnote) - ((int) io.descr.d_delnote) - worksetsize;
 187:     if (deletable <= 0)                 /* candidates? */
 188:     {
 189:     if (io.descr.d_nnote - io.descr.d_delnote > 0)  /* only if non-empty */
 190:     {
 191:         printf ("Archiver: %s: %d notes <= working set size of %d\n",
 192:             nfname,
 193:             io.descr.d_nnote - io.descr.d_delnote,
 194:             worksetsize);
 195:         fflush (stdout);
 196:     }
 197:     goto docompress;
 198:     }
 199: 
 200:     gettime (&zaptime);                 /* threshold */
 201:     zaptime.w_gmttime -= 60L * 60L * 24L * ((long) daysold);/* internal */
 202:     maketime (&zaptime, zaptime.w_gmttime);     /* re-format */
 203: 
 204: 
 205:     if (!deleteonly)
 206:     {
 207:     if (init (&archio, archdest) < 0)       /* not already */
 208:     {
 209:         printf ("Archiver creating archive notesfile %s\n", archdest);
 210:         fflush (stdout);
 211:         if (buildnf (archend, archbase, 0, 0, 0) < 0)/* make one */
 212:         {
 213:         printf ("Archiver: Problems creating %s for archival\n",
 214:             archdest);
 215:         fflush (stdout);
 216:         goto docompress;
 217:         }
 218:         if (init (&archio, archdest) < 0)       /* and open it */
 219:         {
 220:         printf ("Archiver: Problems opening %s for archival\n",
 221:             archdest);
 222:         fflush (stdout);
 223:         goto docompress;
 224:         }
 225:         locknf (&archio, DSCRLOCK);         /* watch conflicts */
 226:         getdscr (&archio, &archio.descr);
 227:         archio.descr.d_stat |= ISARCH + OPEN;
 228:         putdscr (&archio, &archio.descr);
 229:         unlocknf (&archio, DSCRLOCK);
 230:         /*
 231: 	     *	Copy the active notesfile's access list to
 232: 	     *	the archive notesfile.
 233: 	     */
 234:         {
 235: #ifdef  FASTFORK
 236:         char    old[WDLEN];
 237:         char    new[WDLEN];
 238:         sprintf (old, "%s/%s/%s", io.basedir, io.nf, ACCESS);
 239:         sprintf (new, "%s/%s/%s", archio.basedir, archio.nf, ACCESS);
 240:         dounix (0, 0, "/bin/cp", old, new, 0, 0);
 241: #else   ! FASTFORK
 242:         char    cmdline[WDLEN + WDLEN + 32];
 243:         sprintf (cmdline, "%s %s/%s/%s %s/%s/%s",
 244:             "/bin/cp",
 245:             io.basedir, io.nf, ACCESS,
 246:             archio.basedir, archio.nf, ACCESS);
 247:         dounix (cmdline, 0, 0);
 248: #endif	! FASTFORK
 249:         }
 250:     }
 251: 
 252:     locktarget = strcmp (io.nf, archio.nf);     /* lock if differ */
 253: 
 254: 
 255:     if (!(archio.descr.d_stat & ISARCH))        /* into archive? */
 256:     {
 257:         printf ("Archiver: %s: Target %s is not an archive\n",
 258:             nfname, archdest);
 259:         fflush (stdout);
 260:         closenf (&archio);              /* close that */
 261:         goto docompress;                /* compress him anyway */
 262:     }
 263:     }
 264: 
 265: 
 266: #ifdef OLDGROUP
 267: /*
 268:  *	This code looks at the directory to see if the notesfile
 269:  *	has been idle long enough to be deleted.
 270:  *
 271:  *	This code hasn't been tested by me. It works in the
 272:  *	Salkind/Spickelmier version.
 273:  *
 274:  *	Should stuff a "wait-till-expire" in the master descriptor
 275:  *	of each notesfile so "junk" ones can expire faster or
 276:  *	something like that.  Essentially we want the age at which
 277:  *	the notesfile is deleted to be grabbed from the notesfile
 278:  *	itself.
 279:  *
 280:  *	My personal opinion is that they shouldn't disappear
 281:  *	auto-magically
 282:  *		NOTE: this probably no longer works with the
 283:  *		changes I've made to archiving.   (Dec '83)
 284:  *
 285:  *	N.B. Need some locking in here
 286:  */
 287: 
 288:     /* delete inactive groups - RLS 1/8/83 */
 289: 
 290:     sprintf (line, "%s/%s", MSTDIR, nfname);
 291:     stat (line, &buf);
 292:     current = time (0);
 293:     if (current - buf.st_mtime > 60 * 60 * 24 * (OLDGROUP - daysold))
 294:     {
 295:     finish (&io);
 296: 
 297:     sprintf (line, "/bin/rm -rf %s/%s", MSTDIR, nfname);
 298:     system (line);
 299: 
 300:     gettime (&zaptime);
 301:     sprdate (&zaptime, timeline);
 302: 
 303:     /* message in nfmaint */
 304:     sprintf (line, "Archiver: removed %s\n", nfname);
 305:     nfcomment (NOSUCHWARN, line, line, 0, 0);
 306: 
 307:     sprintf (line, "%s/%s/%s", MSTDIR, UTILITY, NETLOG);
 308:     x ((log = fopen (line, "a")) == NULL, "archiver: no logfile");
 309:     fprintf (log, "Archiver: deleted %s at %s\n", nfname, timeline);
 310:     printf ("Archiver: deleted %s at %s\n", nfname, timeline);
 311:     fclose (log);
 312:     fflush (stdout);
 313:     return (0);
 314:     }
 315: #endif	OLDGROUP
 316: 
 317: 
 318:     locknf (&io, DSCRLOCK);             /* MUTEX */
 319:     if (locktarget)                 /* and target */
 320:     locknf (&archio, DSCRLOCK);
 321:     getdscr (&io, &io.descr);
 322:     wasopen = io.descr.d_stat & OPEN;           /* hold this */
 323:     io.descr.d_stat &= NOT OPEN;            /* privacy */
 324:     putdscr (&io, &io.descr);
 325: 
 326:     for (i = 1; i <= io.descr.d_nnote && deletable; i++)
 327:     {
 328:     getnrec (&io, i, &note);
 329:     if (note.n_stat & DELETED)          /* already gone */
 330:         continue;
 331:     if (inorder (&zaptime, &note.n_lmod))       /* check times */
 332:         continue;                   /* too recent */
 333:     if (dirmsgflag == DIROFF && (note.n_stat & DIRMES))
 334:         continue;                   /* only dir off */
 335:     if (dirmsgflag == DIRON && (note.n_stat & DIRMES) == 0)
 336:         continue;                   /* only dir on */
 337:     if (dirmsgflag == DIRANYON)         /* any w/dir on */
 338:     {
 339:         /*
 340: 	     * if anything in the note string has dir message on,
 341: 	     * expire the sucker.
 342: 	     */
 343:         if (note.n_stat & DIRMES)           /* note has dir */
 344:         goto killit;                /* so expire it */
 345:         for (rnum = 1; rnum <= note.n_nresp; rnum++)
 346:         {                       /* for each response */
 347:         if (lrsp (&io, i, rnum, &resp, &roffset, &rblock) != 0)
 348:             break;              /* busted resp chain */
 349:         if (resp.r_stat[roffset] & DIRMES)  /* is dir message */
 350:             goto killit;            /* so expire */
 351:         }
 352:         continue;                   /* do not expire */
 353:     }
 354: killit:                         /* goto target */
 355:     presps = note.n_nresp;              /* response count */
 356:     if (!deleteonly)                /* save it? */
 357:     {
 358:         /*
 359: 	     * check to see if this one is already in the archive
 360: 	     */
 361:         dup_place = chknote (&archio, &note.n_id, &note2);/* already there? */
 362:         if (dup_place == 0)             /* not there */
 363:         {
 364:         /*
 365: 		 *	This code copied almost verbatim from compression routines
 366: 		 */
 367: #ifdef  notdef
 368:         x ((txtfile = fopen (txtfn, "w")) == NULL, "archiver:bad txt");
 369:         pageout (&io, &note.n_addr, txtfile);
 370:         fclose (txtfile);
 371:         x ((txtfile = fopen (txtfn, "r")) == NULL, "archiver: txt read");
 372:         pagein (&archio, txtfile, &where);
 373:         fclose (txtfile);
 374: #else
 375:         pagemove (&io, &note.n_addr, &archio, &where, LOCKIT);
 376: #endif
 377:         newnum = putnote (&archio, &where, note.ntitle, note.n_stat, &note,
 378:             &note.n_auth, NOPOLICY, NOLOCKIT, NOADDID, note.n_from, NOADDTIME);
 379:         getnrec (&archio, newnum, &note2);  /* get copy */
 380:         }
 381:         else
 382:         {
 383:         if ((note2.n_stat & ORPHND) &&      /* archived is foster */
 384:             !(note.n_stat & ORPHND))    /* and active isn't */
 385:         {
 386: #ifdef  notdef
 387:             x ((txtfile = fopen (txtfn, "w")) == NULL, "archiver:bad txt");
 388:             pageout (&io, &note.n_addr, txtfile);
 389:             fclose (txtfile);
 390:             x ((txtfile = fopen (txtfn, "r")) == NULL, "archiver: txt read");
 391:             pagein (&archio, txtfile, &where);
 392:             fclose (txtfile);
 393: #else
 394:             pagemove (&io, &note.n_addr, &archio, &where, LOCKIT);
 395: #endif
 396: 
 397:             note.n_nresp = note2.n_nresp;   /* save resp chain */
 398:             note.n_rindx = note2.n_rindx;
 399:             note.n_addr = where;        /* get text pointer */
 400:             putnrec (&archio, dup_place, &note);/* replace descriptor */
 401:             note2 = note;           /* save good copy */
 402:             adopts++;               /* count 'em */
 403:         }
 404:         else
 405:         {
 406:             dnotes++;               /* count duplicate */
 407:         }
 408:         newnum = dup_place;         /* for linking resps */
 409:         }
 410: 
 411:         for (rnum = 1; rnum <= presps; rnum++)  /* process responses */
 412:         {
 413:         if (lrsp (&io, i, rnum, &resp, &roffset, &rblock) != 0)
 414:             break;              /* bad response chain - drop rest */
 415:         if (dup_place)              /* better check... */
 416:         {
 417:             dup_resp = chkresp (&archio, &resp.r_id[roffset], &note2, newnum);
 418:             if (dup_resp)           /* already there */
 419:             {
 420:             dresps++;           /* count doubles */
 421:             continue;           /* skip this response */
 422:             }
 423:         }
 424: #ifdef  notdef
 425:         x ((txtfile = fopen (txtfn, "w")) == NULL, "compress:bad txt");
 426:         pageout (&io, &resp.r_addr[roffset], txtfile);
 427:         fclose (txtfile);
 428:         x ((txtfile = fopen (txtfn, "r")) == NULL, "compress: bad txt read");
 429:         pagein (&archio, txtfile, &where);
 430:         fclose (txtfile);
 431: #else
 432:         pagemove (&io, &resp.r_addr[roffset], &archio, &where, LOCKIT);
 433: #endif
 434:         putresp (&archio, &where, resp.r_stat[roffset], newnum, &resp.r_when[roffset],
 435:             &resp.r_auth[roffset], &note, NOLOCKIT, &resp.r_id[roffset],
 436:             NOADDID, resp.r_from[roffset], NOADDTIME, &resp.r_rcvd[roffset]);
 437:         }
 438:     }
 439:     delnote (&io, i, NOLOCKIT);         /* delete entry */
 440:     ncount++;
 441:     rcount += presps;               /* and responses */
 442:     deletable--;                    /* one down */
 443:     }
 444: 
 445:     unlocknf (&io, DSCRLOCK);               /* Un MUTEX */
 446:     if (locktarget)                 /* and the target */
 447:     unlocknf (&archio, DSCRLOCK);
 448: 
 449:     if (!deleteonly)
 450:     {
 451:     finish (&archio);               /* close target */
 452:     unlink (txtfn);                 /* don't litter */
 453:     }
 454: 
 455: /*
 456:  *	Time to compress the notesfile and eliminate those
 457:  *	unsightly holes in the data structure.
 458:  */
 459: docompress:
 460: 
 461:     locknf (&io, DSCRLOCK);             /* MUTEX */
 462:     if (io.descr.d_nnote != 0)              /* non-empty */
 463:     {
 464:     if (io.descr.d_delnote != 0 || io.descr.d_delresp != 0)
 465:     {                       /* has holes */
 466:         int     nnote,
 467:                 nresp;
 468:         compress (&io, NOLOCKIT, 0, &nnote, &nresp);
 469:         printf ("Archiver: %s contains (%d,%d) after compress\n",
 470:             nfname, nnote, nresp);
 471:         fflush (stdout);
 472:     }
 473:     else                        /* no holes so */
 474:     {                       /* don't compress */
 475:         printf ("Archiver: %s already compressed\n", nfname);
 476:         fflush (stdout);
 477:     }
 478:     }
 479:     else                        /* nothing there to */
 480:     {                           /* compress */
 481:     printf ("Archiver: %s is empty.\n", nfname);
 482:     fflush (stdout);
 483:     }
 484: 
 485: 
 486:     if (wasopen)                    /* if it was already */
 487:     {
 488:     getdscr (&io, &io.descr);           /* open season */
 489:     io.descr.d_stat |= OPEN;
 490:     putdscr (&io, &io.descr);           /* replace in file */
 491:     }
 492: 
 493:     unlocknf (&io, DSCRLOCK);               /* all done with this */
 494:     finish (&io);                   /* and close the notesfile */
 495: 
 496:     gettime (&zaptime);
 497:     sprdate (&zaptime, timeline);
 498:     if (ncount)                     /* log only if did somethine */
 499:     {
 500:     sprintf (line, "%s/%s/%s", Mstdir, UTILITY, NETLOG);
 501:     x ((log = fopen (line, "a")) == NULL, "archiver: no logfile");
 502:     if (!deleteonly)
 503:         fprintf (log, "%s: archived (%d,%d) [%d,%d dups, %d adopted] into %s at %s\n",
 504:             nfname, ncount, rcount, dnotes, dresps, adopts, archdest, timeline);
 505:     else
 506:         fprintf (log, "%s: Archiver deleted (%d,%d) at %s\n",
 507:             nfname, ncount, rcount, timeline);
 508:     fclose (log);
 509:     }
 510: 
 511:     if (!deleteonly)
 512:     {
 513:     if (ncount)
 514:         printf ("Archiver: %s: (%d,%d) [%d,%d dups, %d adoptions] into %s at %s\n",
 515:             nfname, ncount, rcount, dnotes, dresps, adopts, archdest, timeline);
 516:     else
 517:         printf ("Archiver: %s: no notes archived\n",
 518:             nfname);
 519:     }
 520:     else
 521:     printf ("Archiver: %s: deleted (%d,%d) at %s\n",
 522:         nfname, ncount, rcount, timeline);
 523:     fflush (stdout);
 524:     return (0);                     /* and return */
 525: 
 526: }

Defined functions

archiver defined in line 27; used 1 times

Defined variables

rcsid defined in line 5; never used
Last modified: 1986-01-26
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3861
Valid CSS Valid XHTML 1.0 Strict