1: #include "parms.h"
   2: #include "structs.h"
   3: 
   4: #ifdef  RCSIDENT
   5: static char rcsid[] = "$Header: archiver.c,v 1.7.0.4 85/06/05 14:16:24 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:         "NOCARE");
 170:     fflush (stdout);
 171:     }
 172: 
 173:     if (io.descr.d_archkeep != KEEPDFLT)        /* keep/delete */
 174:     {
 175:     if (io.descr.d_archkeep == KEEPYES)
 176:         deleteonly = 0;
 177:     else
 178:         deleteonly = 1;
 179:     printf ("Archiver: %s specifies %s expired notes\n",
 180:         nfname,
 181:         deleteonly ? "deleting" : "archiving");
 182:     fflush (stdout);
 183:     }
 184: 
 185:     deletable = ((int) io.descr.d_nnote) - ((int) io.descr.d_delnote) - worksetsize;
 186:     if (deletable <= 0)                 /* candidates? */
 187:     {
 188:     if (io.descr.d_nnote - io.descr.d_delnote > 0)  /* only if non-empty */
 189:     {
 190:         printf ("Archiver: %s: %d notes <= working set size of %d\n",
 191:             nfname,
 192:             io.descr.d_nnote - io.descr.d_delnote,
 193:             worksetsize);
 194:         fflush (stdout);
 195:     }
 196:     goto docompress;
 197:     }
 198: 
 199:     gettime (&zaptime);                 /* threshold */
 200:     zaptime.w_gmttime -= 60L * 60L * 24L * ((long) daysold);/* internal */
 201:     maketime (&zaptime, zaptime.w_gmttime);     /* re-format */
 202: 
 203: 
 204:     if (!deleteonly)
 205:     {
 206:     if (init (&archio, archdest) < 0)       /* not already */
 207:     {
 208:         printf ("Archiver creating archive notesfile %s\n", archdest);
 209:         fflush (stdout);
 210:         if (buildnf (archend, archbase, 0, 0, 0) < 0)/* make one */
 211:         {
 212:         printf ("Archiver: Problems creating %s for archival\n",
 213:             archdest);
 214:         fflush (stdout);
 215:         goto docompress;
 216:         }
 217:         if (init (&archio, archdest) < 0)       /* and open it */
 218:         {
 219:         printf ("Archiver: Problems opening %s for archival\n",
 220:             archdest);
 221:         fflush (stdout);
 222:         goto docompress;
 223:         }
 224:         locknf (&archio, DSCRLOCK);         /* watch conflicts */
 225:         getdscr (&archio, &archio.descr);
 226:         archio.descr.d_stat |= ISARCH + OPEN;
 227:         putdscr (&archio, &archio.descr);
 228:         unlocknf (&archio, DSCRLOCK);
 229:         /*
 230: 	     *	Copy the active notesfile's access list to
 231: 	     *	the archive notesfile.
 232: 	     */
 233:         {
 234: #ifdef  FASTFORK
 235:         char    old[WDLEN];
 236:         char    new[WDLEN];
 237:         sprintf (old, "%s/%s/%s", io.basedir, io.nf, ACCESS);
 238:         sprintf (new, "%s/%s/%s", archio.basedir, archio.nf, ACCESS);
 239:         dounix (0, 0, "/bin/cp", old, new, 0, 0);
 240: #else   ! FASTFORK
 241:         char    cmdline[WDLEN + WDLEN + 10];
 242:         sprintf (cmdline, "%s %s/%s/%s %s/%s/%s",
 243:             "/bin/cp",
 244:             io.basedir, io.nf, ACCESS,
 245:             archio.basedir, archio.nf, ACCESS);
 246:         dounix (cmdline, 0, 0);
 247: #endif	! FASTFORK
 248:         }
 249:     }
 250: 
 251:     locktarget = strcmp (io.nf, archio.nf);     /* lock if differ */
 252: 
 253: 
 254:     if (!(archio.descr.d_stat & ISARCH))        /* into archive? */
 255:     {
 256:         printf ("Archiver: %s: Target %s is not an archive\n",
 257:             nfname, archdest);
 258:         fflush (stdout);
 259:         closenf (&archio);              /* close that */
 260:         goto docompress;                /* compress him anyway */
 261:     }
 262:     }
 263: 
 264: 
 265: #ifdef OLDGROUP
 266: /*
 267:  *	This code looks at the directory to see if the notesfile
 268:  *	has been idle long enough to be deleted.
 269:  *
 270:  *	This code hasn't been tested by me. It works in the
 271:  *	Salkind/Spickelmier version.
 272:  *
 273:  *	Should stuff a "wait-till-expire" in the master descriptor
 274:  *	of each notesfile so "junk" ones can expire faster or
 275:  *	something like that.  Essentially we want the age at which
 276:  *	the notesfile is deleted to be grabbed from the notesfile
 277:  *	itself.
 278:  *
 279:  *	My personal opinion is that they shouldn't disappear
 280:  *	auto-magically
 281:  *		NOTE: this probably no longer works with the
 282:  *		changes I've made to archiving.   (Dec '83)
 283:  *
 284:  *	N.B. Need some locking in here
 285:  */
 286: 
 287:     /* delete inactive groups - RLS 1/8/83 */
 288: 
 289:     sprintf (line, "%s/%s", MSTDIR, nfname);
 290:     stat (line, &buf);
 291:     current = time (0);
 292:     if (current - buf.st_mtime > 60 * 60 * 24 * (OLDGROUP - daysold))
 293:     {
 294:     finish (&io);
 295: 
 296:     sprintf (line, "/bin/rm -rf %s/%s", MSTDIR, nfname);
 297:     system (line);
 298: 
 299:     gettime (&zaptime);
 300:     sprdate (&zaptime, timeline);
 301: 
 302:     /* message in nfmaint */
 303:     sprintf (line, "Archiver: removed %s\n", nfname);
 304:     nfcomment (NOSUCHWARN, line, line, 0, 0);
 305: 
 306:     sprintf (line, "%s/%s/%s", MSTDIR, UTILITY, NETLOG);
 307:     x ((log = fopen (line, "a")) == NULL, "archiver: no logfile");
 308:     fprintf (log, "Archiver: deleted %s at %s\n", nfname, timeline);
 309:     printf ("Archiver: deleted %s at %s\n", nfname, timeline);
 310:     fclose (log);
 311:     fflush (stdout);
 312:     return (0);
 313:     }
 314: #endif	OLDGROUP
 315: 
 316: 
 317:     locknf (&io, DSCRLOCK);             /* MUTEX */
 318:     if (locktarget)                 /* and target */
 319:     locknf (&archio, DSCRLOCK);
 320:     getdscr (&io, &io.descr);
 321:     wasopen = io.descr.d_stat & OPEN;           /* hold this */
 322:     io.descr.d_stat &= NOT OPEN;            /* privacy */
 323:     putdscr (&io, &io.descr);
 324: 
 325:     for (i = 1; i <= io.descr.d_nnote && deletable; i++)
 326:     {
 327:     getnrec (&io, i, &note);
 328:     if (note.n_stat & DELETED)
 329:         continue;                   /* gone already */
 330:     if (dirmsgflag == DIROFF && (note.n_stat & DIRMES))
 331:         continue;                   /* don't if dir on */
 332:     if (dirmsgflag == DIRON && (note.n_stat & DIRMES) == 0)
 333:         continue;                   /* don't if dir off */
 334:     if (inorder (&zaptime, &note.n_lmod))
 335:         continue;                   /* too recent */
 336:     presps = note.n_nresp;              /* response count */
 337:     if (!deleteonly)                /* save it? */
 338:     {
 339:         /*
 340: 	     * check to see if this one is already in the archive
 341: 	     */
 342:         dup_place = chknote (&archio, &note.n_id, &note2);/* already there? */
 343:         if (dup_place == 0)             /* not there */
 344:         {
 345:         /*
 346: 		 *	This code copied almost verbatim from compression routines
 347: 		 */
 348: #ifdef  notdef
 349:         x ((txtfile = fopen (txtfn, "w")) == NULL, "archiver:bad txt");
 350:         pageout (&io, &note.n_addr, txtfile);
 351:         fclose (txtfile);
 352:         x ((txtfile = fopen (txtfn, "r")) == NULL, "archiver: txt read");
 353:         pagein (&archio, txtfile, &where);
 354:         fclose (txtfile);
 355: #else
 356:         pagemove (&io, &note.n_addr, &archio, &where, LOCKIT);
 357: #endif
 358:         newnum = putnote (&archio, &where, note.ntitle, note.n_stat, &note,
 359:             &note.n_auth, NOPOLICY, NOLOCKIT, NOADDID, note.n_from, NOADDTIME);
 360:         getnrec (&archio, newnum, &note2);  /* get copy */
 361:         }
 362:         else
 363:         {
 364:         if ((note2.n_stat & ORPHND) &&      /* archived is foster */
 365:             !(note.n_stat & ORPHND))    /* and active isn't */
 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: 
 378:             note.n_nresp = note2.n_nresp;   /* save resp chain */
 379:             note.n_rindx = note2.n_rindx;
 380:             note.n_addr = where;        /* get text pointer */
 381:             putnrec (&archio, dup_place, &note);/* replace descriptor */
 382:             note2 = note;           /* save good copy */
 383:             adopts++;               /* count 'em */
 384:         }
 385:         else
 386:         {
 387:             dnotes++;               /* count duplicate */
 388:         }
 389:         newnum = dup_place;         /* for linking resps */
 390:         }
 391: 
 392:         for (rnum = 1; rnum <= presps; rnum++)  /* process responses */
 393:         {
 394:         if (lrsp (&io, i, rnum, &resp, &roffset, &rblock) != 0)
 395:             break;              /* bad response chain - drop rest */
 396:         if (dup_place)              /* better check... */
 397:         {
 398:             dup_resp = chkresp (&archio, &resp.r_id[roffset], &note2, newnum);
 399:             if (dup_resp)           /* already there */
 400:             {
 401:             dresps++;           /* count doubles */
 402:             continue;           /* skip this response */
 403:             }
 404:         }
 405: #ifdef  notdef
 406:         x ((txtfile = fopen (txtfn, "w")) == NULL, "compress:bad txt");
 407:         pageout (&io, &resp.r_addr[roffset], txtfile);
 408:         fclose (txtfile);
 409:         x ((txtfile = fopen (txtfn, "r")) == NULL, "compress: bad txt read");
 410:         pagein (&archio, txtfile, &where);
 411:         fclose (txtfile);
 412: #else
 413:         pagemove (&io, &resp.r_addr[roffset], &archio, &where, LOCKIT);
 414: #endif
 415:         putresp (&archio, &where, resp.r_stat[roffset], newnum, &resp.r_when[roffset],
 416:             &resp.r_auth[roffset], &note, NOLOCKIT, &resp.r_id[roffset],
 417:             NOADDID, resp.r_from[roffset], NOADDTIME, &resp.r_rcvd[roffset]);
 418:         }
 419:     }
 420:     delnote (&io, i, NOLOCKIT);         /* delete entry */
 421:     ncount++;
 422:     rcount += presps;               /* and responses */
 423:     deletable--;                    /* one down */
 424:     }
 425: 
 426:     unlocknf (&io, DSCRLOCK);               /* Un MUTEX */
 427:     if (locktarget)                 /* and the target */
 428:     unlocknf (&archio, DSCRLOCK);
 429: 
 430:     if (!deleteonly)
 431:     {
 432:     finish (&archio);               /* close target */
 433:     unlink (txtfn);                 /* don't litter */
 434:     }
 435: 
 436: /*
 437:  *	Time to compress the notesfile and eliminate those
 438:  *	unsightly holes in the data structure.
 439:  */
 440: docompress:
 441: 
 442:     locknf (&io, DSCRLOCK);             /* MUTEX */
 443:     if (io.descr.d_nnote != 0)              /* non-empty */
 444:     {
 445:     if (io.descr.d_delnote != 0 || io.descr.d_delresp != 0)
 446:     {                       /* has holes */
 447:         int     nnote,
 448:                 nresp;
 449:         compress (&io, NOLOCKIT, 0, &nnote, &nresp);
 450:         printf ("Archiver: %s contains (%d,%d) after compress\n",
 451:             nfname, nnote, nresp);
 452:         fflush (stdout);
 453:     }
 454:     else                        /* no holes so */
 455:     {                       /* don't compress */
 456:         printf ("Archiver: %s already compressed\n", nfname);
 457:         fflush (stdout);
 458:     }
 459:     }
 460:     else                        /* nothing there to */
 461:     {                           /* compress */
 462:     printf ("Archiver: %s is empty.\n", nfname);
 463:     fflush (stdout);
 464:     }
 465: 
 466: 
 467:     if (wasopen)                    /* if it was already */
 468:     {
 469:     getdscr (&io, &io.descr);           /* open season */
 470:     io.descr.d_stat |= OPEN;
 471:     putdscr (&io, &io.descr);           /* replace in file */
 472:     }
 473: 
 474:     unlocknf (&io, DSCRLOCK);               /* all done with this */
 475:     finish (&io);                   /* and close the notesfile */
 476: 
 477:     gettime (&zaptime);
 478:     sprdate (&zaptime, timeline);
 479:     if (ncount)                     /* log only if did somethine */
 480:     {
 481:     sprintf (line, "%s/%s/%s", Mstdir, UTILITY, NETLOG);
 482:     x ((log = fopen (line, "a")) == NULL, "archiver: no logfile");
 483:     if (!deleteonly)
 484:         fprintf (log, "%s: archived (%d,%d) [%d,%d dups, %d adopted] into %s at %s\n",
 485:             nfname, ncount, rcount, dnotes, dresps, adopts, archdest, timeline);
 486:     else
 487:         fprintf (log, "%s: Archiver deleted (%d,%d) at %s\n",
 488:             nfname, ncount, rcount, timeline);
 489:     fclose (log);
 490:     }
 491: 
 492:     if (!deleteonly)
 493:     {
 494:     if (ncount)
 495:         printf ("Archiver: %s: (%d,%d) [%d,%d dups, %d adoptions] into %s at %s\n",
 496:             nfname, ncount, rcount, dnotes, dresps, adopts, archdest, timeline);
 497:     else
 498:         printf ("Archiver: %s: no notes archived\n",
 499:             nfname);
 500:     }
 501:     else
 502:     printf ("Archiver: %s: deleted (%d,%d) at %s\n",
 503:         nfname, ncount, rcount, timeline);
 504:     fflush (stdout);
 505:     return (0);                     /* and return */
 506: 
 507: }

Defined functions

archiver defined in line 27; used 1 times

Defined variables

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