home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume19 / cnews2 / part05 < prev    next >
Text File  |  1989-06-29  |  53KB  |  1,997 lines

  1. Subject:  v19i082:  Cnews production release, Part05/19
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: utzoo!henry
  7. Posting-number: Volume 19, Issue 82
  8. Archive-name: cnews2/part05
  9.  
  10. : ---CUT HERE---
  11. echo 'batch/sendbatches':
  12. sed 's/^X//' >'batch/sendbatches' <<'!'
  13. X#! /bin/sh
  14. X# Master batching control.
  15. X
  16. X# =()<. ${NEWSCONFIG-@<NEWSCONFIG>@}>()=
  17. X. ${NEWSCONFIG-/usr/lib/news/bin/config}
  18. X
  19. XPATH=$NEWSCTL/bin:$NEWSBIN/batch:$NEWSBIN:$NEWSPATH ; export PATH
  20. Xumask $NEWSUMASK
  21. X
  22. Xorigpath="$PATH"
  23. X
  24. Xparms=$NEWSCTL/batchparms
  25. Xlog=$NEWSCTL/batchlog        # also same with suffixes .o and .oo
  26. X
  27. X# lock against multiple simultaneous execution
  28. Xlock="$NEWSCTL/LOCKbatch"
  29. Xltemp="$NEWSCTL/L.$$"
  30. Xecho $$ >$ltemp
  31. Xtrap "rm -f $ltemp ; exit 0" 0 1 2 15
  32. Xif newslock $ltemp $lock
  33. Xthen
  34. X    trap "rm -f $ltemp $lock ; exit 0" 0 1 2 15
  35. Xelse
  36. X    exit 0
  37. Xfi
  38. X
  39. Xcd $NEWSARTS/out.going
  40. X
  41. X# Determine what systems are being requested, in what order.
  42. Xcase "$1"
  43. Xin
  44. X    -d)
  45. X    debug=yes
  46. X    shift
  47. X    ;;
  48. Xesac
  49. Xcase $#
  50. Xin
  51. X    0)
  52. X    if egrep '^/default/[     ]' $parms >/dev/null    # default line found
  53. X    then
  54. X        syses=`ls -tr | egrep -v '^[@.]'`    # oldest first
  55. X    else
  56. X        syses="`egrep '^[^/#]' $parms | awk '{ print $1 }'`"
  57. X    fi
  58. X    ;;
  59. X
  60. X    *)
  61. X    syses="$*"
  62. X    ;;
  63. Xesac
  64. Xcase $debug
  65. Xin
  66. X    yes)
  67. X    for sys in $syses
  68. X    do
  69. X        echo $sys
  70. X    done
  71. X    exit 0
  72. X    ;;
  73. Xesac
  74. X
  75. X# Start up logging.
  76. Xmv $log.o $log.oo
  77. Xmv $log $log.o
  78. Xdate >$log
  79. X
  80. X# Run through them.
  81. Xfor sys in $syses
  82. Xdo
  83. X    # Move into his directory, include it in search path.
  84. X    here=$NEWSARTS/out.going/$sys
  85. X    if test ! -d $here
  86. X    then
  87. X        echo "$0: cannot find batch directory for \`$sys'" >>$log
  88. X        continue
  89. X    fi
  90. X    cd $here
  91. X    PATH=$here:$origpath ; export PATH
  92. X    NEWSSITE=$sys ; export NEWSSITE        # For site-specific programs.
  93. X
  94. X    # Is there anything to do?
  95. X    files=`echo togo*`
  96. X    if test "$files" = 'togo*' || test "$files" = "togo" -a ! -s togo
  97. X    then
  98. X        continue            # no
  99. X    fi
  100. X
  101. X    # Pick up the batchparms line.
  102. X    ctlline="`egrep \"^$sys[     ]\" $parms | sed 1q`"
  103. X    if test " $ctlline" = " "
  104. X    then
  105. X        ctlline="`egrep '^/default/[     ]' $parms | sed 1q`"
  106. X    fi
  107. X    set $ctlline
  108. X    if test " $#" -ne 6
  109. X    then
  110. X        echo "$0: bad or missing batchparms line for \`$sys'" >>$log
  111. X        continue
  112. X    fi
  113. X    batchsize=$2
  114. X    limit=$3
  115. X    batcher=$4
  116. X    muncher=$5
  117. X    sender=$6
  118. X
  119. X    # How many to send?
  120. X    outstand=`queuelen $sys`
  121. X    nbatch=`expr $limit - $outstand`
  122. X    roomfor=`spacefor $batchsize outbound $sys`
  123. X    if test " $nbatch" -gt " $roomfor"
  124. X    then
  125. X        nbatch=$roomfor
  126. X    fi
  127. X
  128. X    # If not allowed to send, remember reason.
  129. X    status='batches flowing'
  130. X    if test " $nbatch" -le 0
  131. X    then
  132. X        if test " $roomfor" -le 0
  133. X        then
  134. X            status='disk too full for batching'
  135. X        else
  136. X            status='queue full, no recent movement'
  137. X        fi
  138. X    fi
  139. X
  140. X    # Try sending some.
  141. X    while test " $nbatch" -gt 0
  142. X    do
  143. X        # Does he have batches prepared already?
  144. X        if test "`echo togo.[0-9]`" = 'togo.[0-9]'
  145. X        then
  146. X            # No -- need some more batches.
  147. X            if test ! -s togo && test ! -s togo.next
  148. X            then
  149. X                break        # Nothing left to do.
  150. X            fi
  151. X            batchsplit $batchsize
  152. X        fi
  153. X
  154. X        # Send some batches.
  155. X        them=`ls | egrep '^togo\.[0-9]' | sed "${nbatch}q"`
  156. X        for f in $them
  157. X        do
  158. X            if $batcher -d $NEWSARTS $f | $muncher | $sender $sys
  159. X            then
  160. X                rm $f
  161. X            else
  162. X                echo "$0: batching for \`$sys' failed" >>$log
  163. X                exit 1
  164. X            fi
  165. X        done
  166. X        ndone=`echo $them | wc -w`
  167. X        nbatch=`expr $nbatch - $ndone`
  168. X
  169. X        # Recheck the space -- it can fall for other reasons.
  170. X        roomfor=`spacefor $batchsize outbound $sys`
  171. X        if test " $nbatch" -gt " $roomfor"
  172. X        then
  173. X            nbatch=$roomfor
  174. X        fi
  175. X    done
  176. X
  177. X    # Report status, if appropriate.
  178. X    nart=`cat togo* | wc -l | awk '{print $1}'`
  179. X    if test " $nart" -gt 0
  180. X    then
  181. X        echo "$sys    backlog $nart ($status)" >>$log
  182. X    fi
  183. Xdone
  184. !
  185. echo 'batch/batchih':
  186. sed 's/^X//' >'batch/batchih' <<'!'
  187. X#! /bin/sh
  188. X# ihave batch preparer
  189. X
  190. X# =()<. ${NEWSCONFIG-@<NEWSCONFIG>@}>()=
  191. X. ${NEWSCONFIG-/usr/lib/news/bin/config}
  192. X
  193. XPATH=$NEWSCTL/bin:$NEWSBIN/batch:$NEWSBIN:$NEWSPATH ; export PATH
  194. Xumask $NEWSUMASK
  195. X
  196. Xcase "$1"
  197. Xin
  198. X    -d)
  199. X    shift ; shift        # ignore -d option
  200. X    ;;
  201. Xesac
  202. X
  203. Xdest=`expr "$NEWSSITE" : "^\([^.]*\)\.ihave$"`
  204. Xcase "$dest"
  205. Xin
  206. X    '')
  207. X    dest="$NEWSSITE"
  208. X    ;;
  209. Xesac
  210. Xme="`newshostname`"
  211. X
  212. Xecho "Newsgroups: to.$dest"
  213. Xecho "Subject: ihave $me"
  214. Xecho "Control: ihave $me"
  215. Xecho
  216. Xexec cat $*
  217. !
  218. echo 'batch/compcun':
  219. sed 's/^X//' >'batch/compcun' <<'!'
  220. X#! /bin/sh
  221. X# Invoke compress, adding silly 2.11-compatible header.
  222. X# 12-bit compression is the lowest common denominator among news sites,
  223. X# and is often almost as good as the much-more-costly 16-bit compression.
  224. X
  225. Xecho "#! cunbatch"
  226. Xcompress -b 12
  227. Xstatus=$?
  228. Xcase "$status"
  229. Xin
  230. X    2)
  231. X    status=0        # compress stupidity
  232. X    ;;
  233. Xesac
  234. Xexit $status
  235. !
  236. echo 'batch/batcher.c':
  237. sed 's/^X//' >'batch/batcher.c' <<'!'
  238. X/*
  239. X * batcher - send a bunch of news articles as an unbatch script
  240. X *
  241. X * Usage: batcher [-d dir] listfile
  242. X *
  243. X *    where listfile is a file containing a list, one per line, of
  244. X *    full pathnames of files containing articles.  Only the first
  245. X *    field of each line is looked at, so there can be more if needed
  246. X *    for other things.
  247. X *
  248. X *    The -d option specifies a directory where most articles are
  249. X *    likely to be; the program chdirs there to speed things up.
  250. X */
  251. X
  252. X#include <stdio.h>
  253. X#include <string.h>
  254. X#include <signal.h>
  255. X#include <sys/types.h>
  256. X#include <sys/stat.h>
  257. X#include "fgetmfs.h"
  258. X
  259. X#ifndef READSIZE
  260. X#define READSIZE 8192    /* allows for even 4.2 worst case file systems */
  261. X#endif
  262. Xchar buffer[READSIZE];
  263. X
  264. Xchar *progname;
  265. X
  266. Xchar *dir = NULL;        /* NULL means don't bother chdiring. */
  267. Xint dirlen;            /* strlen(dir) */
  268. Xint debug = 0;            /* Debugging? */
  269. X
  270. Xmain(argc, argv)
  271. Xint argc;
  272. Xchar *argv[];
  273. X{
  274. X    int c;
  275. X    int errflg = 0;
  276. X    extern int optind;
  277. X    extern char *optarg;
  278. X    register FILE *list;
  279. X    char *article;
  280. X    int ret;
  281. X
  282. X    progname = argv[0];
  283. X    while ((c = getopt(argc, argv, "d:x")) != EOF)
  284. X        switch (c) {
  285. X        case 'd':    /* Directory containing many articles. */
  286. X            dir = optarg;
  287. X            dirlen = strlen(dir);
  288. X            break;
  289. X        case 'x':    /* Debugging. */
  290. X            debug++;
  291. X            break;
  292. X        case '?':
  293. X        default:
  294. X            errflg++;
  295. X            break;
  296. X        }
  297. X    if (errflg || optind != argc-1) {
  298. X        (void) fprintf(stderr,
  299. X            "Usage: batcher [-d dir] listfile\n");
  300. X        exit(2);
  301. X    }
  302. X
  303. X    list = fopen(argv[optind], "r");
  304. X    if (list == NULL)
  305. X        error("unable to open `%s'", argv[optind]);
  306. X
  307. X    if (dir != NULL)
  308. X        if (chdir(dir) < 0)
  309. X            error("can't chdir to `%s'", dir);
  310. X
  311. X    while ((article = fgetms(list)) != NULL) {
  312. X        process(article);
  313. X        free(article);
  314. X    }
  315. X    if (!feof(list))
  316. X        error("fgetmfs failure", "");
  317. X
  318. X    exit(0);
  319. X}
  320. X
  321. X/*
  322. X - process - process an article
  323. X */
  324. Xprocess(article)
  325. Xchar *article;
  326. X{
  327. X    char *p;
  328. X    register int artfile;
  329. X    register int count;
  330. X    struct stat sbuf;
  331. X
  332. X    *(article + strcspn(article, "\n\t ")) = '\0';
  333. X    if (dir != NULL && strncmp(article, dir, dirlen) == 0 &&
  334. X            article[dirlen] == '/')
  335. X        p = article+dirlen+1;
  336. X    else
  337. X        p = article;
  338. X
  339. X    artfile = open(p, 0);
  340. X    if (artfile < 0) {
  341. X        /*
  342. X         * Can't read the article.  This isn't necessarily a
  343. X         * disaster, since things like cancellations will do
  344. X         * this.  Mumble and carry on.
  345. X         */
  346. X        if (debug)
  347. X            warning("can't find `%s'", p);
  348. X        return;
  349. X    }
  350. X
  351. X    if (fstat(artfile, &sbuf) < 0)
  352. X        error("internal disaster, can't fstat", "");
  353. X    if ((sbuf.st_mode&S_IFMT) != S_IFREG) {
  354. X        close(artfile);
  355. X        return;        /* Don't try to batch directories etc. */
  356. X    }
  357. X
  358. X    (void) printf("#! rnews %ld\n", sbuf.st_size);
  359. X    fflush(stdout);
  360. X
  361. X    while ((count = read(artfile, buffer, sizeof buffer)) > 0)
  362. X        if (write(1, buffer, count) != count)
  363. X            error("write failure in `%s'", article);
  364. X    if (count < 0)
  365. X        error("read failure in `%s'", article);
  366. X
  367. X    (void) close(artfile);
  368. X}
  369. !
  370. echo 'batch/c7encode.c':
  371. sed 's/^X//' >'batch/c7encode.c' <<'!'
  372. X#include <stdio.h>
  373. X
  374. X#ifdef SCCSID
  375. Xstatic char    *SccsId = "@(#)encode.c    1.3    5/15/85";
  376. X#endif /* SCCSID */
  377. X
  378. X/*
  379. X * Produce a 7 bit printable encoding of stdin on stdout.
  380. X *
  381. X * Encoding uses acsii chars from ' ' .. 'z'
  382. X * (040 .. 0172) (0x20 - 0x7a) inclusive
  383. X *
  384. X * Method is to expand 3 chars -> 4 6 bit ones.
  385. X * Then collect 13 6 bit chars, and spread the 13th over
  386. X * the preceding 12, so that each of the 12 chars is now
  387. X * 6.5 bits.  These 2 6.5 bit chars are a little hard
  388. X * to represent on most common machines (one of these days
  389. X * sane hosts will have 1/2 bits just for this program)
  390. X * so we take a pair of them, and represent that in 13 bits.
  391. X * 13 bits (max value 8191) can be represented as
  392. X *    A * 91 + B
  393. X * where A < 91, B < 91  (91^2 == 8281, so it fits!)
  394. X *
  395. X * Each of A and B is encoded as a character by adding 32
  396. X * to make it printable (ie: 0x20).
  397. X *
  398. X * The termination conditions are foul beyond belief.  Don't
  399. X * monkey with them!
  400. X *
  401. X * If you think its a fluke that 040 .. 0171 just happen to
  402. X * be the chars that Piet Beertema's uucp 'f' protocol transmits
  403. X * as single bytes, you're insane.  0172 chars are produced
  404. X * with lower frequency than any other (given random data)
  405. X * so the doubling that occurs with that we will just suffer.
  406. X * (A newer 'f' proto, sometime, will probably not use 0172)
  407. X */
  408. X
  409. X/*
  410. X * the following pair of characters cannot legally occur
  411. X * in normal output (since 90*91 + 90 == 8280, which > 2^13)
  412. X * so we use them to indicate that the data that follows is the
  413. X * terminator.  The character immediately following this
  414. X * pair is the length of the (expanded) terminator (which
  415. X * otherwise might be indeterminable)
  416. X */
  417. X#define    ENDMARK1    ((90*91 + 90) / 91 + ' ')
  418. X#define    ENDMARK2    ((90*91 + 90) % 91 + ' ')
  419. X
  420. Xmain()
  421. X{
  422. X    register char *p;
  423. X    register char *e;
  424. X    register c;
  425. X    char b3[3];
  426. X
  427. X    p = b3;
  428. X    e = b3 + 3;
  429. X    while ((c = getchar()) != EOF) {
  430. X        *p++ = c;
  431. X        if (p == e) {
  432. X            encode(b3, 3);
  433. X            p = b3;
  434. X        }
  435. X    }
  436. X    encode(b3, p - b3);
  437. X    flushout();
  438. X    exit(0);
  439. X}
  440. X
  441. Xstatic char b13[13];
  442. Xstatic int cnt = 0;
  443. X
  444. Xencode(c, n)
  445. X    register char *c;
  446. X    int n;
  447. X{
  448. X    register char *p;
  449. X    register i = cnt;
  450. X    register j;
  451. X    char b4[4];
  452. X
  453. X    p = b4;
  454. X
  455. X    p[0] = (c[0] >> 2) & 0x3f;
  456. X    p[1] = ((c[0] & 0x3) << 4) | ((c[1] >> 4) & 0xf);
  457. X    p[2] = ((c[1] & 0xF) << 2) | ((c[2] >> 6) & 0x3);
  458. X    if (n == 3)
  459. X        p[3] = c[2] & 0x3f;
  460. X    else
  461. X        p[3] = n;
  462. X
  463. X    c = &b13[i];
  464. X    for (j = 4; --j >= 0; i++) {
  465. X        if (i == 13) {
  466. X            dumpcode(b13, 13);
  467. X            c = b13;
  468. X            i = 0;
  469. X        }
  470. X        *c++ = *p++;
  471. X    }
  472. X    cnt = i;
  473. X}
  474. X
  475. Xflushout()
  476. X{
  477. X    putchar(ENDMARK1);
  478. X    putchar(ENDMARK2);
  479. X    putchar(cnt + ' ');
  480. X    dumpcode(b13, cnt);
  481. X}
  482. X
  483. Xdumpcode(p, n)
  484. X    register char *p;
  485. X    register int n;
  486. X{
  487. X    register last;
  488. X    register c;
  489. X
  490. X    if (n == 13)
  491. X        n--, last = p[12];
  492. X    else if (n & 1)
  493. X        last = (1 << (6-1));
  494. X    else
  495. X        last = 0;
  496. X
  497. X    for ( ; n > 0; n -= 2) {
  498. X        c = *p++ << 6;
  499. X        c |= *p++;
  500. X        if (last & (1 << (6-1)))
  501. X            c |= (1 << 12);
  502. X        last <<= 1;
  503. X
  504. X        /*
  505. X         * note: 91^2 > 2^13, 90^2 < 2^13, (91 + ' ') is printable
  506. X         */
  507. X
  508. X        /* oh for a compiler that would only do one division... */
  509. X        putchar((c / 91) + ' ');
  510. X        putchar((c % 91) + ' ');
  511. X    }
  512. X}
  513. !
  514. echo 'batch/coder.h':
  515. sed 's/^X//' >'batch/coder.h' <<'!'
  516. Xchar header[] = "Decode the following with bdecode\n";
  517. Xchar codeset[] =
  518. X    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";
  519. X
  520. X#define ENCODE(c)    codeset[c]
  521. X
  522. Xextern short crctab[];
  523. X#define CRC(crc, c)     crc = (crc >> 8) ^ crctab[(crc^c) & 0xff]
  524. !
  525. echo 'batch/viamail':
  526. sed 's/^X//' >'batch/viamail' <<'!'
  527. X#! /bin/sh
  528. X# send via mail, unprotected (typically used for bencode output only)
  529. X
  530. X( echo ; cat ) | mail $1!rnews
  531. !
  532. echo 'batch/viainews':
  533. sed 's/^X//' >'batch/viainews' <<'!'
  534. X#! /bin/sh
  535. X# Feed batch to inews, for ihave/sendme mostly.
  536. X
  537. Xexec inews -h -W
  538. !
  539. echo 'batch/nocomp':
  540. sed 's/^X//' >'batch/nocomp' <<'!'
  541. X#! /bin/sh
  542. X# Null muncher, for uncompressed links.
  543. X
  544. Xexec cat $*
  545. !
  546. echo 'batch/bencode.c':
  547. sed 's/^X//' >'batch/bencode.c' <<'!'
  548. X/*
  549. X * bencode [file]
  550. X */
  551. X#include <stdio.h>
  552. X#include "coder.h"
  553. X#define MAXPERLINE 78        /* max chars/line */
  554. Xchar *myname;
  555. X
  556. Xmain(argc,argv) 
  557. X    char **argv;
  558. X{
  559. X    register FILE *fin = stdin, *fout = stdout; /* faster in a register */
  560. X    register int c, bcount, ccount = MAXPERLINE-1;
  561. X    register long word, nbytes;
  562. X    register int crc;
  563. X
  564. X    myname = argv[0];
  565. X    if (sizeof(word) < 4)
  566. X        fprintf(stderr, "%s: word size too small\n", myname), exit(1);
  567. X    if (argc == 2 && (fin = fopen(argv[1], "r")) == NULL) {
  568. X        fprintf(stderr, "%s: ", myname);
  569. X        perror(argv[1]);
  570. X        exit(1);
  571. X    }
  572. X    else if (argc > 2) {
  573. X        fprintf(stderr, "Usage: %s [file]\n", myname);
  574. X        exit(1);
  575. X    }
  576. X
  577. X#define PUTC(c) \
  578. X    putc(c, fout); \
  579. X    if (--ccount == 0) { \
  580. X        putc('\n', fout); \
  581. X        ccount = MAXPERLINE-1; \
  582. X    }
  583. X
  584. X    fputs(header, fout);
  585. X    word = 0;
  586. X    bcount = 3;
  587. X    crc = 0;
  588. X    for (nbytes = 0; (c = getc(fin)) != EOF; nbytes++) {
  589. X        CRC(crc, c);
  590. X        word <<= 8;
  591. X        word |= c;
  592. X        if (--bcount == 0) {
  593. X            PUTC(ENCODE((word >> 18) & 077));
  594. X            PUTC(ENCODE((word >> 12) & 077));
  595. X            PUTC(ENCODE((word >>  6) & 077));
  596. X            PUTC(ENCODE((word      ) & 077));
  597. X            word = 0;
  598. X            bcount = 3;
  599. X        }
  600. X    }
  601. X    /*
  602. X     * A trailing / marks end of data.
  603. X     * The last partial encoded word follows in hex,
  604. X     * preceded by a byte count.
  605. X     */
  606. X    if (ccount != MAXPERLINE-1)    /* avoid empty lines */
  607. X        putc('\n', fout);
  608. X    fprintf(fout, "/%d%x\n", 3-bcount, word);
  609. X    /*
  610. X     * And finally the byte count and CRC.
  611. X     */
  612. X    fprintf(fout, "%ld %x\n", nbytes, crc & 0xffff);
  613. X    exit(0);
  614. X}
  615. !
  616. echo 'batch/crctab.c':
  617. sed 's/^X//' >'batch/crctab.c' <<'!'
  618. X/* generated using the CRC-16 polynomial x^16 + x^15 + x^2 + 1 = 0120001 */
  619. Xshort crctab[256] = {
  620. X    0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
  621. X    0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
  622. X    0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
  623. X    0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
  624. X    0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
  625. X    0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
  626. X    0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
  627. X    0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
  628. X    0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
  629. X    0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
  630. X    0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
  631. X    0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
  632. X    0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
  633. X    0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
  634. X    0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
  635. X    0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
  636. X    0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
  637. X    0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
  638. X    0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
  639. X    0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
  640. X    0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
  641. X    0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
  642. X    0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
  643. X    0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
  644. X    0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
  645. X    0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
  646. X    0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
  647. X    0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
  648. X    0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
  649. X    0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
  650. X    0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
  651. X    0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
  652. X};
  653. !
  654. echo 'batch/compb':
  655. sed 's/^X//' >'batch/compb' <<'!'
  656. X#! /bin/sh
  657. X# like comp except use bencode
  658. X
  659. X# =()<. ${NEWSCONFIG-@<NEWSCONFIG>@}>()=
  660. X. ${NEWSCONFIG-/usr/lib/news/bin/config}
  661. X
  662. XPATH=$NEWSCTL/bin:$NEWSBIN/batch:$NEWSBIN:$NEWSPATH ; export PATH
  663. Xumask $NEWSUMASK
  664. X
  665. Xcompress -b 12 | bencode
  666. Xexit 0                # compress exit status sometimes stupid
  667. !
  668. echo 'batch/viapmail':
  669. sed 's/^X//' >'batch/viapmail' <<'!'
  670. X#! /bin/sh
  671. X# send via mail (protected against stupid mailers)
  672. X
  673. X( echo ; sed 's/^/N/' ) | mail $1!rnews
  674. !
  675. echo 'contrib/putenv.alt.c':
  676. sed 's/^X//' >'contrib/putenv.alt.c' <<'!'
  677. X/*
  678. X * From: chip@ateng.ateng.com (Chip Salzenberg)
  679. X * Newsgroups: comp.unix.wizards
  680. X * Subject: Re: replacement for putenv()
  681. X * Date: 13 Feb 89 16:51:05 GMT
  682. X * 
  683. X * Here is a rather nice replacement for putenv().  I wrote it for the BSD port
  684. X * of my deliver program.  (I know it's source, but it's short.)  Its nicest
  685. X * feature is the avoidance of memory waste when it is called several times.
  686. X */
  687. X
  688. Xint
  689. Xputenv(s)
  690. Xchar *s;
  691. X{
  692. X    static char **env_array;
  693. X    static int env_size;
  694. X    char *e;
  695. X    int i, j;
  696. X
  697. X    if (env_array == NULL) {
  698. X        for (i = 0; environ[i]; ++i)
  699. X            ;
  700. X        env_size = i + 10;          /* arbitrary */
  701. X        env_array = (char **) malloc(env_size * sizeof(char *));
  702. X        if (env_array == NULL)
  703. X            return 1;
  704. X        memcpy((char *)env_array, (char *)environ,
  705. X               (int) ((i + 1) * sizeof(char *)));
  706. X        environ = env_array;
  707. X    } else if (environ != env_array)
  708. X        fprintf(stderr, "putenv: warning: someone moved environ!\n");
  709. X
  710. X    if ((e = strchr(s, '=')) != NULL)
  711. X        ++e;
  712. X    else
  713. X        e = s + strlen(s);
  714. X
  715. X    j = 0;
  716. X    for (i = 0; env_array[i]; ++i)
  717. X        if (strncmp(env_array[i], s, e - s) != 0)
  718. X            env_array[j++] = env_array[i];
  719. X
  720. X    if (j + 1 >= env_size) {
  721. X        env_size += 10;                 /* arbitrary */
  722. X        env_array = (char **) realloc((char *)env_array,
  723. X                    env_size * sizeof(char **));
  724. X        if (env_array == NULL)
  725. X            return 1;
  726. X    }
  727. X
  728. X    env_array[j++] = s;
  729. X    env_array[j] = NULL;
  730. X
  731. X    environ = env_array;
  732. X    return 0;
  733. X}
  734. !
  735. echo 'contrib/dbz':
  736. sed 's/^X//' >'contrib/dbz' <<'!'
  737. XFrom utgpu!jarvis.csri.toronto.edu!mailrus!sharkey!b-tech!zeeff Tue Feb  7 17:19:31 EST 1989
  738. XArticle: 1900 of news.software.b:
  739. XPath: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!sharkey!b-tech!zeeff
  740. XFrom: zeeff@b-tech.ann-arbor.mi.us (Jon Zeeff)
  741. XNewsgroups: news.software.b
  742. XSubject: Re: Dbz and news 2.11
  743. XMessage-ID: <5095@b-tech.ann-arbor.mi.us>
  744. XDate: 4 Feb 89 18:56:09 GMT
  745. XReferences: <20@bungia.Bungia.MN.ORG>
  746. XReply-To: zeeff@b-tech.ann-arbor.mi.us (Jon Zeeff)
  747. XDistribution: usa
  748. XOrganization: Branch Technology Ann Arbor, MI
  749. XLines: 322
  750. X
  751. XIn article <20@bungia.Bungia.MN.ORG> ahby@bungia.MN.ORG (Shane P. McCarron) writes:
  752. X>Some time ago the dbz sources were posted for use with news 2.11.
  753. X>Patches have been posted, and a number of sites are using these
  754. X>routines to make news run faster on machines without dbm libraries.  I
  755. X>seem to remember some controversy surrounding the use of these
  756. X>routines.  Something about their containing AT&T proprietary stuff?  I
  757. X>realize that by asking this I am going to get a hundred answers, all
  758. X>of them different.  What I am really looking for is ONE AUTHORITATIVE
  759. X>ANSWER.  Can anyone out there say for sure whether this code is freely
  760. X>distributable or not?
  761. X
  762. XAs the author, I suppose I can supply an authorative answer.  Dbz 
  763. Xcontains no AT&T code at all.  The only thing in it not written by me 
  764. Xis the hashing, and that is taken from pathalias (with permission).  
  765. X
  766. XHere it is if anyone missed it:
  767. X
  768. X
  769. X/*
  770. Xdbz.c  V1.5
  771. X
  772. XCopyright 1988 Jon Zeeff (umix!b-tech!zeeff)
  773. XYou can use this code in any manner, as long as you leave my name on it
  774. Xand don't hold me responsible for any problems with it.
  775. X
  776. XHacked on by gdb@ninja.UUCP (David Butler); Sun Jun  5 00:27:08 CDT 1988
  777. X
  778. XThese routines replace dbm as used by the usenet news software
  779. X(it's not a full dbm replacement by any means).  It's fast and
  780. Xsimple.  It contains no AT&T code.
  781. X
  782. XBSD sites will notice some savings in disk space.  Sys V sites without
  783. Xdbm will notice much faster operation.
  784. X
  785. XNote: .pag files created by version 1.[0-3] need to be recreated before
  786. X      using this version.
  787. X
  788. XThis code relies on the fact that news stores a pointer to the history
  789. Xfile as the dbm data.  It doesn't store another copy of the key like
  790. Xdbm does so it saves disk space.  All you can do is fetch() and
  791. Xstore() data.
  792. X
  793. XJust make news with the DBM option and link with dbz.o.
  794. X*/
  795. X
  796. X/*
  797. X   Set this to the something several times larger than the maximum # of
  798. X   lines in a history file.  It should be a prime number.
  799. X*/
  800. X#define INDEX_SIZE 99991L
  801. X
  802. X#define DEBUG if (0) printf              /* for no debugging */
  803. X/* #define DEBUG if (1) printf          /* for debugging */
  804. X/* #define DEBUG if (debug) printf        /* for "rn" type debugging */
  805. X
  806. X/* Note: let the optimizer remove any if(0) or if(1) code above */
  807. X
  808. X#include <fcntl.h>
  809. X#include <string.h>
  810. X#include <ctype.h>
  811. X
  812. Xlong lseek();
  813. X
  814. Xstatic long get_ptr();
  815. Xstatic int put_ptr();
  816. Xstatic void lcase();
  817. Xstatic long hash();
  818. Xstatic void crcinit();
  819. X
  820. Xtypedef struct {
  821. X    char *dptr;
  822. X    int dsize;
  823. X} datum;
  824. X
  825. Xstatic int Data_fd;        /* points to /usr/lib/news/[n]history */
  826. Xstatic int Index_fd = -1;    /* points to /usr/lib/news/[n]history.pag */
  827. X
  828. Xint 
  829. Xdbminit(name)
  830. Xchar *name;
  831. X{
  832. X        char index_file[1024];    /* index file name */
  833. X    void crcinit();
  834. X
  835. X    if (Index_fd >= 0) {
  836. X        DEBUG("dbminit: dbminit aready called once\n");
  837. X        return(-1);    /* init already called once */
  838. X    }
  839. X
  840. X    strcpy(index_file, name);
  841. X    strcat(index_file, ".pag");
  842. X
  843. X    /* if we don't have permission to open the pag file for read/write */
  844. X    /* then we may never attempt a store().  If we do, it will fail */
  845. X
  846. X    if ((Index_fd = open(index_file, O_RDWR)) < 0 &&
  847. X        (Index_fd = open(index_file, O_RDONLY)) < 0 &&
  848. X        (Index_fd = open(index_file, O_CREAT | O_RDWR, 0644)) < 0) 
  849. X    {
  850. X        DEBUG("dbminit: Index_file open failed\n");
  851. X        return(-1);
  852. X    }
  853. X
  854. X    if ((Data_fd = open(name, O_RDONLY)) < 0) {
  855. X
  856. X        /* The only time the data file does not exist is when */
  857. X        /* expire is running (as "news") and it is ok to create it */
  858. X        /* If we don't have "permission" the create will fail, too */
  859. X
  860. X        if (close(creat(name, 0644)) < 0 ||
  861. X            (Data_fd = open(name, O_RDONLY)) < 0) {
  862. X            DEBUG("dbminit: Data_file open failed\n");
  863. X            close(Index_fd);
  864. X            Index_fd = -1;
  865. X            return(-1);
  866. X        }
  867. X    }
  868. X
  869. X    crcinit();    /* initialize the crc table */
  870. X    DEBUG("dbminit: succeeded\n");
  871. X    return(0);
  872. X}
  873. X
  874. Xint
  875. Xdbmclose()
  876. X{
  877. X    if (Index_fd >= 0) {
  878. X        close(Index_fd);
  879. X        Index_fd = -1;
  880. X        close(Data_fd);
  881. X    }
  882. X    DEBUG("dbmclose: succeeded\n");
  883. X    return(0);
  884. X}
  885. X
  886. X/* get an entry from the database */
  887. Xdatum
  888. Xfetch(key)
  889. Xdatum key;
  890. X{
  891. X    long index_ptr;
  892. X    long index_size = INDEX_SIZE;
  893. X        char buffer[1024];
  894. X    static long data_ptr;
  895. X    datum output;
  896. X    long hash();
  897. X    long get_ptr();
  898. X    void lcase();
  899. X
  900. X    DEBUG("fetch: (%s)\n", key.dptr);
  901. X
  902. X    for (index_ptr = hash(key.dptr, key.dsize);
  903. X        --index_size && (data_ptr = get_ptr(index_ptr)) >= 0L;
  904. X        index_ptr = ++index_ptr % INDEX_SIZE) {
  905. X
  906. X        lseek(Data_fd, data_ptr, 0);
  907. X        read(Data_fd, buffer, (unsigned)key.dsize);
  908. X
  909. X        /* key should be article id and no tab */
  910. X
  911. X        /* lcase(buffer, key.dsize);    lcase is a B news botch */
  912. X        if (buffer[key.dsize - 1] == '\t') {
  913. X            buffer[key.dsize - 1] = '\0';
  914. X        }
  915. X
  916. X        DEBUG("fetch: buffer (%s)\n", buffer);
  917. X        if (strncmp(key.dptr, buffer, key.dsize) == 0) {
  918. X            /* we found it */
  919. X            output.dptr = (char *)&data_ptr;
  920. X            output.dsize = sizeof(long);
  921. X            DEBUG("fetch: successful\n");
  922. X            return(output);
  923. X        }
  924. X    }
  925. X
  926. X    /* we didn't find it */
  927. X
  928. X    output.dptr = (char *)0;
  929. X    output.dsize = 0;
  930. X    DEBUG("fetch: failed\n");
  931. X    return(output);
  932. X}
  933. X
  934. X/* add an entry to the database */
  935. Xstore(key, data)
  936. Xdatum key;
  937. Xdatum data;
  938. X{
  939. X    /* lint complains about a possible pointer alignment problem here */
  940. X    /* it is not a problem because dptr is the first element of a */
  941. X    /* structure and should be aligned for anything */
  942. X    DEBUG("store: (%s, %ld)\n", key.dptr, *((long *)data.dptr));
  943. X    return(put_ptr(hash(key.dptr, key.dsize), *((long *)data.dptr)));
  944. X}
  945. X
  946. X/* get a data file pointer from the specified location in the index file */
  947. X
  948. Xstatic long
  949. Xget_ptr(index_ptr)
  950. Xlong index_ptr;
  951. X{
  952. X    long data_ptr;
  953. X
  954. X    DEBUG("get_ptr: (%ld)\n", index_ptr);
  955. X
  956. X    /* seek to where it should be */
  957. X    lseek(Index_fd, (long)(index_ptr * sizeof(long)) ,0);
  958. X
  959. X    /* read it */
  960. X    if (read(Index_fd, (char *)&data_ptr, sizeof(long)) != sizeof(long) ||
  961. X        data_ptr == 0L) {
  962. X        DEBUG("get_ptr: failed\n");
  963. X        return(-1L);
  964. X    }
  965. X    DEBUG("get_ptr: succeeded\n");
  966. X    return(--data_ptr);    /* remove the offset we added in put_ptr */
  967. X}
  968. X
  969. X/* put a data file pointer into the specified location in the index file */
  970. X/* move down further if slots are full (linear probing) */
  971. Xstatic
  972. Xput_ptr(index_ptr, data_ptr)
  973. Xlong index_ptr;
  974. Xlong data_ptr;
  975. X{
  976. X    long get_ptr();
  977. X    long index_size = INDEX_SIZE;
  978. X
  979. X    /* find an empty slot */
  980. X    while (--index_size && get_ptr(index_ptr) >= 0L) {
  981. X        index_ptr = ++index_ptr % INDEX_SIZE;
  982. X    }
  983. X
  984. X    if (index_size == 0L) {
  985. X        DEBUG("put_ptr: hash table overflow - failed\n");
  986. X        return(-1);
  987. X    }
  988. X
  989. X    /* seek to spot */
  990. X    lseek(Index_fd, (long)(index_ptr * sizeof(long)), 0);
  991. X
  992. X    ++data_ptr;   /* add one so that we can use 0 as no pointer */
  993. X
  994. X    /* write in data */
  995. X    if (write(Index_fd, (char *)&data_ptr, sizeof(long)) != sizeof(long)) {
  996. X        DEBUG("put_ptr: write failed\n");
  997. X        return(-1);
  998. X    }
  999. X
  1000. X    DEBUG("put_ptr: succeeded\n");
  1001. X    return(0);
  1002. X}
  1003. X
  1004. Xstatic void
  1005. Xlcase(s, n)
  1006. Xregister char *s;
  1007. Xregister int n;
  1008. X{
  1009. X    for (; n > 0; --n, ++s) {
  1010. X        *s = tolower(*s);
  1011. X    }
  1012. X}
  1013. X
  1014. X/* This is a simplified version of the pathalias hashing function.
  1015. X * Thanks to Steve Belovin and Peter Honeyman
  1016. X *
  1017. X * hash a string into a long int.  31 bit crc (from andrew appel).
  1018. X * the crc table is computed at run time by crcinit() -- we could
  1019. X * precompute, but it takes 1 clock tick on a 750.
  1020. X *
  1021. X * This fast table calculation works only if POLY is a prime polynomial
  1022. X * in the field of integers modulo 2.  Since the coefficients of a
  1023. X * 32-bit polynomial won't fit in a 32-bit word, the high-order bit is
  1024. X * implicit.  IT MUST ALSO BE THE CASE that the coefficients of orders
  1025. X * 31 down to 25 are zero.  Happily, we have candidates, from
  1026. X * E. J.  Watson, "Primitive Polynomials (Mod 2)", Math. Comp. 16 (1962):
  1027. X *    x^32 + x^7 + x^5 + x^3 + x^2 + x^1 + x^0
  1028. X *    x^31 + x^3 + x^0
  1029. X *
  1030. X * We reverse the bits to get:
  1031. X *    111101010000000000000000000000001 but drop the last 1
  1032. X *         f   5   0   0   0   0   0   0
  1033. X *    010010000000000000000000000000001 ditto, for 31-bit crc
  1034. X *       4   8   0   0   0   0   0   0
  1035. X */
  1036. X
  1037. X#define POLY 0x48000000L    /* 31-bit polynomial (avoids sign problems) */
  1038. X
  1039. Xstatic long CrcTable[128];
  1040. X
  1041. Xstatic void
  1042. Xcrcinit()
  1043. X{    register int i, j;
  1044. X    register long sum;
  1045. X
  1046. X    for (i = 0; i < 128; ++i) {
  1047. X        sum = 0L;
  1048. X        for (j = 7 - 1; j >= 0; --j)
  1049. X            if (i & (1 << j))
  1050. X                sum ^= POLY >> j;
  1051. X        CrcTable[i] = sum;
  1052. X    }
  1053. X    DEBUG("crcinit: done\n");
  1054. X}
  1055. X
  1056. Xstatic long
  1057. Xhash(name, size)
  1058. Xregister char *name;
  1059. Xregister int size;
  1060. X{
  1061. X    register long sum = 0L;
  1062. X
  1063. X    while (size--) {
  1064. X        sum = (sum >> 7) ^ CrcTable[(sum ^ (*name++)) & 0x7f];
  1065. X    }
  1066. X    DEBUG("hash: returns (%ld)\n", sum % INDEX_SIZE);
  1067. X    return(sum % INDEX_SIZE);
  1068. X}
  1069. X
  1070. X-- 
  1071. X  Jon Zeeff            zeeff@b-tech.ann-arbor.mi.us
  1072. X  Ann Arbor, MI            mailrus!b-tech!zeeff
  1073. X
  1074. X
  1075. !
  1076. echo 'contrib/dirfns':
  1077. sed 's/^X//' >'contrib/dirfns' <<'!'
  1078. Xecho 'directory.3':
  1079. Xsed 's/^X//' >'directory.3' <<'!'
  1080. XX.TH DIRECTORY 3 imported
  1081. XX.DA 9 Oct 1985
  1082. XX.SH NAME
  1083. XXopendir, readdir, telldir, seekdir, rewinddir, closedir \- high-level directory operations
  1084. XX.SH SYNOPSIS
  1085. XX.B #include <sys/types.h>
  1086. XX.br
  1087. XX.B #include <ndir.h>
  1088. XX.PP
  1089. XX.SM
  1090. XX.B DIR
  1091. XX.B *opendir(filename)
  1092. XX.br
  1093. XX.B char *filename;
  1094. XX.PP
  1095. XX.SM
  1096. XX.B struct direct
  1097. XX.B *readdir(dirp)
  1098. XX.br
  1099. XX.B DIR *dirp;
  1100. XX.PP
  1101. XX.SM
  1102. XX.B long
  1103. XX.B telldir(dirp)
  1104. XX.br
  1105. XX.B DIR *dirp;
  1106. XX.PP
  1107. XX.SM
  1108. XX.B seekdir(dirp, loc)
  1109. XX.br
  1110. XX.B DIR *dirp;
  1111. XX.br
  1112. XX.B long loc;
  1113. XX.PP
  1114. XX.SM
  1115. XX.B rewinddir(dirp)
  1116. XX.br
  1117. XX.B DIR *dirp;
  1118. XX.PP
  1119. XX.SM
  1120. XX.B closedir(dirp)
  1121. XX.br
  1122. XX.B DIR *dirp;
  1123. XX.SH DESCRIPTION
  1124. XXThis library provides high-level primitives for directory scanning,
  1125. XXsimilar to those available for 4.2BSD's (very different) directory system.
  1126. XX.\"The purpose of this library is to simulate
  1127. XX.\"the new flexible length directory names of 4.2bsd UNIX
  1128. XX.\"on top of the old directory structure of v7.
  1129. XXIt incidentally provides easy portability to and from 4.2BSD (insofar
  1130. XXas such portability is not compromised by other 4.2/VAX dependencies).
  1131. XX.\"It allows programs to be converted immediately
  1132. XX.\"to the new directory access interface,
  1133. XX.\"so that they need only be relinked
  1134. XX.\"when moved to 4.2bsd.
  1135. XX.\"It is obtained with the loader option
  1136. XX.\".BR \-lndir .
  1137. XX.PP
  1138. XX.I Opendir
  1139. XXopens the directory named by
  1140. XX.I filename
  1141. XXand associates a
  1142. XX.I directory stream
  1143. XXwith it.
  1144. XX.I Opendir
  1145. XXreturns a pointer to be used to identify the
  1146. XX.I directory stream
  1147. XXin subsequent operations.
  1148. XXThe pointer
  1149. XX.SM
  1150. XX.B NULL
  1151. XXis returned if
  1152. XX.I filename
  1153. XXcannot be accessed or is not a directory.
  1154. XX.PP
  1155. XX.I Readdir
  1156. XXreturns a pointer to the next directory entry.
  1157. XXIt returns
  1158. XX.B NULL
  1159. XXupon reaching the end of the directory or detecting
  1160. XXan invalid
  1161. XX.I seekdir
  1162. XXoperation.
  1163. XX.PP
  1164. XX.I Telldir
  1165. XXreturns the current location associated with the named
  1166. XX.I directory stream.
  1167. XX.PP
  1168. XX.I Seekdir
  1169. XXsets the position of the next
  1170. XX.I readdir
  1171. XXoperation on the
  1172. XX.I directory stream.
  1173. XXThe new position reverts to the one associated with the
  1174. XX.I directory stream
  1175. XXwhen the
  1176. XX.I telldir
  1177. XXoperation was performed.
  1178. XXValues returned by
  1179. XX.I telldir
  1180. XXare good only for the lifetime of the DIR pointer from 
  1181. XXwhich they are derived.
  1182. XXIf the directory is closed and then reopened, 
  1183. XXthe 
  1184. XX.I telldir
  1185. XXvalue may be invalidated
  1186. XXdue to undetected directory compaction in 4.2BSD.
  1187. XXIt is safe to use a previous
  1188. XX.I telldir
  1189. XXvalue immediately after a call to
  1190. XX.I opendir
  1191. XXand before any calls to
  1192. XX.I readdir.
  1193. XX.PP
  1194. XX.I Rewinddir
  1195. XXresets the position of the named
  1196. XX.I directory stream
  1197. XXto the beginning of the directory.
  1198. XX.PP
  1199. XX.I Closedir
  1200. XXcauses the named
  1201. XX.I directory stream
  1202. XXto be closed,
  1203. XXand the structure associated with the DIR pointer to be freed.
  1204. XX.PP
  1205. XXA
  1206. XX.I direct
  1207. XXstructure is as follows:
  1208. XX.PP
  1209. XX.RS
  1210. XX.nf
  1211. XXstruct    direct {
  1212. XX    /* unsigned */ long    d_ino;    /* inode number of entry */
  1213. XX    unsigned short    d_reclen;    /* length of this record */
  1214. XX    unsigned short    d_namlen;    /* length of string in d_name */
  1215. XX    char    d_name[MAXNAMLEN + 1];    /* name must be no longer than this */
  1216. XX};
  1217. XX.fi
  1218. XX.RE
  1219. XX.PP
  1220. XXThe
  1221. XX.I d_reclen
  1222. XXfield is meaningless in non-4.2BSD systems and should be ignored.
  1223. XXThe use of a
  1224. XX.I long
  1225. XXfor
  1226. XX.I d_ino
  1227. XXis also a 4.2BSDism;
  1228. XX.I ino_t
  1229. XX(see
  1230. XX.IR types (5))
  1231. XXshould be used elsewhere.
  1232. XXThe macro
  1233. XX.I DIRSIZ(dp)
  1234. XXgives the minimum memory size needed to hold the
  1235. XX.I direct
  1236. XXvalue pointed to by
  1237. XX.IR dp ,
  1238. XXwith the minimum necessary allocation for
  1239. XX.IR d_name .
  1240. XX.PP
  1241. XXThe preferred way to search the current directory for entry ``name'' is:
  1242. XX.PP
  1243. XX.RS
  1244. XX.nf
  1245. XX    len = strlen(name);
  1246. XX    dirp = opendir(".");
  1247. XX    if (dirp == NULL) {
  1248. XX        fprintf(stderr, "%s: can't read directory .\\n", argv[0]);
  1249. XX        return NOT_FOUND;
  1250. XX    }
  1251. XX    while ((dp = readdir(dirp)) != NULL)
  1252. XX        if (dp->d_namlen == len && strcmp(dp->d_name, name) == 0) {
  1253. XX            closedir(dirp);
  1254. XX            return FOUND;
  1255. XX        }
  1256. XX    closedir(dirp);
  1257. XX    return NOT_FOUND;
  1258. XX.RE
  1259. XX.\".SH LINKING
  1260. XX.\"This library is accessed by specifying ``-lndir'' as the
  1261. XX.\"last argument to the compile line, e.g.:
  1262. XX.\".PP
  1263. XX.\"    cc -I/usr/include/ndir -o prog prog.c -lndir
  1264. XX.SH "SEE ALSO"
  1265. XXopen(2),
  1266. XXclose(2),
  1267. XXread(2),
  1268. XXlseek(2)
  1269. XX.SH HISTORY
  1270. XXWritten by
  1271. XXKirk McKusick at Berkeley (ucbvax!mckusick).
  1272. XXMiscellaneous bug fixes from elsewhere.
  1273. XXThe size of the data structure has been decreased to avoid excessive
  1274. XXspace waste under V7 (where filenames are 14 characters at most).
  1275. XXFor obscure historical reasons, the include file is also available
  1276. XXas
  1277. XX.IR <ndir/sys/dir.h> .
  1278. XXThe Berkeley version lived in a separate library (\fI\-lndir\fR),
  1279. XXwhereas ours is
  1280. XXpart of the C library, although the separate library is retained to
  1281. XXmaximize compatibility.
  1282. XX.PP
  1283. XXThis manual page has been substantially rewritten to be informative in
  1284. XXthe absence of a 4.2BSD manual.
  1285. XX.SH BUGS
  1286. XXThe
  1287. XX.I DIRSIZ
  1288. XXmacro actually wastes a bit of space due to some padding requirements
  1289. XXthat are an artifact of 4.2BSD.
  1290. XX.PP
  1291. XXThe returned value of
  1292. XX.I readdir
  1293. XXpoints to a static area that will be overwritten by subsequent calls.
  1294. XX.PP
  1295. XXThere are some unfortunate name conflicts with the \fIreal\fR V7
  1296. XXdirectory structure definitions.
  1297. X!
  1298. Xecho 'dir.h':
  1299. Xsed 's/^X//' >'dir.h' <<'!'
  1300. XX/*    dir.h    4.4    82/07/25    */
  1301. XX
  1302. XX/*
  1303. XX * A directory consists of some number of blocks of DIRBLKSIZ
  1304. XX * bytes, where DIRBLKSIZ is chosen such that it can be transferred
  1305. XX * to disk in a single atomic operation (e.g. 512 bytes on most machines).
  1306. XX *
  1307. XX * Each DIRBLKSIZ byte block contains some number of directory entry
  1308. XX * structures, which are of variable length.  Each directory entry has
  1309. XX * a struct direct at the front of it, containing its inode number,
  1310. XX * the length of the entry, and the length of the name contained in
  1311. XX * the entry.  These are followed by the name padded to a 4 byte boundary
  1312. XX * with null bytes.  All names are guaranteed null terminated.
  1313. XX * The maximum length of a name in a directory is MAXNAMLEN.
  1314. XX *
  1315. XX * The macro DIRSIZ(dp) gives the amount of space required to represent
  1316. XX * a directory entry.  Free space in a directory is represented by
  1317. XX * entries which have dp->d_reclen >= DIRSIZ(dp).  All DIRBLKSIZ bytes
  1318. XX * in a directory block are claimed by the directory entries.  This
  1319. XX * usually results in the last entry in a directory having a large
  1320. XX * dp->d_reclen.  When entries are deleted from a directory, the
  1321. XX * space is returned to the previous entry in the same directory
  1322. XX * block by increasing its dp->d_reclen.  If the first entry of
  1323. XX * a directory block is free, then its dp->d_ino is set to 0.
  1324. XX * Entries other than the first in a directory do not normally have
  1325. XX * dp->d_ino set to 0.
  1326. XX */
  1327. XX#define DIRBLKSIZ    512
  1328. XX#ifdef VMUNIX
  1329. XX#define    MAXNAMLEN    255
  1330. XX#else
  1331. XX#define    MAXNAMLEN    14
  1332. XX#endif
  1333. XX
  1334. XXstruct    direct {
  1335. XX    /* unsigned */ long    d_ino;    /* inode number of entry */
  1336. XX    unsigned short    d_reclen;    /* length of this record */
  1337. XX    unsigned short    d_namlen;    /* length of string in d_name */
  1338. XX    char    d_name[MAXNAMLEN + 1];    /* name must be no longer than this */
  1339. XX};
  1340. XX
  1341. XX/*
  1342. XX * The DIRSIZ macro gives the minimum record length which will hold
  1343. XX * the directory entry.  This requires the amount of space in struct direct
  1344. XX * without the d_name field, plus enough space for the name with a terminating
  1345. XX * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
  1346. XX */
  1347. XX#undef DIRSIZ
  1348. XX#define DIRSIZ(dp) \
  1349. XX    ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
  1350. XX
  1351. XX#ifndef KERNEL
  1352. XX/*
  1353. XX * Definitions for library routines operating on directories.
  1354. XX */
  1355. XXtypedef struct _dirdesc {
  1356. XX    int    dd_fd;
  1357. XX    long    dd_loc;
  1358. XX    long    dd_size;
  1359. XX    char    dd_buf[DIRBLKSIZ];
  1360. XX} DIR;
  1361. XX#ifndef NULL
  1362. XX#define NULL 0
  1363. XX#endif
  1364. XXextern    DIR *opendir();
  1365. XXextern    struct direct *readdir();
  1366. XXextern    long telldir();
  1367. XX#ifdef void
  1368. XXextern    void seekdir();
  1369. XXextern    void closedir();
  1370. XX#endif
  1371. XX#define rewinddir(dirp)    seekdir((dirp), (long)0)
  1372. XX#endif KERNEL
  1373. X!
  1374. Xecho 'makefile':
  1375. Xsed 's/^X//' >'makefile' <<'!'
  1376. XXDIR = closedir.o opendir.o readdir.o seekdir.o telldir.o
  1377. XXCFLAGS=-O -I. -Dvoid=int
  1378. XXDEST=..
  1379. XX
  1380. XXall:    $(DIR)
  1381. XX
  1382. XXmv:    $(DIR)
  1383. XX    mv $(DIR) $(DEST)
  1384. XX
  1385. XXcpif:    dir.h
  1386. XX    cp dir.h /usr/include/ndir.h
  1387. XX
  1388. XXclean:
  1389. XX    rm -f *.o
  1390. X!
  1391. Xecho 'closedir.c':
  1392. Xsed 's/^X//' >'closedir.c' <<'!'
  1393. XXstatic char sccsid[] = "@(#)closedir.c 4.2 3/10/82";
  1394. XX
  1395. XX#include <sys/types.h>
  1396. XX#include <dir.h>
  1397. XX
  1398. XX/*
  1399. XX * close a directory.
  1400. XX */
  1401. XXvoid
  1402. XXclosedir(dirp)
  1403. XX    register DIR *dirp;
  1404. XX{
  1405. XX    close(dirp->dd_fd);
  1406. XX    dirp->dd_fd = -1;
  1407. XX    dirp->dd_loc = 0;
  1408. XX    free((char *)dirp);
  1409. XX}
  1410. X!
  1411. Xecho 'opendir.c':
  1412. Xsed 's/^X//' >'opendir.c' <<'!'
  1413. XX/* Copyright (c) 1982 Regents of the University of California */
  1414. XX
  1415. XXstatic char sccsid[] = "@(#)opendir.c 4.4 11/12/82";
  1416. XX
  1417. XX#include <sys/types.h>
  1418. XX#include <sys/stat.h>
  1419. XX#include <dir.h>
  1420. XX
  1421. XX/*
  1422. XX * open a directory.
  1423. XX */
  1424. XXDIR *
  1425. XXopendir(name)
  1426. XX    char *name;
  1427. XX{
  1428. XX    register DIR *dirp;
  1429. XX    register int fd;
  1430. XX    struct stat statbuf;
  1431. XX    char *malloc();
  1432. XX
  1433. XX    if ((fd = open(name, 0)) == -1)
  1434. XX        return NULL;
  1435. XX    if (fstat(fd, &statbuf) == -1 || !(statbuf.st_mode & S_IFDIR)) {
  1436. XX        close(fd);
  1437. XX        return NULL;
  1438. XX    }
  1439. XX    if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
  1440. XX        close (fd);
  1441. XX        return NULL;
  1442. XX    }
  1443. XX    dirp->dd_fd = fd;
  1444. XX    dirp->dd_loc = 0;
  1445. XX    dirp->dd_size = 0;    /* so that telldir will work before readdir */
  1446. XX    return dirp;
  1447. XX}
  1448. X!
  1449. Xecho 'readdir.c':
  1450. Xsed 's/^X//' >'readdir.c' <<'!'
  1451. XX/* Copyright (c) 1982 Regents of the University of California */
  1452. XX
  1453. XXstatic char sccsid[] = "@(#)readdir.c 4.3 8/8/82";
  1454. XX
  1455. XX#include <sys/types.h>
  1456. XX#include <dir.h>
  1457. XX
  1458. XX/*
  1459. XX * read an old stlye directory entry and present it as a new one
  1460. XX */
  1461. XX#define    ODIRSIZ    14
  1462. XX
  1463. XXstruct    olddirect {
  1464. XX    ino_t    od_ino;
  1465. XX    char    od_name[ODIRSIZ];
  1466. XX};
  1467. XX
  1468. XX/*
  1469. XX * get next entry in a directory.
  1470. XX */
  1471. XXstruct direct *
  1472. XXreaddir(dirp)
  1473. XX    register DIR *dirp;
  1474. XX{
  1475. XX    register struct olddirect *dp;
  1476. XX    static struct direct dir;
  1477. XX
  1478. XX    for (;;) {
  1479. XX        if (dirp->dd_loc == 0) {
  1480. XX            dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 
  1481. XX                DIRBLKSIZ);
  1482. XX            if (dirp->dd_size <= 0) {
  1483. XX                dirp->dd_size = 0;
  1484. XX                return NULL;
  1485. XX            }
  1486. XX        }
  1487. XX        if (dirp->dd_loc >= dirp->dd_size) {
  1488. XX            dirp->dd_loc = 0;
  1489. XX            continue;
  1490. XX        }
  1491. XX        dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc);
  1492. XX        dirp->dd_loc += sizeof(struct olddirect);
  1493. XX        if (dp->od_ino == 0)
  1494. XX            continue;
  1495. XX        dir.d_ino = dp->od_ino;
  1496. XX        strncpy(dir.d_name, dp->od_name, ODIRSIZ);
  1497. XX        dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */
  1498. XX        dir.d_namlen = strlen(dir.d_name);
  1499. XX        dir.d_reclen = DIRBLKSIZ;
  1500. XX        return (&dir);
  1501. XX    }
  1502. XX}
  1503. X!
  1504. Xecho 'seekdir.c':
  1505. Xsed 's/^X//' >'seekdir.c' <<'!'
  1506. XXstatic char sccsid[] = "@(#)seekdir.c 4.9 3/25/83";
  1507. XX
  1508. XX#include <sys/param.h>
  1509. XX#include <dir.h>
  1510. XX
  1511. XX/*
  1512. XX * seek to an entry in a directory.
  1513. XX * Only values returned by "telldir" should be passed to seekdir.
  1514. XX */
  1515. XXvoid
  1516. XXseekdir(dirp, loc)
  1517. XX    register DIR *dirp;
  1518. XX    long loc;
  1519. XX{
  1520. XX    long curloc, base, offset;
  1521. XX    struct direct *dp;
  1522. XX    extern long lseek();
  1523. XX
  1524. XX    curloc = telldir(dirp);
  1525. XX    if (loc == curloc)
  1526. XX        return;
  1527. XX    base = loc & ~(DIRBLKSIZ - 1);
  1528. XX    offset = loc & (DIRBLKSIZ - 1);
  1529. XX    (void) lseek(dirp->dd_fd, base, 0);
  1530. XX    dirp->dd_size = 0;
  1531. XX    dirp->dd_loc = 0;
  1532. XX    while (dirp->dd_loc < offset) {
  1533. XX        dp = readdir(dirp);
  1534. XX        if (dp == NULL)
  1535. XX            return;
  1536. XX    }
  1537. XX}
  1538. X!
  1539. Xecho 'telldir.c':
  1540. Xsed 's/^X//' >'telldir.c' <<'!'
  1541. XXstatic char sccsid[] = "@(#)telldir.c 4.1 2/21/82";
  1542. XX
  1543. XX#include <sys/types.h>
  1544. XX#include <dir.h>
  1545. XX
  1546. XX/*
  1547. XX * return a pointer into a directory
  1548. XX */
  1549. XXlong
  1550. XXtelldir(dirp)
  1551. XX    DIR *dirp;
  1552. XX{
  1553. XX    long lseek();
  1554. XX
  1555. XX    return (lseek(dirp->dd_fd, 0L, 1) - dirp->dd_size + dirp->dd_loc);
  1556. XX}
  1557. X!
  1558. Xecho done
  1559. !
  1560. echo 'contrib/README':
  1561. sed 's/^X//' >'contrib/README' <<'!'
  1562. XThis directory contains some software from others that might be of use
  1563. Xin getting C News running in an unusual environment.
  1564. X
  1565. XWE MAKE ABSOLUTELY NO GUARANTEES ABOUT QUALITY OR USABILITY.  EVERYTHING
  1566. XHERE IS SUPPLIED "AS IS".  SOMETIMES WE HAVEN'T EVEN TESTED IT.
  1567. !
  1568. echo 'contrib/nntpmail/README':
  1569. sed 's/^X//' >'contrib/nntpmail/README' <<'!'
  1570. XThis directory contains.
  1571. X
  1572. Xmailing_lists        support for moderating, redistributing and
  1573. X            gatewaying mailing lists into newsgroups/vice-versa.
  1574. Xmail_to_group        support for being able to "mail comp.unix.wizards"
  1575. Xnntp_support        support for posting articles remotely using
  1576. X            NNTP.
  1577. Xpost_via_mail        support for posting articles remotely by mailing
  1578. X            them there. Poor man's NNTP.
  1579. !
  1580. echo 'contrib/nntpmail/post_via_mail/README':
  1581. sed 's/^X//' >'contrib/nntpmail/post_via_mail/README' <<'!'
  1582. XThis directory contains C news support for posting news to a remote
  1583. Xserver by mailing the article to a special alias.
  1584. X
  1585. Xfrontend_inews    parse options, masquerades news headers so they can
  1586. X        go through mail, mail the article to the remote
  1587. X        alias.  Install as $NEWSLIB/inews
  1588. X
  1589. Xserver_inews    The special alias on the news server should invke this
  1590. X        e.g.
  1591. X        feednews: "|/usr/lib/newsbin/server_inews"
  1592. X
  1593. X        Make sure the nntp server invokes server_inews and
  1594. X        not fake_inews (instant infinite loop!).
  1595. X
  1596. X        You can find this file in ../nntp_support
  1597. X
  1598. Xusenet        a version of ../mail_to_newsgroup/usenet that works
  1599. X        by remailing the article.
  1600. !
  1601. echo 'contrib/nntpmail/post_via_mail/frontend_inews':
  1602. sed 's/^X//' >'contrib/nntpmail/post_via_mail/frontend_inews' <<'!'
  1603. X#! /bin/sh
  1604. X# inews [-p] [-d k] [-x site] [-hMD] [-t subj] [-n ng] [-e exp] [-F ref] \
  1605. X#  [-d dist] [-a mod] [-f from] [-o org] [-C ng] [file...] - inject news:
  1606. X#
  1607. X#     pseudo inews that supports the use of a central posting server accessed
  1608. X#     via mail.  This provides less opportunities to inject fake messages, and
  1609. X#     relies on mail to do fancy things like hiding names of workstations and
  1610. X#     providing full-name return addresses.
  1611. X#
  1612. X# Jean-Francois Lamy (lamy@ai.toronto.edu) 88-02-11
  1613. X
  1614. X#NEWSCTL=${NEWSCTL-/usr/lib/news}
  1615. X#NEWSBIN=${NEWSBIN-/usr/lib/newsbin}
  1616. X#NEWSARTS=${NEWSARTS-/usr/spool/news}
  1617. XNEWSCTL=/local/share/news
  1618. XNEWSBIN=/local/lib/news
  1619. XNEWSARTS=/var/spool/news
  1620. XPATH=$NEWSBIN:$NEWSCTL:$NEWSBIN/relay:/bin:/usr/bin:/usr/ucb; export PATH
  1621. X
  1622. Xallowed=sandra\|rayan\|lamy        # tailor: local news admin (may be "")
  1623. Xhdrspresent=no
  1624. X
  1625. Xwhoami=/tmp/in$$who        # just created to determine effective uid
  1626. Xinput=/tmp/in$$in        # uncensored input
  1627. Xcensart=/tmp/in$$cens        # censored input
  1628. Xrmlist="$input $censart"
  1629. Xegrep=egrep
  1630. X
  1631. X# figure out where the remote server is.  We mail even if we are on the
  1632. X# server, in order to garantee proper return addresses
  1633. X   servaddr=feednews@news-server.csri.toronto.edu
  1634. X
  1635. Xumask 2
  1636. Xtrap '' 1 2 15            # ignore signals to avoid losing articles
  1637. X
  1638. X# "inews -p": invoke rnews
  1639. Xcase "$1" in
  1640. X-p)
  1641. X    shift
  1642. X    exec rnews $*        # rnews, bailing out at or near line 1
  1643. X    ;;
  1644. Xesac
  1645. X
  1646. X# parse arguments for options, cat headers onto $input; cat files onto $input
  1647. X>$input
  1648. Xwhile :
  1649. Xdo
  1650. X    case $# in
  1651. X    0)    break ;;        # arguments exhausted
  1652. X    esac
  1653. X
  1654. X    case "$1" in
  1655. X    -debug)    shift; debug="$1" ;;        # peculiar to C news
  1656. X    -x)    shift; exclusion="-x $1" ;;    # you're welcome, erik (2.11)
  1657. X    -h)    hdrspresent=yes ;;
  1658. X    -M)    # TODO: what's this *really* do? dunno, find out
  1659. X        ;;
  1660. X    -D)    # obsolete, undocumented: meant "don't check for recordings".
  1661. X        # last present in B 2.10.1, invoked by readnews for followups.
  1662. X        ;;
  1663. X    -t)    shift; echo "Subject: $1" >>$input ;;
  1664. X    -n)    shift; echo "Newsgroups: $1" >>$input ;;
  1665. X    -e)    shift; echo "Expires: $1" >>$input ;;
  1666. X    -F)    # undocumented in B 2.10.1, documented in B 2.11.
  1667. X        shift; echo "References: $1" >>$input ;;
  1668. X    -d)    shift; echo "Distribution: $1" >>$input ;;
  1669. X    -a)    shift; echo "Approved: $1" >>$input ;;
  1670. X
  1671. X    # pass next options as environment variables to client.censor
  1672. X
  1673. X    -f)    shift; PASSEDFROM="$1" ;;    # complex due to Sender:
  1674. X    -o)    shift; ORGANIZATION="$1"; export ORGANIZATION ;;
  1675. X
  1676. X    -[cC])
  1677. X        # megakludge-o-rama
  1678. X        # first, permit only to super-users
  1679. X        >$whoami
  1680. X        whoever = "`ls -l $whoami | awk '{print $3}'`"
  1681. X        case $whoever in
  1682. X        root|$allowed)    : a winner ;;
  1683. X        *)
  1684. X            echo "$0: $1 restricted to super-users " >&2
  1685. X            exit 1
  1686. X            ;;
  1687. X        esac
  1688. X        rm -f $whoami
  1689. X        case "$1" in
  1690. X        -C)    cat <<! >>$input        # generate -C header
  1691. XNewsgroups: $ng
  1692. XSubject: newgroup $2
  1693. XControl: newgroup $2
  1694. XApproved: $whoever@`hostname`.`domainname`
  1695. X
  1696. Xcreated by inews -C
  1697. X!             
  1698. X            shift
  1699. X            ;;
  1700. X        -c)    cat <<! >>$input        # generate -c header
  1701. XNewsgroups: $ng
  1702. XSubject: $2
  1703. XControl: $2
  1704. XApproved: $whoever@`hostname`.`domainname`
  1705. X
  1706. Xcreated by inews -c.
  1707. X!
  1708. X            shift
  1709. X            ;;
  1710. X        esac
  1711. X        ;;
  1712. X    -*)
  1713. X        echo "$0: bad option $1" >&2
  1714. X        exit 1
  1715. X        ;;
  1716. X    *)
  1717. X        case "$hdrspresent" in
  1718. X        no)    echo "" >>$input; hdrspresent=yes ;;
  1719. X        esac
  1720. X        cat "$1" >>$input        # is a filename; append file
  1721. X        fileseen=yes
  1722. X        ;;
  1723. X    esac
  1724. X    shift        # pass option or filename (any value was done above)
  1725. Xdone
  1726. X
  1727. X# if no files named, read stdin
  1728. Xcase "$fileseen" in
  1729. Xyes)    ;;
  1730. X*)
  1731. X    case "$hdrspresent" in
  1732. X    no)    echo "" >>$input; hdrspresent=yes ;;
  1733. X    esac
  1734. X    # capture incoming news in case inews fails
  1735. X    if cat >>$input; then
  1736. X        : far out
  1737. X    else
  1738. X        echo "$0: lost news; cat returned status $?" >&2
  1739. X        exit 1
  1740. X    fi
  1741. X    ;;
  1742. Xesac
  1743. X
  1744. X(
  1745. X# trivial censoring, before passing on to mailer.
  1746. XORGANIZATION=${ORGANIZATION=`cat ${NEWSCTL}/organi?ation`}
  1747. Xawk "BEGIN        { subject = 0; body = 0; skipping = 0 ;
  1748. X              newsgroups = 0; distribution = 0; organization = 0;
  1749. X              print \"To: $servaddr\" }
  1750. Xbody == 1        { print; next }
  1751. X/[A-Za-z-]*:[ ]*$/    { next }
  1752. X/^$|^[ ][ \t]*$/        { if (!body) {
  1753. X                if (!organization) 
  1754. X                   print \"Organization: $ORGANIZATION\";
  1755. X                if (!newsgroups) print \"Newsgroups: $groups\";
  1756. X                if (!subject) print \"Subject: (none)\"; 
  1757. X              }
  1758. X              print; body = 1; next
  1759. X            }
  1760. X/^Organization:/    { organization = 1; skipping = 0; print; next }
  1761. X/^Newsgroups:/        { newsgroups = 1; skipping = 0; print; next }
  1762. X/^Distribution:/    { distribution = 1; skipping = 0; print; next }
  1763. X/^Subject:/        { subject = 1; skipping = 0; print; next }
  1764. X/^To:|^Cc:|^X-To:/    { skipping = 1; next }
  1765. X/^From |^Return-Path:/    { skipping = 1; next }
  1766. X/^Apparently-To:/    { skipping = 1; next }
  1767. X/^[     ]/        { if (skipping) next }
  1768. X            { print }
  1769. X" <$input >$censart
  1770. Xif test -r $HOME/.signature; then
  1771. X   echo "-- " >>$censart
  1772. X   sed 5q $HOME/.signature >>$censart    # glue on first bit of signature
  1773. Xfi
  1774. X
  1775. Xif /usr/lib/sendmail -t ${PASSEDFROM+-f"$PASSEDFROM"} <$censart
  1776. Xthen
  1777. X    rm -f $rmlist        # far out, it worked
  1778. X    exit 0
  1779. Xelse
  1780. X    status=$?
  1781. X    echo\
  1782. X"$0: could not send article to server; sendmail returned status $status" >&2
  1783. X    echo "$0: processed news article can be found in $input" >&2
  1784. X    exit $status
  1785. Xfi
  1786. X) &
  1787. !
  1788. echo 'contrib/nntpmail/post_via_mail/usenet':
  1789. sed 's/^X//' >'contrib/nntpmail/post_via_mail/usenet' <<'!'
  1790. X#!/bin/sh
  1791. X#
  1792. X# post.news
  1793. X#
  1794. X# meant to be invoked as a sendmail-compatible mailer from zmailer.  Arguments
  1795. X# are the newsgroups to which the article should be posted. A complete
  1796. X# message, including To:, From: and From_ line expected on stdin.
  1797. X# 
  1798. X# To use this script as a transport agent, add the following to scheduler.cntl:
  1799. X#    usenet/*    1m    10 0 0    root    daemon    sm -c $channel news
  1800. X# The definition of the news transport agent in sm.cf should contain
  1801. X#    news    m    /usr/lib/zmail/post.news    post.news $u
  1802. X# (adjust this to reflect the actual location of the installed copy of this
  1803. X# script, of course)
  1804. X#
  1805. X# Jean-Francois Lamy (lamy@ai.toronto.edu), 88-02-13
  1806. X# based on code by Rayan Zachariassen.
  1807. X
  1808. X# Notes:
  1809. X# - The news program invoked by this script should trust From: lines
  1810. X#   (otherwise workstation name hiding, full-name id generation and
  1811. X#   all other smarts done by router.cf will be lost)
  1812. X# - router.cf checks local parts with embedded dots for membership in the
  1813. X#   active newsgroups file and routes them through this transport agent. One
  1814. X#   word newsgroup names are not tested in that fashion, because of the risk
  1815. X#   of obscure clashes with user-ids.  Explicit aliases of the form
  1816. X#      gradnews: gradnews@localnews
  1817. X#   should be used for those (such names are not a good idea to start with).
  1818. X#   If such aliases are used, add a line in hosts.transports that reads
  1819. X#      localnews usenet!
  1820. X#   This tells the router that mail to fake host localnews is to be sent to the
  1821. X#   local host (there is nothing after the !) on channel usenet. 
  1822. X
  1823. X# this version forwards the article via mail to a server that will trust
  1824. X# the return address.
  1825. Xserver="feednews@news-server.csri.toronto.edu"
  1826. X
  1827. Xcase x$DISTRIBUTE in
  1828. Xx)    org="`cat /local/share/news/organi?ation`"
  1829. X    [ "$org" ] || org = "Department of Computer Science, University of Toronto"
  1830. X    orgflag=1
  1831. X    ;;
  1832. X*)    orgflag=0
  1833. X    ;;
  1834. Xesac
  1835. Xfrom=/tmp/from$$
  1836. X
  1837. Xfor i in $@
  1838. Xdo
  1839. X    groups="${groups+$groups,}$i"
  1840. Xdone
  1841. X
  1842. Xawk "BEGIN        { subject = 0; body = 0; skipping = 0 ;
  1843. X              newsgroups = 0; distribution = 0;
  1844. X              organization = $orgflag;
  1845. X              print \"To: $server\" }
  1846. Xbody == 1        { print; next }
  1847. X/^$|^[ ][ \\t]*$/    { if (!body) {
  1848. X                np = split(path,parts,\"!\");
  1849. X                if (!organization && np == 1)
  1850. X                    print \"Organization: $org\";
  1851. X                if (!newsgroups) print \"Newsgroups: $groups\";
  1852. X                if (!subject) print \"Subject: (none)\"; 
  1853. X              }
  1854. X              print; body = 1; next
  1855. X            }
  1856. X/^To:|^X-To:|^Cc:|^Apparently-To:/    { skipping=1 ; next }
  1857. X/^Newsgroups:/        { newsgroups = 1; skipping = 0; printf(\"%s\",\$0);
  1858. X              if (\"$groups\" != \"\")
  1859. X                 printf(\",%s\\n\",\"$groups\");
  1860. X              else printf(\"\\n\");
  1861. X              next }
  1862. X/^Distribution:/    { distribution = 1; skipping = 0; print; next }
  1863. X/^Subject:/        { subject = 1; skipping = 0; print; next }
  1864. X/^From |^Return-Path:/    { print \$2 > from ; path = \$2 ; skipping = 1; next }
  1865. X/^[     ]/        { if (skipping) next }
  1866. X/^[A-Za-z-]*:[ \\t]*$/    { if (!body) next }
  1867. X            { print }
  1868. X" from="$from" - >/tmp/bug$$
  1869. X
  1870. Xif [ -s $from ]; then
  1871. X    /usr/lib/sendmail -f"`cat $from`" </tmp/bug$$
  1872. Xfi
  1873. Xrm $from /tmp/bug$$
  1874. Xexit 0
  1875. !
  1876. echo 'contrib/nntpmail/mailing_lists/README':
  1877. sed 's/^X//' >'contrib/nntpmail/mailing_lists/README' <<'!'
  1878. XMANAGING AND REDISTRIBUTING MAILING LISTS
  1879. X
  1880. XThe tools described below allow you to set up a mailing list that is
  1881. X- archived in a single file if you wish
  1882. X- archived in one file per volume/issue if you wish
  1883. X- gatewayed to a newsgroup (bi-directionally if you wish)
  1884. X- well-behaved (the bounces go back to the owner, not to the whole list)
  1885. X- protected from unauthorized perusal if you wish.
  1886. X
  1887. XThis requires something like the following aliases to be set-up.
  1888. X
  1889. X    example: "|/local/lib/mail/bin/moderate example-owner example-people",
  1890. X        "|/local/lib/mail/bin/distribute -a example -n list.example"
  1891. X    example-request: lamy
  1892. X    example-owner: lamy
  1893. X    example-people:    ":include:/local/share/mail/lists/example"
  1894. X
  1895. XFor bi-directional gatewaying you need to edit the sys file on the news
  1896. Xserver:
  1897. X
  1898. X    list.example:list.example/all::/news/bin/mailgateway example@ai.toronto.edu
  1899. X
  1900. XThe tools used are as follows:
  1901. X
  1902. Xa) redistributing a mailing list
  1903. X
  1904. Xmoderate:     used for setting up mail aliases so that bounces don't pester
  1905. X          the whole membership.  Typically the members of the list will
  1906. X          be another alias that invokes "distribute" (below) so that
  1907. X          the contents get archived or/and fed to newsgroups.
  1908. X
  1909. Xb) gatewaying mailing lists to newsgroups, archival
  1910. X
  1911. Xdistribute:   takes a message, forwards it to mail recipients, gateways
  1912. X          into newsgroups, and archives the articles either one article
  1913. X          per file or mailbox style.
  1914. X
  1915. Xappendfile:   setuid append program; required so that sensitive lists can
  1916. X          be protected.
  1917. X
  1918. X
  1919. Xc) gatewaying of newsgroups into mailing lists (bidirectionally as well).
  1920. X
  1921. Xmailgateway:  Used on the news server, and invoked from the sys file, this
  1922. X          script allows notification of people who can't/won't read news.
  1923. X          Messages posted to a newsgroup are fed to a mailing list, except
  1924. X          if the message appears to have come from the mailing list in the
  1925. X          first place.  This is detected by looking for the Approved:
  1926. X          header "distribute" tacks on.  News control messages are
  1927. X          weeded out.
  1928. !
  1929. echo 'contrib/nntpmail/mailing_lists/appendfile/Makefile':
  1930. sed 's/^X//' >'contrib/nntpmail/mailing_lists/appendfile/Makefile' <<'!'
  1931. XNAME=appendfile
  1932. XDESTDIR=/ai/lib/mail/bin
  1933. XMANEXT=1
  1934. XMANDIR=/ai/man/man$(MANEXT)
  1935. XCFLAGS=-O
  1936. X
  1937. Xall: $(NAME)
  1938. X$(NAME): $(NAME).c
  1939. X    cc $(CFLAGS) $(NAME).c -o $(NAME)
  1940. X
  1941. Xinstall: all
  1942. X    install -s -m 755 $(NAME) $(DESTDIR)
  1943. X#    install -c -m a=r $(NAME).man $(MANDIR)/$(NAME).$(MANEXT)
  1944. X
  1945. Xclean:
  1946. X    rm -f *.o $(NAME) \#* *~
  1947. !
  1948. echo 'contrib/nntpmail/mailing_lists/appendfile/appendfile.c':
  1949. sed 's/^X//' >'contrib/nntpmail/mailing_lists/appendfile/appendfile.c' <<'!'
  1950. X#define BUFSIZ    1024
  1951. X#include <sys/file.h>
  1952. X
  1953. Xmain(argc,argv)
  1954. Xint    argc;
  1955. Xchar    **argv;
  1956. X{
  1957. X    char    *ofile, buf[BUFSIZ];
  1958. X    int    fd, n, p, neednl;
  1959. X
  1960. X    argc--, argv++;
  1961. X    neednl = 0;
  1962. X    p = 1;
  1963. X    if (**argv == '-') {
  1964. X        if ((fd = open(argv[0]+1,O_WRONLY|O_APPEND|O_CREAT,0644)) < 0
  1965. X            || dup2(fd, 1) < 0) {
  1966. X            perror(argv[0]+1);
  1967. X            exit(1);
  1968. X        }
  1969. X        argc--, argv++;
  1970. X    }
  1971. X    while (argc--) {
  1972. X        if ((fd = open(*argv, 0)) < 0) {
  1973. X            perror(*argv++);
  1974. X            continue;
  1975. X        }
  1976. X        argv++;
  1977. X        if (neednl)
  1978. X            write(1, "\n", 1);
  1979. X        while ((n = read(fd, buf, BUFSIZ)) > 0) {
  1980. X            write(1, buf, n);
  1981. X            if (n == 1)
  1982. X                neednl = !(buf[0] == '\n' && buf[p-1] == '\n');
  1983. X            else
  1984. X                neednl = !(buf[n-1] == '\n' && buf[n-2]=='\n');
  1985. X            p = n;
  1986. X        }
  1987. X        close(fd);
  1988. X    }
  1989. X    if (neednl)
  1990. X        write(1, "\n", 1);
  1991. X    exit(0);
  1992. X}
  1993. !
  1994. echo done
  1995.  
  1996.  
  1997.