home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3154 < prev    next >
Encoding:
Text File  |  1991-04-02  |  33.4 KB  |  1,170 lines

  1. Newsgroups: alt.sources
  2. From: admerlev@immd4.informatik.uni-erlangen.de (Arnd Merlevede)
  3. Subject: Re: reap(8): expire news as space needed
  4. Message-ID: <1991Apr1.190028.14519@informatik.uni-erlangen.de>
  5. Date: Mon, 1 Apr 1991 19:00:28 GMT
  6.  
  7. dt@yenta.alb.nm.us (David B. Thomas) writes:
  8.  
  9. hallo andreas, vielleicht interessiert Dich
  10. die follgende Msg falls Dus nicht selbst gelesen hast.
  11.  
  12. Uebrigns, liegt noch die Source von nn irgendwo ?
  13. Und ist des schwer die zu installieren ? Ich wuerd sie gerne 
  14. im ET-CipPool installieren (ala faui09)
  15. ?
  16. Bis denn Arnd
  17.  
  18.  
  19. >This message contains the README, followed by the source:
  20.  
  21. >README for reap version 1.1 by David B. Thomas (dt@yenta.alb.nm.us).
  22.  
  23. >A Problem:
  24. >    News volume fluctuates wildly...sites with small disks must either
  25. >expire aggresively, often deleting more than necessary, or worry that an
  26. >unexpected huge dose of news might overfill the disk.
  27.  
  28.  
  29. >A Solution:
  30. >    Implement a tool that expires according to a user-defined scheme
  31. >until sufficient freespace is reclaimed, then stops, leaving as much
  32. >juicy news online as is feasible.  Reap does this.
  33.  
  34.  
  35. >Expire Does Two Jobs:
  36. >    Both Bnews and Cnews expires really do two jobs:
  37. >        1. trim history files
  38. >        2. delete outdated articles
  39. >Thanks to some inspired jootsing (acronym for "jumping out of the system")
  40. >by Mike Murphy (mrm@sceard.com) and others, it is more than possible to
  41. >separate those two functions.  This is, of course, in keeping with the
  42. >unix philosophy of one tool doing one job well!
  43.  
  44.  
  45. >What Reap Does:
  46. >    Reap only takes care of the second job: deleting old articles.
  47. >It works by checking freespace, and processing one line at a time from a
  48. >list of expire functions, until the desired freespace is attained.
  49. >Each expire function consists of an age limit in days (decimals okay)
  50. >and a list of newsgroups to process or not process, sys file style.  Ex:
  51.  
  52. >    .5    alt.sex.pictures,talk,!talk.bizarre,junk
  53. >    1    rec,!rec.games,!rec.humor
  54.  
  55. >This example would check freespace, and if more space is needed, expire
  56. >to .5 days everything in alt.sex.pictures, talk (except for talk.bizarre)
  57. >and junk.  Then it would stop and check freespace again.  If still more
  58. >space is needed, it would expire to 1 day everything in rec except
  59. >rec.games.* and rec.humor.*.  It's that simple.
  60.  
  61.  
  62. >Okay...So How Do I Arrange To Trim The History Files, Since Reap Can't:
  63. >    Included in this distribution is a shell script (mostly written
  64. >by Mike Murphy) to handle Cnews history files.  It shouldn't be too
  65. >difficult to do something similar for Bnews, or you can give in and use
  66. >the original expire utility with options that tell it to expire the
  67. >history files only...but I think this will be slow.  It just comes down
  68. >to removing lines from ordinary text files, based on their contents.
  69. >Murphy and I used awk.
  70.  
  71.  
  72. >But Is It Fast:
  73. >    Yes, largely because it doesn't have to do much.  Even "find | rm"
  74. >is slower because find is repeatedly exec-ing rm.  "rm -rf" has me beat,
  75. >though, I'll bet!  :-)
  76.  
  77. >    Since the functions of deleting articles and trimming history
  78. >are separate, I now run reap every six hours, but trim the history list
  79. >just once a day.  That effectively keeps my disk space up to snuff, but
  80. >only thrashes at the history file in the middle of the night.
  81.  
  82.  
  83. >Credits:
  84. >    I owe a lot to Mike Murphy for inspiring me with his "trasher"
  85. >system.  I also owe a lot to all of your netters who will flood me with
  86. >more suggestions and improvements in the coming weeks (hint, hint!).
  87.  
  88. >                        little david
  89. >                        dt@yenta.alb.nm.us
  90.  
  91. >ps - reap is freeware.  No strings(1) attached.
  92.  
  93.  
  94. >#!/bin/sh
  95. ># This is a shell archive (shar 3.44)
  96. ># made 03/28/1991 02:51 UTC by dt@yenta
  97. ># Source directory /u/dt/src/reap
  98. >#
  99. ># existing files will NOT be overwritten unless -c is specified
  100. >#
  101. ># This shar contains:
  102. ># length  mode       name
  103. ># ------ ---------- ------------------------------------------
  104. >#    934 -rw-rw-r-- Install
  105. >#    339 -rw-rw-r-- MANIFEST
  106. >#    900 -rw-rw-r-- Makefile
  107. >#   2918 -rw-rw-r-- README
  108. >#    969 -rwxrwxr-x exphist
  109. >#   3567 -rw-rw-r-- lib.c
  110. >#   1611 -rw-rw-r-- list.sample
  111. >#   2497 -rw-rw-r-- main.c
  112. >#   6129 -rw-r--r-- reap.8
  113. >#   2845 -rw-rw-r-- reap.c
  114. >#   1195 -rw-rw-r-- reap.h
  115. >#
  116. ># ============= Install ==============
  117. >if test -f 'Install' -a X"$1" != X"-c"; then
  118. >    echo 'x - skipping Install (File already exists)'
  119. >else
  120. >echo 'x - extracting Install (Text)'
  121. >sed 's/^X//' << 'SHAR_EOF' > 'Install' &&
  122. >X
  123. >To install:
  124. >X
  125. >1. Edit tops of Makefile and reap.h to fit your system.
  126. >X   [If you are installing this on a non-system-V machine, you will need
  127. >X   to rewrite the freeblox() function at the top of lib.c.  This should
  128. >X   be very easy.  Please email your working mods to me.]
  129. >2. make
  130. >3. Compose a sample function list file or use the sample provided to
  131. >X    test reap (use the -n option to avoid really removing files).
  132. >4. su and make install.
  133. >5. Arrange to trim your news system's history list regularly.  If you have
  134. >X    Cnews, try the "exphist" script provided, run from cron.  That
  135. >X    script requires that a tiny file, /usr/lib/news/histdays, containing
  136. >X    the number of days of history data to keep, or else you can hardcode
  137. >X    in your favorite number.  If you have Bnews, I don't have a nifty
  138. >X    suggestion, other than using expire(8) with a ridiculously long
  139. >X    article expire time, but a sane history expire time.
  140. >6. Arrange to run reap from cron.
  141. >SHAR_EOF
  142. >chmod 0664 Install ||
  143. >echo 'restore of Install failed'
  144. >Wc_c="`wc -c < 'Install'`"
  145. >test 934 -eq "$Wc_c" ||
  146. >    echo 'Install: original size 934, current size' "$Wc_c"
  147. >fi
  148. ># ============= MANIFEST ==============
  149. >if test -f 'MANIFEST' -a X"$1" != X"-c"; then
  150. >    echo 'x - skipping MANIFEST (File already exists)'
  151. >else
  152. >echo 'x - extracting MANIFEST (Text)'
  153. >sed 's/^X//' << 'SHAR_EOF' > 'MANIFEST' &&
  154. >Included with this distribution are:
  155. >X
  156. >README        - general description and credits
  157. >Install        - hints on how to install reap and get it going
  158. >Xexphist        - history trimmer utility for Cnews
  159. >list.sample    - sample function script file for reap
  160. >reap.8        - man page
  161. >lib.c        - source
  162. >main.c        - source
  163. >reap.c        - source
  164. >reap.h        - source
  165. >Makefile    - makefile
  166. >SHAR_EOF
  167. >chmod 0664 MANIFEST ||
  168. >echo 'restore of MANIFEST failed'
  169. >Wc_c="`wc -c < 'MANIFEST'`"
  170. >test 339 -eq "$Wc_c" ||
  171. >    echo 'MANIFEST: original size 339, current size' "$Wc_c"
  172. >fi
  173. ># ============= Makefile ==============
  174. >if test -f 'Makefile' -a X"$1" != X"-c"; then
  175. >    echo 'x - skipping Makefile (File already exists)'
  176. >else
  177. >echo 'x - extracting Makefile (Text)'
  178. >sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
  179. >#----------------------------
  180. ># parameters for installation
  181. >#----------------------------
  182. >X
  183. ># directories where manual and executable are to be installed
  184. >BINDIR = /usr/lib/newsbin/expire
  185. >MANDIR = /usr/man/man8
  186. >X
  187. ># owner, group and file mode for manual and executable
  188. >EXEOWNER = bin
  189. >EXEGROUP = bin
  190. >EXEMODE = 775
  191. >MANOWNER = bin
  192. >MANGROUP = bin
  193. >MANMODE = 664
  194. >X
  195. >X
  196. ># your favorite C compiler
  197. >#CC = cc
  198. >CC = shcc
  199. >X
  200. ># directory access functions library, if not in standard C library.
  201. >LIB = -ldirent
  202. >X
  203. >X
  204. >#-------------
  205. ># boring stuff
  206. >#-------------
  207. >X
  208. >OBJ = main.o lib.o reap.o
  209. >X
  210. >reap: $(OBJ)
  211. >X    $(CC) -s -o reap $(SHLIB) $(OBJ) $(LIB)
  212. >X
  213. >$(OBJ): reap.h
  214. >X
  215. >install: reap reap.8
  216. >X    cp reap $(BINDIR)
  217. >X    chown $(EXEOWNER) $(BINDIR)/reap
  218. >X    chgrp $(EXEGROUP) $(BINDIR)/reap
  219. >X    chmod $(EXEMODE) $(BINDIR)/reap
  220. >X    cp reap.8 $(MANDIR)
  221. >X    chmod $(MANMODE) $(MANDIR)/reap.8
  222. >X    chown $(MANOWNER) $(MANDIR)/reap.8
  223. >X    chgrp $(MANGROUP) $(MANDIR)/reap.8
  224. >SHAR_EOF
  225. >chmod 0664 Makefile ||
  226. >echo 'restore of Makefile failed'
  227. >Wc_c="`wc -c < 'Makefile'`"
  228. >test 900 -eq "$Wc_c" ||
  229. >    echo 'Makefile: original size 900, current size' "$Wc_c"
  230. >fi
  231. ># ============= README ==============
  232. >if test -f 'README' -a X"$1" != X"-c"; then
  233. >    echo 'x - skipping README (File already exists)'
  234. >else
  235. >echo 'x - extracting README (Text)'
  236. >sed 's/^X//' << 'SHAR_EOF' > 'README' &&
  237. >X
  238. >README for reap version 1.1 by David B. Thomas (dt@yenta.alb.nm.us).
  239. >X
  240. >A Problem:
  241. >X    News volume fluctuates wildly...sites with small disks must either
  242. >Xexpire aggresively, often deleting more than necessary, or worry that an
  243. >unexpected huge dose of news might overfill the disk.
  244. >X
  245. >X
  246. >A Solution:
  247. >X    Implement a tool that expires according to a user-defined scheme
  248. >until sufficient freespace is reclaimed, then stops, leaving as much
  249. >juicy news online as is feasible.  Reap does this.
  250. >X
  251. >X
  252. >Expire Does Two Jobs:
  253. >X    Both Bnews and Cnews expires really do two jobs:
  254. >X        1. trim history files
  255. >X        2. delete outdated articles
  256. >Thanks to some inspired jootsing (acronym for "jumping out of the system")
  257. >by Mike Murphy (mrm@sceard.com) and others, it is more than possible to
  258. >separate those two functions.  This is, of course, in keeping with the
  259. >unix philosophy of one tool doing one job well!
  260. >X
  261. >X
  262. >What Reap Does:
  263. >X    Reap only takes care of the second job: deleting old articles.
  264. >It works by checking freespace, and processing one line at a time from a
  265. >list of expire functions, until the desired freespace is attained.
  266. >Each expire function consists of an age limit in days (decimals okay)
  267. >and a list of newsgroups to process or not process, sys file style.  Ex:
  268. >X
  269. >X    .5    alt.sex.pictures,talk,!talk.bizarre,junk
  270. >X    1    rec,!rec.games,!rec.humor
  271. >X
  272. >This example would check freespace, and if more space is needed, expire
  273. >to .5 days everything in alt.sex.pictures, talk (except for talk.bizarre)
  274. >and junk.  Then it would stop and check freespace again.  If still more
  275. >space is needed, it would expire to 1 day everything in rec except
  276. >rec.games.* and rec.humor.*.  It's that simple.
  277. >X
  278. >X
  279. >Okay...So How Do I Arrange To Trim The History Files, Since Reap Can't:
  280. >X    Included in this distribution is a shell script (mostly written
  281. >by Mike Murphy) to handle Cnews history files.  It shouldn't be too
  282. >difficult to do something similar for Bnews, or you can give in and use
  283. >the original expire utility with options that tell it to expire the
  284. >history files only...but I think this will be slow.  It just comes down
  285. >to removing lines from ordinary text files, based on their contents.
  286. >Murphy and I used awk.
  287. >X
  288. >X
  289. >But Is It Fast:
  290. >X    Yes, largely because it doesn't have to do much.  Even "find | rm"
  291. >is slower because find is repeatedly exec-ing rm.  "rm -rf" has me beat,
  292. >though, I'll bet!  :-)
  293. >X
  294. >X    Since the functions of deleting articles and trimming history
  295. >are separate, I now run reap every six hours, but trim the history list
  296. >just once a day.  That effectively keeps my disk space up to snuff, but
  297. >only thrashes at the history file in the middle of the night.
  298. >X
  299. >X
  300. >Credits:
  301. >X    I owe a lot to Mike Murphy for inspiring me with his "trasher"
  302. >system.  I also owe a lot to all of your netters who will flood me with
  303. >more suggestions and improvements in the coming weeks (hint, hint!).
  304. >X
  305. >X                        little david
  306. >X                        dt@yenta.alb.nm.us
  307. >X
  308. >ps - reap is freeware.  No strings(1) attached.
  309. >SHAR_EOF
  310. >chmod 0664 README ||
  311. >echo 'restore of README failed'
  312. >Wc_c="`wc -c < 'README'`"
  313. >test 2918 -eq "$Wc_c" ||
  314. >    echo 'README: original size 2918, current size' "$Wc_c"
  315. >fi
  316. ># ============= exphist ==============
  317. >if test -f 'exphist' -a X"$1" != X"-c"; then
  318. >    echo 'x - skipping exphist (File already exists)'
  319. >else
  320. >echo 'x - extracting exphist (Text)'
  321. >sed 's/^X//' << 'SHAR_EOF' > 'exphist' &&
  322. >#! /bin/sh
  323. ># exphist - expire history file
  324. >X
  325. ># =()<. ${NEWSCONFIG-@<NEWSCONFIG>@}>()=
  326. >. ${NEWSCONFIG-/usr/lib/news/bin/config}
  327. >X
  328. >PATH=$NEWSCTL/bin:$NEWSBIN/expire:$NEWSBIN:$NEWSPATH ; export PATH
  329. >umask $NEWSUMASK
  330. >X
  331. >days=`cat /usr/lib/news/histdays`
  332. >X
  333. >lock="$NEWSCTL/LOCKexpire"
  334. >ltemp="$NEWSCTL/L.$$"
  335. >Xecho $$ >$ltemp
  336. >trap "rm -f $ltemp ; exit 0" 0 1 2 15
  337. >if newslock $ltemp $lock
  338. >then
  339. >X    trap "rm -f $ltemp $lock ; exit 0" 0 1 2 15
  340. >Xelse
  341. >X    echo "$0: expire apparently already running" | mail "$NEWSMASTER"
  342. >X    exit 1
  343. >fi
  344. >X
  345. >cd $NEWSCTL
  346. >rm -f history.n history.n.pag history.n.dir
  347. >now=`getdate now`
  348. >age=`expr 86400 \* $days`
  349. >ago=`expr $now - $age`
  350. >awk "{split(\$2,dates,\"~\");if(dates[1]>$ago)print \$0}" history >history.n
  351. >mkdbm history.n
  352. >[ -s history.n ] &&
  353. >mv history history.o &&    # install new ASCII history file
  354. >mv history.n history &&
  355. >rm -f history.pag &&       # and related dbm files
  356. >rm -f history.dir &&
  357. >mv history.n.pag history.pag &&
  358. >mv history.n.dir history.dir
  359. >Xexit 0
  360. >SHAR_EOF
  361. >chmod 0775 exphist ||
  362. >echo 'restore of exphist failed'
  363. >Wc_c="`wc -c < 'exphist'`"
  364. >test 969 -eq "$Wc_c" ||
  365. >    echo 'exphist: original size 969, current size' "$Wc_c"
  366. >fi
  367. ># ============= lib.c ==============
  368. >if test -f 'lib.c' -a X"$1" != X"-c"; then
  369. >    echo 'x - skipping lib.c (File already exists)'
  370. >else
  371. >echo 'x - extracting lib.c (Text)'
  372. >sed 's/^X//' << 'SHAR_EOF' > 'lib.c' &&
  373. >X
  374. >/*
  375. >X * lib.c
  376. >X *    subroutines needed by reap utility
  377. >X */
  378. >X
  379. >#include "reap.h"
  380. >X
  381. >/*
  382. >X * freeblox(devno)
  383. >X *
  384. >X * THIS WILL REQUIRE MODIFICATION TO WORK UNDER NON-SYSTEM-V UNIX.
  385. >X * IT SHOULD BE EASY.  PLEASE EMAIL WORKING MODS TO THE AUTHOR:
  386. >X *            dt@yenta.alb.nm.us
  387. >X *
  388. >X *    assuming devno is the device number of a file system,
  389. >X *    this function returns the free space on that file system,
  390. >X *    in blocks (whatever that means for that filesystem) as an int.
  391. >X *
  392. >X */
  393. >X
  394. >freeblox(devno)
  395. >int    devno;
  396. >{
  397. >X    static struct ustat    ust;
  398. >X
  399. >X    if (ustat(devno, &ust))
  400. >X        ouch ("%s: ustat() failed\n");
  401. >X
  402. >X    return (ust.f_tfree);
  403. >X
  404. >} /* freeblox() */
  405. >X
  406. >X
  407. >X
  408. >X
  409. >/*
  410. >X * parse(cmd)
  411. >X *    execute a line from the script file
  412. >X *
  413. >X * valid command lines:
  414. >X *    a blank line is ignored
  415. >X *    # comment (ignored)
  416. >X *    days filespecs
  417. >X *
  418. >X * filespecs is a comma separated list of any combination of the following:
  419. >X * 1. a directory (newsgroup) to include, without recursion.
  420. >X *    ex:  alt.sources.
  421. >X * 2. a directory to include, recursively.
  422. >X *    ex:  alt.sources
  423. >X * 3. a directory to exclude, without recursion.
  424. >X *    ex:  !alt.sex.
  425. >X * 4. a directory to exclude, recursively.
  426. >X *    ex:  !alt.sex
  427. >X */
  428. >X
  429. >parse(cmd)
  430. >char    *cmd;
  431. >{
  432. >X    register int    l;
  433. >X    int        recurseflag;
  434. >X    double        days;
  435. >X    char        *t,
  436. >X            *p,
  437. >X            *q,
  438. >X            *seps = ",\n ";
  439. >X
  440. >X
  441. >/* skip initial whitespace */
  442. >X    p = cmd;
  443. >X    while (isspace(*p))
  444. >X        ++p;
  445. >X
  446. >/* ignore blank lines or comments */
  447. >X    if (*p == '\0' || *p == '#')
  448. >X        return(1);
  449. >X
  450. >/* read the expire time from the line as a floating point number,
  451. >X * then figure out what the timestamp on a file that old would be */
  452. >X    age = now - (time_t) (atof(p) * SECINDAY);
  453. >X
  454. >/* skip ahead to the filespec list */
  455. >X    while (!isspace(*p))
  456. >X        ++p;
  457. >X    while (isspace(*p))
  458. >X        ++p;
  459. >X
  460. >/* initialize exclusion list to null list */
  461. >X    preclude();
  462. >X
  463. >/* for each filespec in list */
  464. >X    for (t = strtok(p, seps); t; t = strtok(NULL, seps)) {
  465. >X
  466. >X    /* forbid starting with a slash */
  467. >X        if (*t == '/')
  468. >X            *t = '.';
  469. >X
  470. >X    /* change dots to slashes except in column 1 */
  471. >X        while ( (q = strchr(t+1,'.')) != NULL)
  472. >X            *q = '/';
  473. >X
  474. >X    /* for final dot or slash, remove it, and shut off recursion */
  475. >X        recurseflag = 1;
  476. >X        if (t[l = (strlen(t) - 1)] == '/') {
  477. >X            recurseflag = 0;
  478. >X            t[l] = '\0';
  479. >X        }
  480. >X
  481. >X        if (*t == '!')
  482. >X            exclude (t+1, recurseflag);
  483. >X        else
  484. >X            include (t, recurseflag);
  485. >X    }
  486. >X
  487. >X    reap();
  488. >X
  489. >X    return (0);
  490. >X
  491. >} /* parse() */
  492. >X
  493. >X
  494. >X
  495. >/*
  496. >X * newnode,exclude, include, preclude
  497. >X *
  498. >X *    functions to maintain global linked lists:
  499. >X *        incl    include this path in list of dirs to reap
  500. >X *        excl    leave out this directory
  501. >X            (each entry can be recursive or not)
  502. >X *
  503. >X *    the functions are:
  504. >X *        include (text,rflag)    add to incl list
  505. >X *        exclude (text,rflag)    add to excl list
  506. >X *        preclude()        clear both lists
  507. >X */
  508. >struct filspec *
  509. >newnode(text)
  510. >char    *text;
  511. >{
  512. >X    struct filspec    *f;
  513. >X
  514. >X    if ( (f = (struct filspec *) malloc (sizeof(struct filspec))) == NULL ||
  515. >X        (f->name = malloc (strlen(text)+1)) == NULL)
  516. >X        ouch ("%s: out of memory\n");
  517. >X
  518. >X    strcpy (f->name, text);
  519. >X    return (f);
  520. >}
  521. >Xexclude(text, rflag)
  522. >char    *text;
  523. >int    rflag;
  524. >{
  525. >X    struct filspec    *f;
  526. >X
  527. >X    f = newnode(text);
  528. >X    f->recurse = rflag;
  529. >X    f->next = excl;
  530. >X    excl = f;
  531. >}
  532. >include(text, rflag)
  533. >char    *text;
  534. >int    rflag;
  535. >{
  536. >X    struct filspec    *f;
  537. >X
  538. >X    f = newnode(text);
  539. >X    f->recurse = rflag;
  540. >X    f->next = incl;
  541. >X    incl = f;
  542. >}
  543. >preclude()
  544. >{
  545. >X    struct filspec    *p;
  546. >X
  547. >X    while (incl != NULL) {
  548. >X        p = incl;
  549. >X        incl = incl->next;
  550. >X        free (p->name);
  551. >X        free (p);
  552. >X    }
  553. >X    while (excl != NULL) {
  554. >X        p = excl;
  555. >X        excl = excl->next;
  556. >X        free (p->name);
  557. >X        free (p);
  558. >X    }
  559. >}
  560. >X
  561. >X
  562. >/*
  563. >X * ouch(fmt, arg)
  564. >X *    outputs an error message and exits with error status
  565. >X */
  566. >X
  567. >ouch (fmt,arg)
  568. >char    *fmt, *arg;
  569. >{
  570. >X    fprintf (stderr, fmt, progname, arg);
  571. >X    exit (-1);
  572. >}
  573. >SHAR_EOF
  574. >chmod 0664 lib.c ||
  575. >echo 'restore of lib.c failed'
  576. >Wc_c="`wc -c < 'lib.c'`"
  577. >test 3567 -eq "$Wc_c" ||
  578. >    echo 'lib.c: original size 3567, current size' "$Wc_c"
  579. >fi
  580. ># ============= list.sample ==============
  581. >if test -f 'list.sample' -a X"$1" != X"-c"; then
  582. >    echo 'x - skipping list.sample (File already exists)'
  583. >else
  584. >echo 'x - extracting list.sample (Text)'
  585. >sed 's/^X//' << 'SHAR_EOF' > 'list.sample' &&
  586. ># yenta's /usr/lib/news/reaplist function script file.
  587. >.1 junk,alt.flame,control,comp.binaries,alt.sex.pictures.,alt.fractals.pictures
  588. >.1 alt.desert-storm,alt.desert-shield,soc.motss,soc.culture
  589. >1 soc.singles,alt.activism,alt.romance.chat
  590. >.5 talk
  591. >1 sci,!sci.skeptic
  592. >2 sci.skeptic
  593. >.5 comp.text,comp.sys.atari,comp.windows,comp.os.vms
  594. >.5 comp.unix.sysv386
  595. >.5 misc.jobs,misc.handicap
  596. >2 soc,!soc.singles,!soc.motss,!soc.culture
  597. >.5 rec,!rec.arts.anime,!rec.arts.animation,!rec.arts.movies,!rec.games.hack,!rec.radio.amateur,!rec.autos,!rec.arts.tv,!rec.audio,!rec.video,!rec.music,!rec.skydiving
  598. >1 rec.music,!rec.music.synth
  599. >3 rec.music.synth,rec.skydiving
  600. >2 alt.tv
  601. >2 rec.arts.anime,rec.arts.animation,rec.arts.movies,rec.radio.amateur,rec.autos,rec.arts.tv,rec.audio,rec.video
  602. >3 rec.games.hack
  603. >1 misc.headlines,misc.consumers,misc.kids,misc.legal
  604. >1 alt.sex,!alt.sex.bondage,!alt.sex.pictures.
  605. >1.5 comp,!comp.dcom.telecom,!comp.binaries,!comp.text,!comp.sys.atari,!comp.windows,!comp.os.vms,!comp.sys.att,!comp.sys.3b1,!comp.sources.3b1
  606. >3 comp.dcom.telecom
  607. >1 comp.binaries
  608. >1 alt.sources
  609. >1 news,!news.announce.newusers
  610. >3 biz
  611. >3 misc
  612. >3 alt,!alt.sources,!alt.tv,!alt.desert-shield,!alt.activism,!alt.fractals.pictures,!alt.desert-storm,!alt.romance.chat
  613. >3 comp.sys.att
  614. >5 comp.sys.3b1
  615. >5 comp.sources.3b1
  616. >7 general
  617. ># up to here is "normal expire"... now let's get desparate
  618. >.1 alt.sex.pictures
  619. >.1 rec.arts.anime,rec.arts.animation,rec.arts.movies,rec.ham-radio,rec.autos,rec.arts.tv,rec.audio,rec.video
  620. >.1 biz
  621. >.1 talk
  622. >.1 news
  623. >.1 soc
  624. >.1 sci
  625. >.1 comp
  626. >.1 alt
  627. >.1 misc
  628. ># if we got here, we're in big trouble -- wipe it all!
  629. >0 .
  630. >SHAR_EOF
  631. >chmod 0664 list.sample ||
  632. >echo 'restore of list.sample failed'
  633. >Wc_c="`wc -c < 'list.sample'`"
  634. >test 1611 -eq "$Wc_c" ||
  635. >    echo 'list.sample: original size 1611, current size' "$Wc_c"
  636. >fi
  637. ># ============= main.c ==============
  638. >if test -f 'main.c' -a X"$1" != X"-c"; then
  639. >    echo 'x - skipping main.c (File already exists)'
  640. >else
  641. >echo 'x - extracting main.c (Text)'
  642. >sed 's/^X//' << 'SHAR_EOF' > 'main.c' &&
  643. >X
  644. >/*
  645. >X * main.c
  646. >X *    main routine and globals for reap utility, version 1.1
  647. >X */
  648. >X
  649. >X
  650. >#include "reap.h"
  651. >X
  652. >X
  653. >/* linked lists for included and excluded file specs */
  654. >struct filspec
  655. >X        *incl = NULL,
  656. >X        *excl = NULL
  657. >;
  658. >char
  659. >X        *scriptfile = SCRIPT,    /* path of function script    */
  660. >X        *progname,        /* argv[0] for errors        */
  661. >X        *newsdir = NEWSDIR    /* news root directory        */
  662. >;
  663. >int
  664. >X        verbose = 0,        /* verbosity (-v) flag        */
  665. >X        dryrun = 0        /* do-not-unlink (-n) flag    */
  666. >;
  667. >time_t
  668. >X        age,            /* unlink files older than this    */
  669. >X        now            /* current time            */
  670. >;
  671. >X
  672. >X
  673. >/************************
  674. >X *    MAIN FUNCTION    *
  675. >X ************************/
  676. >X
  677. >main(argc, argv)
  678. >int    argc;
  679. >char    *argv[];
  680. >{
  681. >X    int        device,        /* device # containing newsdir    */
  682. >X            c,
  683. >X            lineno = 0,
  684. >X            summary = 0,
  685. >X            thenfree,
  686. >X            errflag = 0;
  687. >X    long        wantblox;    /* desired free space        */
  688. >X    char        *p;
  689. >X    static char    line[MAXLINE];
  690. >X    FILE        *script;    /* file ptr for function script    */
  691. >X    struct stat    st;
  692. >X
  693. >X
  694. >/* save argv[0] for error spewings */
  695. >X    progname = argv[0];
  696. >X
  697. >/* parse args */
  698. >X    while ( (c=getopt(argc,argv,"vsnf:")) != EOF)
  699. >X        switch(c) {
  700. >X        case 'n':
  701. >X            ++dryrun;
  702. >X            break;
  703. >X        case 'v':
  704. >X            ++verbose;
  705. >X            break;
  706. >X        case 'f':
  707. >X            scriptfile = optarg;
  708. >X            break;
  709. >X        case 's':
  710. >X            ++summary;
  711. >X            break;
  712. >X        default:
  713. >X            ++errflag;
  714. >X            break;
  715. >X        }
  716. >X    
  717. >X    if (argc - optind != 1 ||
  718. >X        sscanf(argv[optind], "%ld", &wantblox) != 1 )
  719. >X        ++errflag;
  720. >X
  721. >X    if (errflag) {
  722. >X        fprintf (stderr,
  723. >X            "usage: %s [-v] [-s] [-n] [-f funclist] freeblocks\n",
  724. >X            progname);
  725. >X        exit (-1);
  726. >X    }
  727. >X
  728. >X
  729. >/* stat newsdir to find the number of the device it's on */
  730. >X    if (stat(newsdir, &st))
  731. >X        ouch ("%s: can't stat %s\n", newsdir);
  732. >X    device = st.st_dev;
  733. >X
  734. >/* open function script file for reading */
  735. >X    if ( (script = fopen (scriptfile, "r")) == NULL)
  736. >X        ouch ("%s: can't read %s\n", scriptfile);
  737. >X
  738. >/* Record the current time, for deciding what gets the axe. */
  739. >X    time (&now);
  740. >X
  741. >/* chdir to newsdir */
  742. >X    chdir (newsdir);
  743. >X
  744. >/* record initial freespace if summary is desired */
  745. >X    if (summary)
  746. >X        thenfree = freeblox(device);
  747. >X
  748. >/* main loop ... process until goal reached or end of script */
  749. >X
  750. >X    while (freeblox(device) < wantblox &&
  751. >X        (p = fgets (line, MAXLINE, script)) != NULL )
  752. >X        parse (line), ++lineno;
  753. >X
  754. >X    fclose (script);
  755. >X
  756. >X    if (summary) {
  757. >X        c = freeblox(device);
  758. >X        printf ("Freespace was %d, now %d.  Cleared %d.\n",
  759. >X            thenfree, c, c - thenfree);
  760. >X        printf ("Stopped after line %d in %s\n", lineno,
  761. >X            scriptfile);
  762. >X    }
  763. >X
  764. >/* return 0 if freespace goal was met at exit, 1 if not */
  765. >X    exit (freeblox(device) >= wantblox ? 0 : 1);
  766. >X
  767. >} /* main() */
  768. >X
  769. >SHAR_EOF
  770. >chmod 0664 main.c ||
  771. >echo 'restore of main.c failed'
  772. >Wc_c="`wc -c < 'main.c'`"
  773. >test 2497 -eq "$Wc_c" ||
  774. >    echo 'main.c: original size 2497, current size' "$Wc_c"
  775. >fi
  776. ># ============= reap.8 ==============
  777. >if test -f 'reap.8' -a X"$1" != X"-c"; then
  778. >    echo 'x - skipping reap.8 (File already exists)'
  779. >else
  780. >echo 'x - extracting reap.8 (Text)'
  781. >sed 's/^X//' << 'SHAR_EOF' > 'reap.8' &&
  782. >.TH REAP 8 LOCAL
  783. >.SH NAME
  784. >reap - remove news articles as space needed
  785. >.SH SYNOPSIS
  786. >.B reap
  787. >[-v] [-s] [-n] [-f scriptfile] freeblocks
  788. >.SH DESCRIPTION
  789. >.I Reap
  790. >checks disk freespace and deletes netnews articles
  791. >according to a flexible user-specified
  792. >scheme until
  793. >.I freeblocks
  794. >minimum freespace is available.
  795. >It does this by sequentially reading commands (expire functions) from a
  796. >text file (function script), and executing them one at a time.
  797. >.PP
  798. >Each expire function consists of an age limit and a list of newsgroups
  799. >to expire to that limit.
  800. >Before executing
  801. >Xeach new expire function, reap checks the freespace on the news spool
  802. >device.  Reap will exit when either the desired freespace is attained, or
  803. >the end of the function script file is reached (the latter case is considered
  804. >an unsuccessful exit).
  805. >By carefully designing the function script, a news administrator can
  806. >automate a wide variety of expiring policies.
  807. >.PP
  808. >The
  809. >.B -n
  810. >causes a dry run (as in make(1)).  When this
  811. >option is specified, reap merely reports which articles it would delete if
  812. >the option were left off.  This is useful for debugging function scripts.
  813. >However, since no space is actually freed in this mode,
  814. >it will either do nothing
  815. >(there was enough space to begin with) or proceed through the entire function
  816. >script file, indicating that reap would delete all applicable articles.
  817. >.PP
  818. >With the
  819. >.B -v
  820. >option, reap prints a verbose commentary on its progress to the standard
  821. >output.
  822. >.PP
  823. >The
  824. >.B -s
  825. >option causes reap to print a brief summary of blocks freed to the standard
  826. >output just before exiting.  It also indicates how much of the script file
  827. >was processed.  This is independent of -v.
  828. >.PP
  829. >By default, reap looks in /usr/lib/news/reaplist for its list of functions.
  830. >The
  831. >.B -f
  832. >option is used to specify an alternate function script file.
  833. >.SH FUNCTION SCRIPT FILE FORMAT
  834. >A function script file consists of a series of expire functions, one per line.
  835. >Each expire function contains an age limit (in days, decimals okay), followed
  836. >by a comma-separated list of newsgroup specifications, similar to the
  837. >sys file format.
  838. >.PP
  839. >There are four types of valid newsgroup specifications that can go in the list:
  840. >.PP
  841. >(1) An ordinary newsgroup name (alt.sex) indicates that any articles in that
  842. >newsgroup and any of its descendants (such as alt.sex.pictures), which are
  843. >older than the age limit, should be expired.
  844. >.PP
  845. >(2) A newsgroup name with a trailing dot (alt.sex.) indicates that any articles
  846. >in that newsgroup, which are older than the age limit, should be expired.
  847. >However, recursion is not implied.  Articles in descendants of that group
  848. >(such as alt.sex.pictures) are not affected.
  849. >.PP
  850. >(3) A newsgroup name with a preceding exclamation point (!alt.sex.pictures)
  851. >indicates that that newsgroup and all of its descendants should be excluded
  852. >from the list.
  853. >For example, "1 alt.sex,!alt.sex.pictures" means to expire everything subsumed
  854. >under alt.sex to 1 day, but do not touch anything subsumed under
  855. >alt.sex.pictures.
  856. >.PP
  857. >(4) A newsgroup name with both a preceding exclamation point and a trailing
  858. >dot (!alt.sex.pictures.) indicates that that newsgroup should be excluded
  859. >from the list, but its descendants should remain in the list.  For example,
  860. >"1 alt.sex,!alt.sex.pictures." means to expire everything subsumed under
  861. >alt.sex to 1 day, including the contents of any subgroups of alt.sex.pictures
  862. >(like alt.sex.pictures.d), but do not touch the articles in the newsgroup
  863. >alt.sex.pictures.
  864. >.PP
  865. >Blank lines and lines beginning with a "#" are ignored.
  866. >A sample function script file:
  867. >.PP
  868. >.nf
  869. >X    # my first function script file
  870. >X    0.5    talk,junk,alt.sex.pictures.
  871. >X    2    rec,!rec.games,!rec.humor
  872. >X    2    misc
  873. >.fi
  874. >.PP
  875. >In the example,
  876. >if space is needed, reap
  877. >Xexpires to .5 days the entire talk and junk
  878. >hierarchies, and alt.sex.pictures (not touching any subgroups of
  879. >alt.sex.pictures, such as alt.sex.pictures.d).
  880. >If still more space is needed, the
  881. >rec hierarchy (excepting all of rec.games.* and rec.humor.*) is expired
  882. >to 2 days.  If freespace is still short, reap then expires all of misc
  883. >to 2 days.
  884. >.PP
  885. >Note that, while it would be possible to consolidate the 2-day
  886. >lines, leaving them separate makes it possible for reap to stop
  887. >in between them if sufficient space is cleared.
  888. >.PP
  889. >A practical function script file would directly or indirectly
  890. >include every group carried on the system, with some age limit.  Otherwise,
  891. >the spool directory will inevitably overflow without operator intervention.
  892. >.PP
  893. >It is valid to specify a dot all by itself (.) in the newsgroup list field.
  894. >This is taken to mean the entire spool directory hierarchy, so "14 ." means
  895. >to expire all news to 14 days.  Be warned that reap must search the entire
  896. >news hierarchy when this feature is used.  Still, it is probably a good
  897. >idea to end all function script files with a "0 .", so that, in absolute
  898. >desperation, all news would be removed.
  899. >.SH FILES
  900. >.TP 25
  901. >/usr/spool/news
  902. >News spool directory
  903. >.TP 25
  904. >/usr/lib/news/reaplist
  905. >Default function list file
  906. >.SH DIAGNOSTICS
  907. >Returns zero if sufficient space was free at exit, 1 if the entire function
  908. >script was executed without freeing enough space, and -1 on an error
  909. >condition.
  910. >.SH CAVEATS
  911. >What constitutes a disk "block" is implementation-dependent.
  912. >.PP
  913. >History files are not updated.  That must be performed as a separate operation.
  914. >.PP
  915. >For best performance, exclude recursively (without the dot) whenever
  916. >possible.  Otherwise, reap will have to search the excluded directory
  917. >for any subdirectories which might not have been excluded, which is slow.
  918. >.SH BUGS
  919. >The use of the ustat() system call is not very portable, and your humble
  920. >author isn't aware of its non-system-V equivalents.
  921. >.PP
  922. >Lines in the function file are limited to 1024 characters.
  923. >.PP
  924. >The "cleared" figure in the summary merely indicates the difference in
  925. >freespace before and after the run, not necessarily the actual number of
  926. >blocks liberated by reap.
  927. >.SH AUTHOR
  928. >Reap is freeware by David B. Thomas (dt@yenta.alb.nm.us).  You are free
  929. >to copy, distribute, staple, bend, fold or mutilate this package to your
  930. >heart's content.  Please email any enhancements or ideas for enhancements.
  931. >SHAR_EOF
  932. >chmod 0644 reap.8 ||
  933. >echo 'restore of reap.8 failed'
  934. >Wc_c="`wc -c < 'reap.8'`"
  935. >test 6129 -eq "$Wc_c" ||
  936. >    echo 'reap.8: original size 6129, current size' "$Wc_c"
  937. >fi
  938. ># ============= reap.c ==============
  939. >if test -f 'reap.c' -a X"$1" != X"-c"; then
  940. >    echo 'x - skipping reap.c (File already exists)'
  941. >else
  942. >echo 'x - extracting reap.c (Text)'
  943. >sed 's/^X//' << 'SHAR_EOF' > 'reap.c' &&
  944. >X
  945. >/*
  946. >X * reap.c
  947. >X *    contains the reap() function.
  948. >X *
  949. >X * Once the global linked lists incl and excl have been stuffed,
  950. >X * reap() actually scans the filesystem for files that meet the specs
  951. >X * and unlinks them if they are older than the age global variable.
  952. >X */
  953. >X
  954. >#include "reap.h"
  955. >X
  956. >X
  957. >reap()
  958. >{
  959. >X    struct filspec    *f;
  960. >X
  961. >X    for (f = incl; f != NULL; f = f->next) {
  962. >X        if (verbose)
  963. >X            printf ("scanning %s ...\n", f->name);
  964. >X        dodir (f->name, f->recurse);
  965. >X    }
  966. >X
  967. >} /* reap() */
  968. >X
  969. >X
  970. >X
  971. >dodir(name, rflag)
  972. >char    *name;
  973. >int    rflag;
  974. >{
  975. >X    /* the following can be overwritten safely during recursion */
  976. >X    static struct filspec    *e;
  977. >X    static struct stat    st;
  978. >X    static struct dirent    *dp;
  979. >X    static char        thisname[MAXFILENAME+1];
  980. >X    /* the following must be preserved through recursion */
  981. >X    char            *fullpath;
  982. >X    int            eflag = 0;
  983. >X    DIR            *dirp;
  984. >X
  985. >X
  986. >/* open directory for reading */
  987. >X    if ( (dirp = opendir(name)) == NULL)
  988. >X        ouch ("%s: can't read directory %s\n", name);
  989. >X
  990. >X
  991. >/* see if this directory is excluded.
  992. >X * If it's excluded recursively, quit here.
  993. >X * If it's excluded non-recursively, set a flag, so we won't consider
  994. >X *    deleting any files in it, but we'll still explore subdirectories.
  995. >X */
  996. >X    for (e = excl; e != NULL; e = e->next)
  997. >X        if (!strcmp (name, e->name))
  998. >X            break;
  999. >X    if (e != NULL) {
  1000. >X        if (e->recurse)
  1001. >X            return;
  1002. >X        else
  1003. >X            ++eflag;
  1004. >X    }
  1005. >X
  1006. >X
  1007. >/* loop for each directory entry */
  1008. >X    while ( (dp = readdir(dirp)) != NULL) {
  1009. >X
  1010. >X    /* name might be exactly MAXFILENAME characters long, and thus
  1011. >X     * might not be null-terminated.  Some insurance:
  1012. >X     */
  1013. >X        strncpy (thisname, dp->d_name, MAXFILENAME);
  1014. >X        thisname[MAXFILENAME] = '\0';
  1015. >X
  1016. >X    /* skip dot and dotdot */
  1017. >X        if (!strcmp(thisname, ".") || !strcmp(thisname, ".."))
  1018. >X            continue;
  1019. >X
  1020. >X    /* build the full pathname of current object */
  1021. >X        if ( (fullpath =
  1022. >X            malloc(strlen(name)+strlen(thisname)+2)) == NULL)
  1023. >X            ouch ("%s: out of memory\n");
  1024. >X
  1025. >X        sprintf (fullpath, "%s/%s", name, thisname);
  1026. >X
  1027. >X    /* try to stat the object */
  1028. >X        if (stat(fullpath,&st)) {
  1029. >X            fprintf (stderr, "%s: can't stat %s\n",
  1030. >X                progname, fullpath);
  1031. >X            free (fullpath);
  1032. >X            continue;
  1033. >X        }
  1034. >X
  1035. >X    /* maybe recurse if it's a directory */
  1036. >X        if ( st.st_mode & S_IFDIR ) {
  1037. >X            if (rflag)
  1038. >X                dodir (fullpath, 1);
  1039. >X            free (fullpath);
  1040. >X            continue;
  1041. >X        }
  1042. >X
  1043. >X    /* it's a file ...  is this a non-recursively excluded directory?
  1044. >X     * if so, there's nothing to do to this file
  1045. >X     */
  1046. >X        if (eflag)
  1047. >X            continue;
  1048. >X
  1049. >X    /* leave it alone if this directory is excluded, or
  1050. >X     * if it's new enough.
  1051. >X     */
  1052. >X        if (eflag || st.st_mtime > age) {
  1053. >X            free (fullpath);
  1054. >X            continue;
  1055. >X        }
  1056. >X
  1057. >X    /* reap this file! */
  1058. >X        if (dryrun) {
  1059. >X            printf ("Would unlink %s\n", fullpath);
  1060. >X            free (fullpath);
  1061. >X            continue;
  1062. >X        }
  1063. >X        if (verbose)
  1064. >X            printf ("Unlinking %s\n", fullpath);
  1065. >X
  1066. >X        if (unlink (fullpath) == -1)
  1067. >X            fprintf (stderr,
  1068. >X                "%s: cannot unlink %s\n", progname, fullpath);
  1069. >X
  1070. >X        free (fullpath);
  1071. >X
  1072. >X    } /* while */
  1073. >X
  1074. >X    closedir (dirp);
  1075. >X
  1076. >} /* dodir() */
  1077. >SHAR_EOF
  1078. >chmod 0664 reap.c ||
  1079. >echo 'restore of reap.c failed'
  1080. >Wc_c="`wc -c < 'reap.c'`"
  1081. >test 2845 -eq "$Wc_c" ||
  1082. >    echo 'reap.c: original size 2845, current size' "$Wc_c"
  1083. >fi
  1084. ># ============= reap.h ==============
  1085. >if test -f 'reap.h' -a X"$1" != X"-c"; then
  1086. >    echo 'x - skipping reap.h (File already exists)'
  1087. >else
  1088. >echo 'x - extracting reap.h (Text)'
  1089. >sed 's/^X//' << 'SHAR_EOF' > 'reap.h' &&
  1090. >X
  1091. >/*
  1092. >X * reap.h
  1093. >X *    header file for reap utility
  1094. >X */
  1095. >X
  1096. >/* set MAXFILENAME to the maximum number of characters in a filename for
  1097. >X * your system.  Typically 14 or infinity, where infinity equals
  1098. >X * 256 characters. :-)
  1099. >X */
  1100. >#define MAXFILENAME    14
  1101. >X
  1102. >/* set NEWSDIR to the directory containing news on your system.
  1103. >X * Very commonly /usr/spool/news
  1104. >X */
  1105. >#define NEWSDIR        "/usr/spool/news"
  1106. >X
  1107. >/* set SCRIPT to the path of the default function script file
  1108. >X * Usually this is /usr/lib/news/reaplist
  1109. >X */
  1110. >#define SCRIPT        "/usr/lib/news/reaplist"
  1111. >X
  1112. >X
  1113. >X
  1114. >X
  1115. >#include <stdio.h>
  1116. >#include <string.h>
  1117. >#include <ctype.h>
  1118. >#include <time.h>
  1119. >#include <malloc.h>
  1120. >#include <sys/types.h>
  1121. >#include <sys/stat.h>
  1122. >#include <ustat.h>
  1123. >#include <dirent.h>
  1124. >X
  1125. >#define MAXLINE        1024        /* max len of line in script    */
  1126. >#define SECINDAY    (3600 * 24)    /* seconds in a day        */
  1127. >X
  1128. >/* structure for linked lists of included and excluded file specs */
  1129. >struct filspec {
  1130. >X    char        *name;
  1131. >X    int        recurse;
  1132. >X    struct filspec    *next;
  1133. >};
  1134. >X
  1135. >Xextern struct filspec
  1136. >X        *incl,
  1137. >X        *excl
  1138. >;
  1139. >Xextern char
  1140. >X        *progname,
  1141. >X        *scriptfile,
  1142. >X        *newsdir
  1143. >;
  1144. >Xextern int
  1145. >X        verbose,
  1146. >X        dryrun,
  1147. >X        optind
  1148. >;
  1149. >Xextern char    *optarg;
  1150. >Xextern double    atof();
  1151. >Xextern long    freeblox();
  1152. >Xextern time_t
  1153. >X        age,
  1154. >X        now
  1155. >;
  1156. >SHAR_EOF
  1157. >chmod 0664 reap.h ||
  1158. >echo 'restore of reap.h failed'
  1159. >Wc_c="`wc -c < 'reap.h'`"
  1160. >test 1195 -eq "$Wc_c" ||
  1161. >    echo 'reap.h: original size 1195, current size' "$Wc_c"
  1162. >fi
  1163. >exit 0
  1164. >-- 
  1165. >Bottom of stack = 0x40000
  1166. >Stack pointer   = 0x3fffe
  1167. >Don't push it!
  1168. ---
  1169.  reply to : admerlev@faui43.informatik.uni-erlangen.de
  1170.