home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume1 / vnews / part4 < prev    next >
Internet Message Format  |  1986-11-30  |  50KB

  1. From: decvax!vax135!hou3c!ka
  2. Return-Path: <decvax!vax135!hou3c!ka>
  3. Date: Mon, 21 Jan 85 22:09:00 est
  4. Newsgroups: mod.sources
  5. Subject: Vnews part 4
  6.  
  7. # Welcome to vnews release 2.11-B 1/17/85.
  8. # This is part 4 out of 7.
  9. # Feed me into sh (NOT csh).
  10.  
  11. if test ! -d lib
  12. then    mkdir lib
  13. fi
  14.  
  15. if test ! -d postnews
  16. then    mkdir postnews
  17. fi
  18.  
  19. cat > lib/routines.doc <<\!E!O!F!
  20. ..  Run this file through nroff (no macro packages needed)
  21. ..  To get page boundaries, pipe the output of nroff though pr.
  22. .hy
  23. .na
  24. .ll 72
  25. .de p
  26. .sp
  27. ..
  28. .de h
  29. .in 0
  30. .sp 2
  31. .ne 4
  32. .nr h +1
  33. \\nh)\ \ \\$1
  34. .p
  35. ..
  36. .de i
  37. .in +4
  38. .fi
  39. ..
  40. .de o
  41. .sp
  42. .in -4
  43. .nf
  44. ..
  45. .h "INTRODUCTION"
  46. This file describes the contents of the lib directory.
  47. .p
  48. The rlib library is intended to simplify the task of writing
  49. news reading programs.  Previously, there was no specific support
  50. for writing news reading programs, and in order to take advantage
  51. of existing software, programmers had to dig the routines out of the
  52. netnews software themselves.  This library attempt collects a
  53. number of routines, in some cases modified to make them more general
  54. or to simplify the caller interface, into a central location where
  55. all users can share them.  It is hoped that this library will unlimately
  56. evolve into a collection of routines used not just by the news
  57. reading software but by all the netnews software.
  58. .p
  59. There are certain limitations to this library.  Because this code
  60. was designed and selected for its usefulness for use with vnews,
  61. it may not always do things in ways appropriate for other programs.
  62. On the other hand, certain functions that might be useful were
  63. not included because they had too much vnews specific code in them.
  64. In particular, writers of news reading programs will probably want
  65. to copy the article selection routines out of vnews/artseq.c and
  66. modify them to work for their particular application.  This does
  67. not attempt to provide complete documentation on all the routines;
  68. so you may have to consult the code for details.
  69. .p
  70. .h "BASIC INFORMATION"
  71. The library source resides in a directory called
  72. "lib".  In general, you should set
  73. .br
  74.     LIB = ../lib
  75. .br
  76. in your makefiles.  That way, your makefiles will run unchanged if
  77. they are placed in a directory parallel to the lib directory.
  78. You should compile your programs with -I$(LIB) so that they can
  79. access header files in lib, and link with $(LIB)/rpathinit.o and
  80. $(LIB)/rlib.a.  The file rpathinit.o contains the pathinit routine;
  81. and rlib.a is an archive containing all the rest of the routines.
  82. .p
  83. To use many of these routines you must provide an error exit routine
  84. called xerror; a typical version is:
  85. .nf
  86.     xerror(msg, a1, a2, a3, a4)  char *msg; {
  87.         printf(msg, a1, a2, a3, a4);
  88.         putchar('\\n');
  89.         exit(2);
  90.     }
  91.  
  92. .fi
  93. There is a global variable called bfr which is a character array
  94. of LBUFLEN (currently 1024) bytes.  Various routines in the library
  95. use this for scratch space; you can use it as well.  Be careful not to
  96. rely on the value of bfr if you call another routine that might modify
  97. it.
  98. The following library routines are guarenteed not to use bfr:  afree,
  99. ainit, bcopy, bzero, ckmalloc, clrunread, findgroup, getaddr, getopt,
  100. g_num, hfgets, hfree, hinit, inunread, launder, lcase, makehimask,
  101. nextgrp, ngmatch, nstrip, prefix, prevgrp, rename, replyname, rmnf,
  102. savestr, scopyn, setunread, and titmat.
  103. For convenience, a declaration of bfr appears in libextern.h.
  104. .h "HEADER FILES"
  105. This section lists the various header files.  In some cases, you
  106. will have to see the descriptions of the routines that use the
  107. files for more details.
  108. .i
  109. .o
  110. artfile.h
  111. .i
  112. This include defines for accessing the artfile.
  113. .o
  114. arthead.h
  115. .i
  116. This header file defines the arthead structure used to hold
  117. and in-core copy of an article header.
  118. .o
  119. config.h
  120. .i
  121. This file specifies the version of UNIX you are running under.
  122. (UNIX is a trademark of AT&T Bell Laboratories.)  It defines
  123. index and rindex to be strchr and strrchr, if necessary.
  124. It also defines BSDREL and USGREL.  The values of these for various
  125. versions of UNIX are:
  126. .nf
  127.     VERSION        USGREL    BSDREL
  128.     Version 6    6    6
  129.     System III    30    6
  130.     System V    50    6
  131.     System V rel 2    52    6
  132.     Version 7    6    7
  133.     4.1 BSD        6    41
  134.     4.2 BSD        6    42
  135. .fi
  136. .o
  137. defs.h
  138. .i
  139. This file includes lots of news related defines.  It includes the file
  140. newsdefs.h, which is generated by the setup program, and also has a
  141. few defines of it's own.
  142. Some of the useful defines are:
  143. .nf
  144.     Name    Default      Description
  145.     MAXGROUPS    300      The maximum number of newsgroups
  146.     BUFLEN    128/256      The size of a general purpose char array
  147.     LBUFLEN    1024      The size of a big buffer
  148.     DATELEN    48      The maximum size of a date
  149.     FPATHLEN    64      The maximum length of a file name
  150.     NAMELEN    64      The maximum size of a message ID or address
  151.     PATHLEN    512      The maximum size of a Path: entry
  152. .fi
  153. .o
  154. libextern.h
  155. .i
  156. Declares various global variables defined in the library.  Bfr is
  157. declared here, as are the various variables set up by pathinit and
  158. getuser.
  159. .o
  160. newsrc.h
  161. .i
  162. Defines for the .newsrc accessing routines.
  163. .o
  164. ng.h
  165. .i
  166. Defines for accessing the newgroups file.
  167. .o
  168. roptions.h
  169. .i
  170. Defines for the roptions routine.
  171. .o
  172. stroff.h
  173. .i
  174. This defines one macro called stroff(element, structure).  It returns
  175. the offset of the specified element into the given structure.
  176. .in -4
  177. .p
  178. The rest of this file details the various routines available.
  179. .h PATHS
  180. To avoid the necessity of hard coding paths, machine names, and so forth
  181. in your program, these routines are provided.  Declarations for all the
  182. variables set by these routines appear in libextern.h.
  183. .i
  184. .o
  185. pathinit()
  186. .i
  187. This routine fills in the following character arrays:
  188. .nf
  189. .in +4
  190. SPOOL:  The netnews spool directory.
  191. LIB:  /usr/lib/news or equivelant.
  192. FULLSYSNAME:  System name as known by neighbors.
  193. DOMAIN:  Concatenated to FULLSYSNAME to form domain name.
  194. XINEWS:  Path of inews program.
  195. MAILPARSER:  Path of sendmail or recmail program.
  196. .in -4
  197. .fi
  198. A number of other library routines assume that pathinit has been
  199. called.
  200. .o
  201. isadmin()
  202. .i
  203. Returns nonzero if user is the netnews administrator or the
  204. superuser.
  205. .o
  206. getpaths()
  207. pgetpaths()
  208. .i
  209. Sets username to the user's login name and userhome to the user's
  210. home directory.  The latter version always goes to the /etc/passwd
  211. file and thus cannot be subverted by modifying the environment.
  212. .h "NEWSGROUPS"
  213. For convenience, each newsgroups is assigned a small integer which
  214. uniquely identifies it.  These numbers will vary from machine to
  215. machine and therefore can only be used locally.  The file
  216. /usr/lib/news/groupfile maintains this mapping.  For reliability, a
  217. backup copy is kept in /usr/lib/news/groupfile.bak.
  218. .p
  219. To access this file, #include\ "ng.h" and use the following routines.
  220. .i
  221. .o
  222. gfopen()
  223. gfclose()
  224. .i
  225. These routines open and close the newsgroup file.  The routine gfopen
  226. also sets the global variable maxng to the largest newsgroup number
  227. in use.
  228. .o
  229. ALL_GROUPS(g) { statement... }    (struct ngrec g)
  230. .i
  231. This macro sets up a loop through all the newsgroups.  The entries
  232. in the ngrec structure are
  233. .nf
  234.       char  g_name[MAXNGNAME];    /* newsgroup name */
  235.       short g_num;        /* newsgroup number */
  236.       short g_flags;        /* various flags */
  237. .fi
  238. The only flag currently in use is G_MOD, which indicates a
  239. moderated or fa.all group.
  240. .h "ARTFILE"
  241. Artfile keeps track of all the
  242. articles in the system.
  243. To use these routines, #include "artfile.h".
  244. Artfile.h contains two typedefs.  An ARTNO is the number of an article
  245. within a newsgroup.  This is currently defined to be int, but will be
  246. changed to "long" when article numbers reach 32000.
  247. A DPTR is the address of an article record in artfile.  The value
  248. of a DPTR is only valid within a given program; therefore if you
  249. want to pass the identity of an article to another program, you
  250. should pass the message-ID of the article.  There is a special
  251. value DNULL used to indicate a null DPTR.
  252.  
  253. There is one artrec structure for each article on the system.
  254. The artrec structure contains the following entries of interest:
  255.       long  a_subtime;        /* when article was posted */
  256.       long  a_rectime;        /* when article was received */
  257.       long  a_exptime;        /* when article expires (0 if not specified) */
  258.       DPTR  a_parent;        /* article this is a followup to */
  259.       DPTR  a_children;        /* linked list of followups */
  260.       DPTR  a_childchain;    /* link for followup chain */
  261.       short a_flags;        /* various flags */
  262.       char  a_ngroups;        /* number of newsgroups article posted to */
  263.       struct artgroup {
  264.             short a_ngnum;    /* newsgroup number */
  265.             short a_artno;    /* article number */
  266.             DPTR  a_ngchain;    /* next article in this newsgroup */
  267.       } a_group[MAXNG];        /* list of groups article posted to */
  268.       char *a_ident;        /* message id */
  269.       char *a_title;        /* article subject line */
  270.       char *a_from;        /* author of article (real name omitted) */
  271.       char *a_file;        /* file containing article */
  272.       char  a_nkwords;        /* number of keywords on article */
  273.       char *a_kword[A_MAXKW];    /* keywords */
  274.  
  275. .fi
  276. A_flags&A_NOFILE will be true if this article does not appear in the
  277. spool directory.  Currently, this can occur if a followup is received
  278. before the original article.  In that case, a dummy entry will be made
  279. for the original article until it arrives.  Later, this may also
  280. indicate that the article has been cancelled or expired.
  281. .p
  282. Currently, keywords are not stored in artfile.  However, most of the
  283. code is in place so that this can be changed if keywords are needed.
  284. .i
  285. .o
  286. afopen()
  287. .i
  288. Open artfile.  A corresponding close routine could be written if there
  289. is a need.
  290. .o
  291. ainit(a)  struct artrec *a;
  292. afree(a)  struct artrec *a;
  293. .i
  294. Ainit initializes and artrec structure and afree frees up the storage
  295. associated with it.  Both of these routines are currently no-ops
  296. but that may change in the future.
  297. .o
  298. lookart(msgid, a)  char *msgid; struct artrec *a;
  299. .i
  300. Get the record for the article.  Returns the address of the record,
  301. or DNULL on failure.
  302. .o
  303. readrec(dp, a)  DPTR dp; struct artrec *a;
  304. .i
  305. Read an article record given its address.
  306. .o
  307. BKWD_GROUP(ngnum, artno, dp, a) { statements... }
  308. .i
  309. This macro sets up a "for" loop to fetch all the articles in the
  310. newsgroup numbered ngnum.  For each article, artno is set to the
  311. article number within the group, a is set to the article record, and
  312. dp is set to the address of the article record.  The highest
  313. numbered records are produced first.
  314. This means you will normally have to sort the articles before you
  315. display them.
  316. On the other hand, this order has the advantage that you can stop
  317. scanning the newsgroup when you reach
  318. the lowest numbered article marked unread in the .newsrc file.
  319. .h ".NEWSRC PROCESSING ROUTINES"
  320. These routines maintain an in-core copy of the .newsrc file and the
  321. the groupfile.  You should #include "newsrc.h" which defines the
  322. ngentry structure.  (There is one such structure for each group.)
  323. .i
  324. .o
  325. openrc()
  326. .i
  327. Open the .newsrc file, creating it if necessary.  A file pointer is
  328. returned.  Getuser must be called before this routine is used.
  329. .o
  330. readinrc(fp)  FILE *fp;
  331. .i
  332. Read in the .newsrc and groupfile files.  fp is the file pointer
  333. returned by openrc, or NULL in which case only the groupfile
  334. is read.  This routine should be called before any of the following
  335. routines are used.
  336. To use this routine, you must provide a routine called "wewant",
  337. which takes the name of a newsgroup, and returns true if the
  338. newsgroup should be appended to the .newsrc file.  Wewant generally
  339. tests whether the user asked for the group in the -n option.
  340. .o
  341. writeoutrc()
  342. .i
  343. Write out an updated version of the .newsrc file.  This routine
  344. is a no-op if readinrc was not called, or was called with a NULL
  345. argument
  346. .o
  347. nextgrp(ngp)  struct ngentry *ngp;
  348. .i
  349. Returns the next group in the .newsrc file, or the first group if
  350. ngp is NULL.
  351. .o
  352. prevgrp(ngp)
  353. .i
  354. Returns the previous group in the .newsrc file.
  355. .o
  356. setupgrp(ngp, max)  struct ngentry *ngp; ARTNO max;
  357. .i
  358. Make the specified group the current group.  Max is the maximum article
  359. number apprearing in the group, which will be the first article number
  360. generated by the BKWD_GROUP macro.  The global variable minartno is set
  361. to the smallest unread article and maxartno is set to max.
  362. .o
  363. isunread(artno)
  364. setunread(artno)
  365. clrunread(artno)
  366. .i
  367. These routines test, set, or clear the "unread article" indication for
  368. a given article.  The group of the article is the group specified in the
  369. last call to setupgrp.
  370. .o
  371. findgroup(name)
  372. .i
  373. Return the address of the ngentry strucure for the group.
  374. .o
  375. numtong(num)
  376. .i
  377. Takes a newsgroup number and returns the address of the ngentry
  378. for the newsgroup.  Currently this routine does not check its argument
  379. for validity.
  380. .o
  381. g_num(ngp)
  382. .i
  383. Return the number of the group.
  384. .h "ARTICLE HEADERS"
  385. The netnews code includes some routines for dealing with article
  386. headers, but they currently require about 5K to store a headers
  387. and still don't allocate enough space to store the "References:"
  388. line.  These routines use dynamicly allocated memory.
  389. To use them, #include "arthead.h".
  390. .i
  391. .o
  392. hinit(hp)  struct arthead *hp;
  393. hfree(hp)  struct arthead *hp;
  394. .i
  395. These routines initialize and free the storage associated with an
  396. arthead structure.  Hinit does not have to be called for static
  397. or global variables since they are initialize to zero automaticly.
  398. .o
  399. gethead(hp, fp)
  400. .i
  401. This routine reads in a news header.  It returns fp on success and
  402. NULL on failure.
  403. .o
  404. hxchg(hp1, hp2)
  405. .i
  406. This routine exchanges the value of two arthead structures.  There is
  407. no way to copy an arthead structure, but an exchange operation will
  408. serve for most purposes.
  409. .o
  410. hfgets(buf, buflen, fp)
  411. .i
  412. Reads a USENET header line.  This routine is like fgets except that
  413. 1) it handles continuation lines, and 2) it always reads in the
  414. entire line, even if it doesn't fit.  The part that doesn't fit is
  415. discarded.
  416. .h "DATE CONVERSION"
  417. .i
  418. .o
  419. cgtdate(datestr)
  420. .i
  421. This routine converts a date string to UNIX internal format.
  422. Because this routine is so big (a little over 10K), there
  423. is also a program called /usr/lib/news/cgtdate which invokes
  424. this routine on its argument and writes the converted value
  425. (in decimal) to the standard output.
  426. .o
  427. getadate(datestr)
  428. .i
  429. This routine converts a date in RFC 822 format to UNIX internal
  430. format.
  431. .h "MISCELLANEOUS NETNEWS ORIENTED ROUTINES"
  432. .i
  433. .o
  434. cancel(ofp, hp, notauthor)
  435. .i
  436. The article whose header has been read into hp is cancelled.  If
  437. the notauthor flag is set, the article will be cancelled locally
  438. only rather than net-wide.  Ofp is a file pointer that is used
  439. to write an error message on if the attempt to fork fails.
  440. .o
  441. dirname(group, buf)
  442. .i
  443. Generates the name of the directory containing the newsgroup
  444. in buf and returns buf.
  445. .o
  446. getaddr(name, result)  char *name;  char result[NAMELEN];
  447. .i
  448. Given the contents of a "From:" line to the right of the colon,
  449. place the machine address in "result".  (E. g.  generate "user@x"
  450. from "user@x (Real Name)".
  451. .o
  452. launder(newsgroups)
  453. .i
  454. This routine should be called when generating followups.  It does
  455. the net.general to net.followup conversion.
  456. .o
  457. makehimask(sublist, newsgroup)
  458. .i
  459. Unless the newsgroup is specificly asked for in the subscription list,
  460. append !newsgroup to the subscription list.  Used to keep people from
  461. seeing groups like control unless they really want to.
  462. .o
  463. ngmatch(nglist, sublist)  char *nglist, *sublist;
  464. .i
  465. Returns nonzero if one of the newsgroups in nglist is matched by
  466. an entry in the subscription list.  Unlike the 2.10 netnews routine
  467. or the same name, neither argument needs a trailing comma.
  468. .o
  469. replyname(hp, buf)
  470. .i
  471. Generates the name of the person to send replies to this article to.
  472. .o
  473. roptions(argv, rcfp)
  474. .i
  475. This routines does the readnews option processing.  Argv is the
  476. arguments to the program.  Rcfp is refers to the .newsrc file; it
  477. is used to read the "options " line at the top of the .newsrc file.
  478. To access the options set by roptions, #include "roptions.h".
  479. .o
  480. rmnf(s)
  481. .i
  482. Remove any trailing " - (nf)" from the string.  Returns nonzero if
  483. removed.
  484. .o
  485. titmat(titles, curtitle)
  486. .i
  487. See if curtitle contains one of the strings listed in titles.
  488. The global variable "titles" is set by the roptions routine.
  489. .o
  490. tomsgid(id)
  491. .i
  492. The argument should be a message ID or an article ID.  If it
  493. appears to be the latter, it is converted to a message ID.
  494. .h "STRING AND MEMORY UTILITY ROUTINES"
  495. The remaining routines are not very netnews specific.
  496. .i
  497. .o
  498. bcopy(from, to, n)
  499. .i
  500. Copy n bytes.
  501. .o
  502. bzero(block, n)
  503. .i
  504. Clear n bytes of memory.
  505. .o
  506. ckmalloc(nbytes)
  507. .i
  508. Invokes malloc and calles xerror if the malloc fails.  All the
  509. routines in rlib call ckmalloc instead of malloc.
  510. .o
  511. lcase(s)
  512. .i
  513. Convert the string to all lower case.
  514. .o
  515. nstrip(s)  char *s;
  516. .i
  517. Strip off trailing newlines, tabs, and spaces.  Returns nonzero if a
  518. newline was present.
  519. .o
  520. prefix(s, pfx)
  521. .i
  522. Return nonzero if pfx is a prefix of s.
  523. .o
  524. savestr(s)  char *s;
  525. .i
  526. Return a copy of s in a block of memory obtained from ckmalloc.
  527. .o
  528. scopyn(from, to, n)
  529. .i
  530. Copy a character string, truncating the string if necessary for make
  531. it fit.  "n" is the size of the destination.  Unlike strncpy, this
  532. routine always terminates the result with a nul.
  533. .o
  534. sindex(s1, s2)
  535. .i
  536. Return a pointer to the first occurance of the string s2 within s1,
  537. or NULL if not found.
  538. .o
  539. strpbrk(s1, s2)
  540. .i
  541. Return a pointer to the first character of s1 that also occurs in s2,
  542. or NULL if no such character exists.
  543. .o
  544. strspn(s1, s2)
  545. strcspn(s1, s2)
  546. .i
  547. Return the length of the longest prefix of s1 sonsisting of characters
  548. in (for strspn), or not in (for strcspn), s2.
  549. .o
  550. strtok(s1, s2)
  551. .i
  552. The System III strtok routine.
  553. .h "OTHER UTILITY ROUTINES"
  554. .i
  555. .o
  556. ckfopen(file, mode)
  557. .i
  558. Calls fopen, and invokes xerror if the fopen fails.
  559. .o
  560. opendir(name)
  561. closedir(dirp)
  562. readdir(dirp)
  563. rewinddir(dirp)
  564. .i
  565. The Berkeley directory access routines.
  566. Opendir opens a directory and returns a (DIR *) pointer, or NULL on failure.
  567. Readdir reads the next directory entry and returns a ponter to a struct direct,
  568. or NULL on eof.
  569. Closedir closes a directory.
  570. Rewinddir goes back to the beginning of a directory and clears any buffered
  571. information.
  572. .o
  573. getopt(argc, argv, optlist)
  574. .i
  575. The System III command argument parsing routine.
  576. .o
  577. rename(from, to)
  578. .i
  579. Rename a file, deleting any existing file named "to".
  580. .h SYNOPSYS
  581. This section gives an alphabetical listing of all the routines
  582. in the library:
  583. .sp
  584. .nf
  585. void addrc(ngp)  struct ngentry *ngp;
  586. void afopen()
  587. void afree(a)  struct artrec *a;
  588. void ainit(a)  struct artrec *a;
  589. void bcopy(from, to, n)  char *from, *to; int n;
  590. char bfr[LBUFLEN];
  591. void bzero(mem, n)  char *mem; int n;
  592. int  cancel(ofp, hp, notauthor)  FILE *ofp; struct arthead *hp; int notauthor;
  593. time_t cgtdate(datestr)  char *datestr;
  594. FILE *ckfopen(filename, mode)  char *filename, *mode;
  595. char *ckmalloc(nbytes)  int nbytes;
  596. void closedir(dirp)  DIR *dirp;
  597. void clrunread(artno)  ARTNO artno;
  598. char *dirname(group, buf)  char *group, *buf;
  599. struct ngentry *findgroup(name)  char *name;
  600. long getadate(datestr)  char *datestr;
  601. char *getaddr(full, mach)  char *full, mach[NAMELEN];
  602. FILE *gethead(hp, fp)  struct arthead *hp; FILE *fp;
  603. int getopt(argc, argv, optstr)  int argc; char **argv; char *optstr;
  604. void getuser();
  605. void gfclose();
  606. void gfopen();
  607. int g_num(ngp)  struct ngentry *ngp;
  608. char *hfgets(buf, buflen, fp)  char *buf; int buflen; FILE *fp;
  609. void hfree(hp)  struct arthead *hp;
  610. void hinit(hp)  struct arthead *hp;
  611. void hxchg(hp1, hp2)   struct arthead *hp1, *hp2;
  612. char *index(str, c)  char *str; char c;
  613. int isadmin();
  614. int isre(title)  char *title;
  615. int isunread(artno)  ARTNO artno;
  616. void launder(newsgroups) char *newsgroups;
  617. void lcase(str)  char *str;
  618. DPTR lookart(msgid, a)  char *msgid; struct artrec *a;
  619. void makehimask(sublist, group)  char *sublist, *group;
  620. struct ngentry *nextgrp(curgrp)  struct ngentry *curgrp;
  621. void pathinit();
  622. int ngmatch(nglist, sublist)  char *nglist, *sublist;
  623. int nstrip(str)  char *str;
  624. DIR *opendir(name)  char *name;
  625. FILE *openrc()
  626. void pgetuser()
  627. int prefix(str, pfx)  char *str, *pfx;
  628. struct ngentry *prevgrp(curgrp)  struct ngentry *curgrp;
  629. struct direct *readdir(dirp)  DIR *dirp;
  630. void readrec(dp, a)  DPTR dp; struct artrec *a;
  631. void readinrc(rcfp)  FILE *rcfp;
  632. int rename(from, to)  char *from, *to;
  633. char *replyname(hp, buf)  struct arthead *hp; char buf[PATHLEN];
  634. void rewinddir(dirp)  DIR *dirp;
  635. int rmnf(title)  char *title;
  636. void roptions(argv, rcfp)  char **argv; FILE *rcfp;
  637. char *savestr(str)  char *str;
  638. void scopyn(from, to, tosize)  char *from, *to; int tosize;
  639. void setunread(artno)  ARTNO artno;
  640. void setupgrp(ngp, max)  struct ngentry *ngp; ARTNO max;
  641. char *sindex(s1, s2)  char *s1, *s2;
  642. char *strcspn(s1, s2)  char *s1, *s2;
  643. char *strpbrk(s1, s2)  char *s1, *s2;
  644. char *strspn(s1, s2)  char *s1, *s2;
  645. char *strtok(s1, s2)  char *s1, *s2;
  646. int titmat(titles, title)  char **titles, *title;
  647. void tomsgid(id)  char *id;
  648. void writeoutrc();
  649. .fi
  650. !E!O!F!
  651.  
  652. cat > lib/setup.doc <<\!E!O!F!
  653. ..  Run this file through nroff (no macro packages needed)
  654. ..  To get page boundaries, pipe the output of nroff though pr.
  655. .hy
  656. .na
  657. .ll 72
  658. .de p
  659. .sp
  660. ..
  661. .de h
  662. .in 0
  663. .sp 2
  664. .ne 4
  665. .nr h +1
  666. \\nh)\ \ \\$1
  667. .p
  668. ..
  669. .de i
  670. \f3\\$1\f1\\$2
  671. ..
  672. .de b
  673. \f2\\$1\f1\\$2
  674. ..
  675. .de n
  676. .sp
  677. .in 0
  678. \\$1
  679. .in 4
  680. ..
  681. .ce
  682. Configuring the Netnews Software
  683. .sp 3
  684. The setup program is used to configure the netnews software.  To run it,
  685. simply type "sh setup".  The setup program reads if file called "config",
  686. which you must create, and sets up the netnews library.  The setup program
  687. attempts to provide sensible defaults, but you must never the less provide
  688. certain entries.
  689. .p
  690. Lines in the config file beginning with a "#" are considered to be comment
  691. lines and are ignored.  Other lines should consist of a parameter name
  692. followed by a value.  Certain parameters are boolean flags which should
  693. be set to "yes" or "no".  If the name of a boolean flag is given without
  694. specifying a value, the flag is set to "yes"
  695. A sample config file appears below:
  696. .sp
  697. .nf
  698.     newsusr news
  699.     newsgrp news
  700.     myorg BTL, Holmdel, NJ.
  701.     mydomain .UUCP
  702.     spool /tools/netnews/spool
  703.     notify
  704.     internet no
  705. .fi
  706. .p
  707. The first four lines are required entries which you must provide values for.
  708. .n newsusr
  709. This is the owner (user name) of
  710. .i inews .
  711. If you are a superuser, you should probably create a new user id
  712. (traditionally
  713. .b news )
  714. and use this id.
  715. If you are not a superuser, you can use your own user id.
  716. If you are able to, you should create a mail alias
  717. .b usenet
  718. and have mail to this alias forwarded to you.
  719. This will make it easier for other sites to find the right person
  720. in the presence of changing jobs and out of date or nonexistent
  721. directory pages.
  722. .n newsgrp
  723. This is the group (name) to which
  724. .i inews
  725. belongs.
  726. The same considerations as NEWSUSR apply.
  727. .n myorg
  728. This should be set to the name of your organization.
  729. Please keep the name short, because it will be printed, along with
  730. the electronic address and full name of the author of each message.
  731. 40 characters is probably a good upper bound on the length.
  732. If the city and state or country of your organization are not obvious,
  733. please try to include them.
  734. If the organization name begins with a `/', it will be taken
  735. as the name of a file.  The first line in that file will be used
  736. as the organization.
  737. This permits the same binary to be used on many different machines.
  738. A good file name would be `/usr/lib/news/organization'.
  739. For example, an organization might read ``Bell Labs, Murray Hill'',
  740. or ``U.C. Berkeley'' or ``MIT'' or
  741. ``Computer Corp. America, Cambridge, Mass''.
  742. .n mydomain
  743. When generating internet addresses, this domain will be appended
  744. to the local site name to form mailing address domains.
  745. For example, on system ucbvax with user root, if MYDOMAIN is
  746. set to ``.UUCP'', addresses generated will read ``root@ucbvax.UUCP''.
  747. If MYDOMAIN is ``.Berkeley.ARPA'', the address would be
  748. ``root@ucbvax.Berkeley.ARPA''.
  749. If your site is in more than one domain, use your primary domain.
  750. The domain always begins with a period, unless the local site name
  751. contains the domain; in this case MYDOMAIN should be the null string.
  752. .in 0
  753. .p
  754. The following entries are not required for the setup program, but
  755. the defaults used by the setup program may not work for you.
  756. .n admin
  757. This is the login name of the USENET administrator for this machine.
  758. This may be different from newsusr.  The default is the person running
  759. the setup program.
  760. .n internet
  761. If your system has a mailer that understands ARPA Internet
  762. syntax addresses (user@domain) turn this on, and replies
  763. will use the From or Reply-To headers.
  764. Otherwise, set it to no and replies will use the Path header.
  765. The default value for this parameter is "yes" because everyone
  766. was supposed to install an internet mailer back in January of
  767. 1984.
  768. .n sys
  769. This is the version of UNIX you are running under.  (UNIX is a
  770. trademark of AT&T Bell Laboratories.)  The following verions
  771. of UNIX are defined:
  772. .nf
  773.     sys3    AT&T System III
  774.     sys5    AT&T System V release 1
  775.     sys5r2    AT&T System V release 2
  776.     v7        AT&T Version 7 UNIX
  777.     4.1bsd    Berkeley release 4.1
  778.     4.2bsd    Berkeley release 4.2
  779. .fi
  780. Hopefully, this list will be expanded in the future.  For now,
  781. simply choose the one that is closest to your version.
  782. If you omit this paramter, setup will normally select the correct value.
  783. .n path
  784. This is the path search used by the setup program.  The default is
  785. the value of $PATH.
  786. .in 0
  787. .p
  788. The remaining parameters can be tuned as you see fit, but netnews
  789. should run OK if you just use the defaults.
  790. .n small
  791. True if you are running on a 16 bit machine such as a PDP-11.
  792. The default is yes if you are running on a PDP-11 under USG UNIX,
  793. and no otherwise.
  794. .n dftsub
  795. The default subscription list.  If a user does not specify any list of
  796. newsgroups, this will be used.  Popular choices are
  797. .b all
  798. and
  799. .b general,all.general .
  800. The default is
  801. .b all .
  802. .n admsub
  803. This newsgroup (or newsgroup list) will always be selected unless the
  804. user specifies a newsgroup list that doesn't include ADMSUB on the
  805. command line.  That is, as long as the user doesn't use the
  806. .b -n
  807. flag to readnews on the command line, ADMSUB will always be selected.
  808. The default is
  809. .b general,all.announce .
  810. The intent of this parameter is to have certain newsgroups which users
  811. are required to subscribe to.
  812. .n umask
  813. Mask for
  814. .i umask(2)
  815. system call.
  816. Set to something like 022 for a secure system.
  817. Unsecure systems might want 002 or 000.
  818. This mask controls the mode of news files created by the software.
  819. Insecure modes would allow people to edit the files directly.
  820. .n dftexp
  821. The default number of days after which an article will expire.
  822. 2 weeks (14 days) is the default choice.
  823. .n tmail
  824. This is the version of the Berkeley
  825. .i Mail
  826. program that has the \-T option.
  827. If left undefined, the
  828. .b -M
  829. option to
  830. .i readnews
  831. will be disabled.
  832. .n page
  833. The default program for which articles will be piped to for paging.
  834. This can be disabled or changed by the environment variable PAGER.
  835. If you have it, the Berkeley
  836. .i more
  837. command should be used, since the + option allows the headers to
  838. be skipped.
  839. If not specified, setup will look around your system in an attempt
  840. to find a suitable program.
  841. .n dfteditor
  842. This is the full path name of the default editor to use during
  843. followups and replies.
  844. It should be set to the most popular text editor on your system.
  845. As distributed,
  846. .b vi
  847. is used.
  848. .n sendmail
  849. This is the name of a sendmail program that understands the
  850. .b -t
  851. option.
  852. .n mailer
  853. This is the name of the mail program that recmail will invoke.
  854. Unless you specify "internet no", this must be a mail program
  855. that understand internet addresses.  The default is mail.
  856. .n home
  857. Some sites will want to run the same version of the object
  858. code on multiple computers.  If home is defined, then the
  859. directories lib and spool are assumed to be relative to the
  860. login directory of the user home.
  861. .n compadmin
  862. Normally, the numeric user id of the netnews administrator
  863. (specified by admin) is compiled into the netnews programs.
  864. If compadmin is set to "yes", then the individual netnews
  865. program will search the password file to know the numeric user id
  866. of the netnews administrator.
  867. .n myname
  868. The name of your machine.  If you don't specify this, the netnews
  869. programs will determine your system name either by using the
  870. uname or gethostname system calls or by scanning /usr/include/whoami.h.
  871. .n uname
  872. Set this if the uname system call is available locally,
  873. even though you are not a USG system.
  874. This defaults to "yes" if you are on a USG system.
  875. .n ghname
  876. Define this if the 4.2BSD gethostname system call is available.
  877. This defaults to "yes" if you are running 4.2 BSD.
  878. .n v7mail
  879. Define this if your system uses V7 mail conventions.
  880. The V7 mail convention is that a mailbox contains several messages
  881. concatenated, each message beginning with a line reading
  882. ``From user date'' and ending in a blank line.
  883. If this is defined, articles saved will have these lines added
  884. so that mail can be used to look at saved news.
  885. .n spool
  886. This directory contains subdirectories in which
  887. news articles will be stored.
  888. It is normally /usr/spool/news.
  889. .PP
  890. Briefly, for each newsgroup (say
  891. .b net.general )
  892. there will be a subdirectory /usr/spool/news/net/general
  893. containing articles, whose filenames are sequential numbers, e.g.
  894. /usr/spool/news/net/general/1, etc.
  895. .PP
  896. Each article file is in a mail-compatible format.
  897. It begins with a number of header lines,
  898. followed by a blank line, followed by the body of the article.
  899. The format has deliberately been chosen to be compatible with the
  900. ARPANET standard for mail documented in RFC 822.
  901. .PP
  902. You should place news in an area of the disk with enough free space
  903. to hold news you intend to keep on line.
  904. The total volume of news in net.all currently runs about 3MB/week.
  905. If you expirenews after the default 2 weeks, you will need about 6MB
  906. of disk space (plus some extra as a safety margin and to allow for
  907. increased traffic in the future.)
  908. If you only receive some of the newsgroups, or expire news after
  909. a different interval, these figures can be adjusted accordingly.
  910. Other newsgroup classes do not add much to the volume;
  911. fa.all accounts for only about 80KB/week, and btl.all+bell.all
  912. are only about 450KB/week.
  913. .n lib
  914. This directory will contain various system files.
  915. It is normally /usr/lib/news.
  916. .n bin
  917. This is the directory in which
  918. .i inews ,
  919. .i readnews ,
  920. and
  921. .i checknews
  922. are to be installed.
  923. This is normally /usr/bin.
  924. If you decide to set BINDIR to a local binary directory, you
  925. should consider that the
  926. .b rnews
  927. command must be in a directory that can be found by
  928. .b uuxqt ,
  929. which only searches /bin and /usr/bin unless you modify uuxqt.
  930. .n maxgroups
  931. The maximum number of newsgroups that the software will support.
  932. You may have to increase this as the network grows.
  933. .n "buflen, lbuflen, datelen, fpathlen, namelen, pathlen"
  934. See the description of defs.h in the file routines.doc for
  935. a description of these.  Decreasing these values to save space
  936. should not be done lightly.
  937. !E!O!F!
  938.  
  939. cat > lib/setupgrp.c <<\!E!O!F!
  940. #include <stdio.h>
  941. #include <ctype.h>
  942. #include "config.h"
  943. #include "defs.h"
  944. #include "newsrc.h"
  945. #include "artfile.h"
  946.  
  947. char *savestr(), *ckmalloc();
  948.  
  949. /*
  950.  * Set up the bit map, curng, ngsize, and groupdir for this newsgroup.
  951.  * If no newsrc was read in then we don't bother with the bit map.
  952.  */
  953.  
  954.  
  955. char *bitmap;            /* which articles have been read */
  956. ARTNO minartno;            /* first unread article */
  957. ARTNO maxartno;            /* last article */
  958.  
  959.  
  960. setupgrp(ngp, max)
  961.     struct ngentry *ngp;
  962.     ARTNO max;
  963.     {
  964.     int mapsize = (max >> 3) + 1;
  965.  
  966.     if (curng != NULL) {
  967.         updaterc();
  968.         free(bitmap);
  969.     }
  970.     curng = ngp;
  971.     maxartno = max;
  972.     bitmap = ckmalloc(mapsize);
  973.  
  974. /*
  975.  * Set up the bit map.
  976.  *
  977.  * The key to understanding this piece of code is that a bit is set iff
  978.  * that article has NOT been read.  Thus, we fill in the holes when
  979.  * commas are found (e.g. 1-20,30-35 will result in filling in the 21-29
  980.  * hold), and so we assume the newsrc file is properly ordered, the way
  981.  * we write it out. 
  982.  */
  983.     {
  984.     register char    *p, punct = ',';
  985.     register ARTNO    cur = 0;
  986.     ARTNO    next;
  987.  
  988.     bzero(bitmap, mapsize);
  989.  
  990.     /* check for first unread article */
  991.     p = ngp->ng_bits;
  992.     if (p == NULL)
  993.         p = "";
  994.     if (p[0] == '1' && p[1] == '-') {
  995.         p += 2;
  996.         cur = atoi(p);
  997.         while (isdigit(*p))
  998.             p++;
  999.     }
  1000.     minartno = cur + 1;
  1001.  
  1002.     /* process rest of bit string */
  1003.     while (*p) {
  1004.         while (!isdigit(*p) && *p)
  1005.             p++;
  1006.         if (!*p)
  1007.             break;
  1008.         next = atoi(p);
  1009.         if (next > maxartno)        /* "Can't happen" */
  1010.             next = maxartno + 1;
  1011.         if (punct == ',') {
  1012.             while (++cur < next) {
  1013.                 setunread(cur);
  1014.             }
  1015.         }
  1016.         cur = next;
  1017.         while (!ispunct(*p) && *p)
  1018.             p++;
  1019.         punct = *p;
  1020.     }
  1021.     while (++cur <= maxartno)
  1022.         setunread(cur);
  1023.     return 0;
  1024.     }
  1025. }
  1026.  
  1027.  
  1028.  
  1029. updaterc()
  1030. {
  1031.     register int    cur, next = 1;
  1032.     register char    *ptr;
  1033.     extern    int rcreadok;
  1034.     extern    char bfr[];
  1035.  
  1036.     if (!rcreadok || !curng)
  1037.         return;
  1038.     bfr[0] = bfr[1] = '\0';
  1039.     for (;;) {
  1040.         ptr = &bfr[strlen(bfr)];
  1041.         while (next <= maxartno && isunread(next))
  1042.             next++;
  1043.         if (next > maxartno)
  1044.             break;
  1045.         cur = next;
  1046.         while (next <= maxartno && ! isunread(next))
  1047.             next++;
  1048.         if (cur + 1 == next)
  1049.             sprintf(ptr, ",%d", cur);
  1050.         else
  1051.             sprintf(ptr, ",%d-%d", cur, next - 1);
  1052.     }
  1053.     if (curng->ng_bits != NULL)
  1054.         free(curng->ng_bits);
  1055.     curng->ng_bits = savestr(bfr + 1);    /* the +1 skips the leading comma */
  1056. }
  1057. !E!O!F!
  1058.  
  1059. cat > lib/str.h <<\!E!O!F!
  1060. /* string declarations */
  1061.  
  1062. char *index(), *rindex(), *sindex(), *strpbrk();
  1063. char *ckmalloc(), *savestr(), *nsavestr();
  1064. #define scopy(from, to)    strcpy(to, from)
  1065. #define equal(s1, s2)    (strcmp(s1, s2) == 0)
  1066. !E!O!F!
  1067.  
  1068. cat > lib/strcspn.c <<\!E!O!F!
  1069. /*
  1070.  * strcspn - find length of initial segment of s1 consisting entirely
  1071.  * of characters not from s2
  1072.  */
  1073.  
  1074. int
  1075. strcspn(s1, s2)
  1076. char *s1;
  1077. char *s2;
  1078. {
  1079.     register char *scan1;
  1080.     register char *scan2;
  1081.     register int count;
  1082.  
  1083.     count = 0;
  1084.     for (scan1 = s1; *scan1 != '\0'; scan1++) {
  1085.         for (scan2 = s2; *scan2 != '\0';)    /* ++ moved down. */
  1086.             if (*scan1 == *scan2++)
  1087.                 return(count);
  1088.         count++;
  1089.     }
  1090.     return(count);
  1091. }
  1092. !E!O!F!
  1093.  
  1094. cat > lib/stroff.h <<\!E!O!F!
  1095. #define stroff(member, str)    ((char *)&((struct str *)0)->member - (char *)0)
  1096. !E!O!F!
  1097.  
  1098. cat > lib/strpbrk.c <<\!E!O!F!
  1099. #include "config.h"
  1100. #if USGREL < 30
  1101. /*
  1102.  * strpbrk - find first occurrence of any char from s2 in s1
  1103.  *         Written by Henry Spencer.
  1104.  */
  1105.  
  1106. #define    NULL    0
  1107.  
  1108. char *                /* found char, or NULL if none */
  1109. strpbrk(s1, s2)
  1110. char *s1;
  1111. char *s2;
  1112. {
  1113.     register char *scan1;
  1114.     register char *scan2;
  1115.  
  1116.     for (scan1 = s1; *scan1 != '\0'; scan1++) {
  1117.         for (scan2 = s2; *scan2 != '\0';)    /* ++ moved down. */
  1118.             if (*scan1 == *scan2++)
  1119.                 return(scan1);
  1120.     }
  1121.     return(NULL);
  1122. }
  1123. #endif
  1124. !E!O!F!
  1125.  
  1126. cat > lib/strpbrk.u3b <<\!E!O!F!
  1127.     .file    "strpbrk.u3b"    # think of this line as an offering to the gods
  1128.  
  1129. # char *strpbrk(s1, s2)  char *s1, *s2;
  1130. # Finds first occurance in s1 of a character in s2.
  1131.  
  1132.     .text
  1133.     .globl    strpbrk
  1134.     .align    4
  1135. strpbrk:
  1136.     save    &2            # save r7 and r8
  1137.     movw    0(%ap), %r0        # r0 = s1
  1138.     movw    4(%ap), %r8        # r8 = s2
  1139.     movw    &0, %r2            # string termination character
  1140.     jmp    L2
  1141. L1:                    # while (*s1 != '\0') {
  1142.       movw      %r8, %r7        #   get s2
  1143.       locce      %r7, %r1, %r2        #   strchr(s2, *s1)
  1144.       je      L4            #   if found, return
  1145.       addw2      &1, %r0        #   increment s1
  1146. L2:      movb      0(%r0), %r1        #   get *s1
  1147.       jne      L1            #   loop if not at end of string
  1148.     movw    &0, %r0            # set s1 to NULL
  1149. L4:    ret    &2            # and return s1
  1150. !E!O!F!
  1151.  
  1152. cat > lib/strspn.c <<\!E!O!F!
  1153. /*
  1154.  * strspn - find length of initial segment of s1 consisting entirely
  1155.  * of characters from s2
  1156.  */
  1157.  
  1158. int
  1159. strspn(s1, s2)
  1160. char *s1;
  1161. char *s2;
  1162. {
  1163.     register char *scan1;
  1164.     register char *scan2;
  1165.     register int count;
  1166.  
  1167.     count = 0;
  1168.     for (scan1 = s1; *scan1 != '\0'; scan1++) {
  1169.         for (scan2 = s2; *scan2 != '\0'; scan2++)
  1170.             if (*scan1 == *scan2)
  1171.                 break;
  1172.         if (*scan2 == '\0')
  1173.             return(count);
  1174.         count++;
  1175.     }
  1176.     return(count);
  1177. }
  1178. !E!O!F!
  1179.  
  1180. cat > lib/strtok.c <<\!E!O!F!
  1181. /*
  1182.  * Get next token from string s1 (NULL on 2nd, 3rd, etc. calls),
  1183.  * where tokens are nonempty strings separated by runs of
  1184.  * chars from s2.  Writes NULs into s1 to end tokens.  s2 need not
  1185.  * remain constant from call to call.
  1186.  */
  1187.  
  1188. #define    NULL    0
  1189.  
  1190. static char *scanpoint = NULL;
  1191.  
  1192. char *                /* NULL if no token left */
  1193. strtok(s1, s2)
  1194. char *s1;
  1195. register char *s2;
  1196. {
  1197.     register char *scan;
  1198.     char *tok;
  1199.     register char *scan2;
  1200.  
  1201.     if (s1 == NULL && scanpoint == NULL)
  1202.         return(NULL);
  1203.     if (s1 != NULL)
  1204.         scan = s1;
  1205.     else
  1206.         scan = scanpoint;
  1207.  
  1208.     /*
  1209.      * Scan leading delimiters.
  1210.      */
  1211.     for (; *scan != '\0'; scan++) {
  1212.         for (scan2 = s2; *scan2 != '\0'; scan2++)
  1213.             if (*scan == *scan2)
  1214.                 break;
  1215.         if (*scan2 == '\0')
  1216.             break;
  1217.     }
  1218.     if (*scan == '\0') {
  1219.         scanpoint = NULL;
  1220.         return(NULL);
  1221.     }
  1222.  
  1223.     tok = scan;
  1224.  
  1225.     /*
  1226.      * Scan token.
  1227.      */
  1228.     for (; *scan != '\0'; scan++) {
  1229.         for (scan2 = s2; *scan2 != '\0';)    /* ++ moved down. */
  1230.             if (*scan == *scan2++) {
  1231.                 scanpoint = scan+1;
  1232.                 *scan = '\0';
  1233.                 return(tok);
  1234.             }
  1235.     }
  1236.  
  1237.     /*
  1238.      * Reached end of string.
  1239.      */
  1240.     scanpoint = NULL;
  1241.     return(tok);
  1242. }
  1243. !E!O!F!
  1244.  
  1245. cat > lib/titmat.c <<\!E!O!F!
  1246. /*
  1247.  * Match title.
  1248.  */
  1249.  
  1250. titmat(title, titlist)
  1251.       char *title;
  1252.       register char **titlist;
  1253.       {
  1254.       char *sindex();
  1255.  
  1256.       while (*titlist) {
  1257.             if (sindex(title, *titlist))
  1258.                   return 1 ;
  1259.             titlist++ ;
  1260.       }
  1261.       return 0 ;
  1262. }
  1263.  
  1264.  
  1265. char *
  1266. sindex(s1, s2)
  1267.       register char *s1 ;        /* string being searched */
  1268.       register char *s2 ;        /* string being scanned for */
  1269.       {
  1270.  
  1271.       if (*s2 == '\0')
  1272.             return s1 ;
  1273.       while (*s1) {
  1274.             if (*s1 == *s2 && prefix(s1, s2))
  1275.                   return s1 ;
  1276.             s1++ ;
  1277.       }
  1278.       return 0 ;
  1279. }
  1280. !E!O!F!
  1281.  
  1282. cat > lib/tomsgid.c <<\!E!O!F!
  1283. #include "config.h"
  1284. #include "defs.h"
  1285.  
  1286. /*
  1287.  * Convert an article id to a message id if it's not already a message id.
  1288.  */
  1289.  
  1290. tomsgid(id)
  1291.       char *id ;
  1292.       {
  1293.       char lbuf[NAMELEN];
  1294.       register char *p ;
  1295.       char *index() ;
  1296.  
  1297.       if (id[0] != '<') {
  1298.             strcpy(lbuf, id);
  1299.             p = index(lbuf, '.');
  1300.             if (p == 0) {
  1301.                   return;
  1302.             }
  1303.             *p++ = '\0';
  1304.             /*
  1305.              * It may seem strange that we hardwire ".UUCP" in
  1306.              * here instead of MYDOMAIN.  However, we are trying
  1307.              * to guess what the domain was on the posting system,
  1308.              * not the local system.  Since we don't really know
  1309.              * what the posting system does, we just go with the
  1310.              * majority - almost everyone will be a .UUCP if they
  1311.              * didn't fill in their Message-ID.
  1312.              */
  1313.             sprintf(id, "<%s@%s%s>", p, lbuf, ".UUCP");
  1314.       }
  1315. }
  1316. !E!O!F!
  1317.  
  1318. cat > lib/vprintf.h <<\!E!O!F!
  1319. /*
  1320.  * These defines allow you to define routines that call printf on their
  1321.  * arguments in a way that at least marks them as machine dependent.
  1322.  * Example:
  1323.  *
  1324.  * fatal(VPARGS)
  1325.  *    VPDCL;
  1326.  *    {
  1327.  *    VFPRINTF(stderr, VPARGS);
  1328.  *    exit(1);
  1329.  * }
  1330.  *
  1331.  * Later:  use varargs.h.
  1332.  */
  1333.  
  1334. #define VPARGS msg, a1, a2, a3, a4
  1335. #define VPDCL char *msg;
  1336. #define VPRINTF(args) printf(VPARGS)
  1337. #define VFPRINTF(fp, args) fprintf(fp, VPARGS)
  1338. #define VSPRINTF(s, args) sprintf(s, VPARGS)
  1339. !E!O!F!
  1340.  
  1341. cat > lib/write.c <<\!E!O!F!
  1342. #include <stdio.h>
  1343. #include "af.h"
  1344. #include "libextern.h"
  1345.  
  1346. long lseek();
  1347.  
  1348.  
  1349. /*
  1350.  * Write a record to the data base.  We can't use stdio because fseek
  1351.  * doesn't work under 4.1 BSD.
  1352.  */
  1353.  
  1354. writerec(a, fd)
  1355.       struct artrec *a ;
  1356.       int fd ;
  1357.       {
  1358.       int i ;
  1359.       register char *p, *q ;
  1360.       char **pp ;
  1361.  
  1362.       bfr[0] = A_PREFIX ;
  1363.       bcopy((char *)a, bfr + 1, A_WRTLEN) ;
  1364.       bcopy((char *)a->a_group, bfr + 1 + A_WRTLEN, i = a->a_ngroups * sizeof(*a->a_group)) ;
  1365.       p = bfr + 1 + A_WRTLEN + i ;
  1366.       pp = &a->a_ident ;
  1367.       i = (a->a_flags & A_DUMMY)? 1 : 4 + a->a_nkwords ;
  1368.       while (--i >= 0) {
  1369.             for (q = *pp++ ; *p++ = *q++ ; ) ;
  1370.       }
  1371.       if (write(fd, bfr, p - bfr) != p - bfr)
  1372.             xerror("Write error in writerec") ;
  1373. }
  1374.  
  1375.  
  1376.  
  1377. writeptr(p, dp)
  1378.       DPTR p, dp ;
  1379.       {
  1380.       if (lseek(affd, (long)dp, 0) < 0)
  1381.             xerror("seek %ld failed, writeptr %ld", dp, p) ;
  1382.       if (write(affd, (char *)&p, sizeof p) != sizeof p)
  1383.             xerror("write failed, writeptr(%ld, %ld)", p, dp) ;
  1384. }
  1385. !E!O!F!
  1386.  
  1387. cat > postnews/artlist.c <<\!E!O!F!
  1388. /*
  1389.  * This routine generates a list of articles for postnews.
  1390.  */
  1391.  
  1392. #include <stdio.h>
  1393. #include <sys/types.h>
  1394. #include "config.h"
  1395. #include "artfile.h"
  1396. #include "ng.h"
  1397.  
  1398.  
  1399.  
  1400. artlist(ngname, pattern)
  1401.       char *ngname, *pattern ;
  1402.       {
  1403.       static struct ngrec ng ;
  1404.       struct artrec a ;
  1405.       ARTNO artno ;
  1406.       DPTR dp ;
  1407.       static int first = 1 ;
  1408.  
  1409.       if (first || strcmp(ngname, ng.g_name) != 0) {
  1410.             gfopen() ;
  1411.             ALL_GROUPS(ng) {
  1412.                   if (strcmp(ng.g_name, ngname) == 0)
  1413.                         goto found ;
  1414.             }
  1415.             xerror("%s does not appear in groupfile", ngname) ;
  1416. found:
  1417.             gfclose() ;
  1418.       }
  1419.       if (first) {
  1420.             afopen() ;
  1421.             first = 0 ;
  1422.       }
  1423.       fputs("NUMB  AUTHOR        TITLE\n", stdout) ;
  1424.       BKWD_GROUP(ng.g_num, artno, dp, a) {
  1425.             if (a.a_flags & A_DUMMY)
  1426.                   continue ;
  1427.             if (sindex(a.a_title, pattern) || sindex(a.a_from, pattern)) {
  1428.                   printf("%-5d %.16s\t", artno, a.a_from) ;
  1429.                   if (strlen(a.a_from) < 10)
  1430.                         putchar('\t') ;
  1431.                   if (strlen(a.a_from) < 2)
  1432.                         putchar('\t') ;
  1433.                   printf("%.40s\n", a.a_title) ;
  1434.             }
  1435.       }
  1436. }
  1437. !E!O!F!
  1438.  
  1439. cat > postnews/distlist <<\!E!O!F!
  1440. # This file contains descriptions of the various distributions, and is
  1441. # used to build the /usr/lib/news/distributions file which is used by
  1442. # postnews.  Unfortunately, this list is probably not complete.  Please
  1443. # mail any additions to ihnp4!hou3c!ka.
  1444.  
  1445. local    Local to this site
  1446. unm    University of New Mexico
  1447. um    University of Maryland
  1448. wat    Universtiy of Waterloo
  1449. atl    Atlanta
  1450. ba    SF Bay Area
  1451. chi    Chicago
  1452. cmh    Columbus, Ohio
  1453. la    Los Angeles
  1454. ho    AT&T Holmdel location
  1455. ih    AT&T Indian Hill location
  1456. cb    AT&T Columbus location
  1457. mh    AT&T Murrey Hill location
  1458. dr    AT&T IS Denver location
  1459. ont    Onterio
  1460. ca    California
  1461. ga    Georgia
  1462. nj    New Jersey
  1463. ny    New York
  1464. oh    Ohio
  1465. or    Oregon
  1466. ne    New England
  1467. intel    Intel
  1468. tek    Tektronix
  1469. btl    AT&T Bell Labs
  1470. att    AT&T
  1471. bell    Bell operating companies
  1472. usa    United States
  1473. can    Canada
  1474. na    North America
  1475. uk    United Kingdom
  1476. eunet    Europe
  1477. world    Everywhere on Usenet in the world (same as net)
  1478. !E!O!F!
  1479.  
  1480. cat > postnews/genmakefile <<\!E!O!F!
  1481. LIB=../lib
  1482. . $LIB/makedefs
  1483. exec > makefile
  1484. cat <<!
  1485. # makefile 2.11-B 1/12/85
  1486.  
  1487. LIB=$LIB
  1488. !
  1489. cat $LIB/makedefs
  1490. cat <<\!
  1491.  
  1492. POSTNEWS = postnews.o artlist.o $(LIB)/rpathinit.o $(LIB)/rlib.a
  1493. POSTREPLY = postreply.o $(LIB)/rpathinit.o $(LIB)/rlib.a
  1494. POSTNM = postnm1.o postnm2.o postnm3.o postnm4.o postnm5.o $(LIB)/rpathinit.o $(LIB)/rlib.a
  1495. RECMAIL = recmail.o
  1496. CFLAGS = $(DEBUG) -I$(LIB)
  1497. DEBUG = -O
  1498.  
  1499. all: makefile postnews postreply postnm distributions gparent.wm
  1500.  
  1501. makefile: genmakefile $(LIB)/makedefs
  1502.     genmakefile
  1503.     @echo 'Makefile changed, so restart make.'
  1504.     @sh -c 'exit 22'
  1505.  
  1506. install: all $(LIBDIR)/distributions $(LIBDIR)/moderators
  1507.     -/bin/mv $(BINDIR)/postnews $(BINDIR)/opostnews
  1508.     /bin/cp postnews postnm gparent $(BINDIR)
  1509.     /bin/cp postreply $(LIBDIR)/postreply
  1510.  
  1511. postnews: $(POSTNEWS)
  1512.     $(CC) $(DEBUG) -o $@ $(POSTNEWS)
  1513.  
  1514. postreply: $(POSTREPLY)
  1515.     $(CC) $(DEBUG) -o $@ $(POSTREPLY)
  1516.  
  1517. postnm: $(POSTNM)
  1518.     $(CC) $(DEBUG) -o $@ $(POSTNM)
  1519.  
  1520. recmail: $(RECMAIL)
  1521.     $(CC) $(DEBUG) -o $@ $(RECMAIL)
  1522.  
  1523. distributions: distlist
  1524.     makedist > distributions
  1525.  
  1526. gparent.wm: gparent.wm.c
  1527.     $(CC) gparent.wm.c
  1528.     a.out > gparent.wm
  1529.     rm a.out
  1530.  
  1531. $(LIBDIR)/distributions: distributions
  1532.     -/bin/mv $(LIBDIR)/distributions $(LIBDIR)/odistributions
  1533.     /bin/cp distributions $(LIBDIR)/distributions
  1534.  
  1535. $(LIBDIR)/moderators:
  1536.     /bin/cp moderators $@
  1537.  
  1538. postnews.o postreply.o recmail.o: $(FRC)
  1539. postnm1.o postnm2.o postnm3.o postnm4.o postnm5.o: postnm.h $(FRC)
  1540.  
  1541. FRC:
  1542. !
  1543. !E!O!F!
  1544. chmod +x postnews/genmakefile
  1545.  
  1546. cat > postnews/gparent <<\!E!O!F!
  1547. #!/bin/sh
  1548. a=${1-${A?}}
  1549. sed -e '1,/^$/d' -e 's/^/> /' $a
  1550. !E!O!F!
  1551. chmod +x postnews/gparent
  1552.  
  1553. cat > postnews/gparent.ml <<\!E!O!F!
  1554. ; This mlisp macro reads in the body of the article being followed up,
  1555. ; preceding each line with a "> ".
  1556. ; It is intended to be bound to ^X^Y.
  1557.  
  1558. (defun
  1559.     (gparent
  1560.     (end-of-file)
  1561.     (save-excursion
  1562.         (set-mark)
  1563.         (insert-file (getenv "A"))
  1564.         (re-search-forward "^$")
  1565.         (next-line)
  1566.         (erase-region)
  1567.         (re-replace-string "^" "> ")
  1568.     )
  1569.     )
  1570. )
  1571. !E!O!F!
  1572.  
  1573. cat > postnews/gparent.wm.c <<\!E!O!F!
  1574. /*
  1575.  * Since the gparent macro for Warren Montgomery's emacs
  1576.  * contains control characters, it cannot be distributed
  1577.  * directly over the net.  This C program will write the
  1578.  * macro to the standard output.
  1579.  */
  1580.  
  1581. #define SIZE 95
  1582.  
  1583. char gparent[SIZE] = {
  1584.       0030,0031,0034,0147,0160,0141,0162,0145,0156,0164,
  1585.       0040,0055,0040,0151,0156,0163,0145,0162,0164,0040,
  1586.       0142,0157,0144,0171,0040,0157,0146,0040,0157,0162,
  1587.       0151,0147,0151,0156,0141,0154,0040,0141,0162,0164,
  1588.       0151,0143,0154,0145,0012,0276,0000,0030,0074,0101,
  1589.       0012,0305,0025,0030,0022,0030,0030,0000,0030,0074,
  1590.       0136,0044,0012,0223,0016,0027,0030,0055,0033,0061,
  1591.       0064,0000,0030,0074,0076,0040,0012,0030,0074,0136,
  1592.       0012,0222,0122,0033,0062,0010,0030,0055,0033,0061,
  1593.       0064,0030,0030,0032,0012
  1594. };
  1595.  
  1596. main() {
  1597.       int i ;
  1598.  
  1599.       for (i = 0 ; i < SIZE ; i++)
  1600.             putchar(gparent[i]);
  1601.       return 0;
  1602. }
  1603. !E!O!F!
  1604.  
  1605. cat > postnews/letter <<\!E!O!F!
  1606. To: uucp-news@cbosgd
  1607. Subject: A new program: postnm
  1608. Message-ID: <467517088@hou3c.UUCP>
  1609.  
  1610. This program is not quite finished yet, but I thought I would let you
  1611. know about it.
  1612.  
  1613. NAME:
  1614.     Postnm - post news and/or mail
  1615.  
  1616. SYNOPSYS:
  1617.     postnm -x [ file ]
  1618.  
  1619. DESCRIPTION:
  1620.  
  1621. Postnm reads and article from the file, or from the standard input if
  1622. no filename is specified.  If the article header contains a Newsgroup:
  1623. line, the article is posted.  If it contains To:, Cc:, or Bcc: lines,
  1624. the article is mailed to the specified recipients.
  1625.  
  1626. Postnm attempts to pass only valid articles to inews.  Postnm cannot
  1627. guarentee to pass only valid mail to the mail program because of the
  1628. lack of standardization of mail under UNIX.  Therefore, tries to accept
  1629. a variety of mail formats and to pass them through to the mailer
  1630. unchanged.
  1631.  
  1632. The input to the program should look like a USENET article or a piece
  1633. of RFC822 mail.  Some headers supported by postnm are:
  1634.  
  1635. To:, Cc:, and Bcc:
  1636.     These lines are scanned for address to be passed to the mail
  1637.     program.  Commas between the addresses are optional.  Any RFC
  1638.     822 address should be accepted as long as it is formatted
  1639.     sensibly (no comments within the address, and no white space
  1640.     except within angle brackets or around the at sign).  Some
  1641.     legal address lines are:
  1642.         To: "Kenneth Almquist" @ hou3c.UUCP  (That's me)
  1643.         To: Kenneth Almquist <@cbosgd.UUCP: ka@hou3c.UUCP>
  1644.     The address is passed to the mailer uninterpreted except that
  1645.     comments and any enclosing angle brackets are deleted.
  1646.  
  1647. Newsgroups:, Followup-To:
  1648.     Newsgroups on these lines are separated by white space and/or
  1649.     commas.
  1650.  
  1651. From:, Reply-To:
  1652.     On posted news, these lines will be converted to the format:
  1653.         From: user@machine (Real Name)
  1654.  
  1655. References:
  1656.     This line is passed through to news.  If you don't include an
  1657.     In-reply-to: line, one will be generated from the References:
  1658.     line.
  1659.  
  1660. Command:
  1661.     This specifies that the article is a reply or a followup.  If
  1662.     "Command: reply" is specified, any Newsgroup: line will be
  1663.     ignored.  If "Command: followup" is specified, any "To:" line
  1664.     will be ignored.  This way, if you type a followup command and
  1665.     then decide that your reply really isn't of interest to the
  1666.     entire net, you can edit this line.
  1667.  
  1668. Other headers are supported.  In addition, any unsupported header is
  1669. passed thorough unchanged if it does not appear to be a misspelling of
  1670. a supported header.
  1671.  
  1672. Although postnm will read from its standard input if no file is given,
  1673. typing an article directly into postnm from the terminal is
  1674. expressly frowned upon because that mode of operation makes it
  1675. difficult to correct errors.  Therefore, postnm will not save the
  1676. article in dead.article if an error occurs.
  1677.                 Kenneth Almquist
  1678. !E!O!F!
  1679.  
  1680. cat > postnews/makedist <<\!E!O!F!
  1681. : This shell procedure creates the distributions file.
  1682.  
  1683. . ../lib/makedefs
  1684.  
  1685. dlist=`sed -e '/^#/d' -e 's/[^:]*://' -e 's/:.*//' -e 's/,/ /g' -e 's/  */ /g' $LIBDIR/sys | tr ' ' '
  1686. ' | sed -e '/^!/d' -e 's/\..*//' | sort | uniq`
  1687.  
  1688. exec < distlist
  1689. while read dist desc
  1690. do    case "$dist" in
  1691.     ""|\#*)    ;;
  1692.     local|world)
  1693.         echo "$dist    $desc"
  1694.         ;;
  1695.     *)    ndlist=
  1696.         for x in $dlist
  1697.         do    if test "$x" = "$dist"
  1698.             then    echo "$dist    $desc"
  1699.             else    ndlist="$ndlist $x"
  1700.             fi
  1701.         done
  1702.         dlist="$ndlist"
  1703.         ;;
  1704.     esac
  1705. done
  1706. ndlist=
  1707. for x in $dlist
  1708. do    case "$x" in
  1709.     fa|mod|net|ug|to|all)
  1710.         ;;
  1711.     *)    grep "^$x " $LIBDIR/active > junk
  1712.         if test -s junk
  1713.         then    :
  1714.         else    ndlist="$ndlist $x"
  1715.         fi
  1716.         rm junk
  1717.         ;;
  1718.     esac
  1719. done
  1720. if test "$ndlist" != "" -a "$ndlist" != " "
  1721. then    echo "The following distributions are not known to me: $ndlist" >&2
  1722.     echo "Please add descriptions of them to postnews/distlist." >&2
  1723.     exit 1
  1724. fi
  1725. exit 0
  1726. !E!O!F!
  1727. chmod +x postnews/makedist
  1728.  
  1729. cat > postnews/moderators <<\!E!O!F!
  1730. net.announce    announce@cbosgd.UUCP
  1731. net.announce.newusers    usenet@gatech.UUCP
  1732. mod.map        mark@cbosgd.UUCP
  1733. mod.map.news    map@cbosgd.UUCP
  1734. mod.map.uucp    uucpmap@cbosgd.UUCP
  1735. mod.motss    motss@bbncca.UUCP
  1736. mod.movies    movies@ecsvax.UUCP
  1737. mod.music    gregbo@hou2e.UUCP
  1738. mod.newslists    usenet@gatech.UUCP
  1739. mod.singles    singles@nsc.UUCP
  1740. mod.sources    sources@genrad.UUCP
  1741. mod.std.c    std-c@cbosgd.UUCP
  1742. mod.std.mumps    std-mumps@plus5.UUCP
  1743. mod.unix    unix@masscomp.UUCP
  1744. fa.arms-d    arms-d@ucbvax.UUCP
  1745. fa.arpa-bboard    arpa-bboard@ucbvax.UUCP
  1746. fa.bitgraph    INFO-BITGRAPH@MIT-MC.ARPA
  1747. fa.human-nets    human-nets@brl-bmd.UUCP
  1748. fa.info-mac    info-mac@uw-beaver.UUCP
  1749. fa.info-vax    info-vax@ucbvax.UUCP
  1750. fa.laser-lovers    laser-lovers@uw-beaver.UUCP
  1751. fa.poli-sci    poli-sci@ucbvax.UUCP
  1752. fa.telecom    telecom@brl-bmd.UUCP
  1753. fa.raliroad    railroad@ucbvax.UUCP
  1754. !E!O!F!
  1755.  
  1756. echo Part 4 of 7 extracted.
  1757.  
  1758.  
  1759.