home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume6 / newbatcha.new < prev    next >
Internet Message Format  |  1986-11-30  |  33KB

  1. From espo@bpa.BELL-ATL.COM Tue Aug 19 06:07:02 1986
  2. Received: by mirror.UUCP (4.12/UUCP-Project/rel-1.0/07-25-86)
  3.     id AA23998; Tue, 19 Aug 86 06:04:50 edt
  4. Received: from bpa.UUCP by seismo.CSS.GOV with UUCP; Mon, 18 Aug 86 13:18:19 EDT
  5. Received: by bpa.BELL-ATL.COM (4.12/UUCP-Project/rel-1.0/07-25-86)
  6.     id AA22779; Mon, 18 Aug 86 07:24:43 edt
  7. Date: Mon, 18 Aug 86 07:24:43 edt
  8. From: espo@bpa.BELL-ATL.COM (Bob Esposito)
  9. Message-Id: <8608181124.AA22779@bpa.BELL-ATL.COM>
  10. To: rs@mirror.ARPA
  11. Subject: nbatcher source
  12. Status: R
  13.  
  14.  
  15. Rich,
  16.  
  17.     Since the fixes are not in a patch format, here's the entire
  18.     source in shar format.  I will post it to net.sources as
  19.     requested.  Thanks,
  20.  
  21.  
  22. --
  23.         //////////////////////////////////////////
  24.         * Bob Esposito  ...espo@bpa.bell-atl.com *
  25.         //////////////////////////////////////////
  26.  
  27.  
  28. #!/bin/sh
  29. # shar:    Shell Archiver
  30. #    Run the following text with /bin/sh to create:
  31. #    define.c
  32. #    main.c
  33. #    parse.c
  34. #    checkwork.c
  35. #    nbatcher.c
  36. #    logger.c
  37. #    nbatcher.h
  38. #    bst.c
  39. #    README
  40. #    nbatcher.ctl
  41. #    nbatcher.doc
  42. #    nbatcher.1
  43. #    Makefile
  44. echo x - extracting define.c
  45. sed 's/^X//' << 'SHAR_EOF' > define.c
  46. X/* char    sccsid[] = "@(#)define.c 1.4 8/14/86"; */
  47. X
  48. X/*******************************************************
  49. X *    define.c - global defines for nbatcher.
  50. X *
  51. X *    R.J. Esposito
  52. X *    Bell of Penna.
  53. X *    June 1986
  54. X *
  55. X ******************************************************/
  56. X
  57. X#include <stdio.h>
  58. X#include "nbatcher.h"
  59. X
  60. XFILE    *lfp,
  61. X    *tfp,
  62. X    *log = NULL;
  63. X
  64. Xlong    n_bytes,
  65. X    cu_bytes;
  66. X
  67. Xchar    *tfile = NULL;
  68. X
  69. Xshort    vflg = 0,
  70. X    nfiles = 10;
  71. X
  72. Xint    fcnt = 0,
  73. X    scnt = 0;
  74. X
  75. SHAR_EOF
  76. echo x - extracting main.c
  77. sed 's/^X//' << 'SHAR_EOF' > main.c
  78. Xchar    sccsid[] = "nbatcher 1.4 8/14/86";
  79. X
  80. X/********************************************
  81. X *
  82. X *    main.c - for nbatcher
  83. X *
  84. X *    R.J. Esposito
  85. X *    Bell of Penna.
  86. X *    June 1986
  87. X *
  88. X ********************************************/
  89. X
  90. X#include <stdio.h>
  91. X#include "nbatcher.h"
  92. X
  93. Xmain()
  94. X{
  95. X    int    uid, nowork;
  96. X    FILE    *cfp;
  97. X    char    fbuf[BUFSIZ];
  98. X
  99. X    uid = getuid();
  100. X
  101. X    if (uid && uid != NEWSUID)
  102. X        xerror ("permission denied - not NEWSUSER\n");
  103. X
  104. X    if (chdir(LIBDIR) < 0)
  105. X        xerror ("can't chdir to %s\n", LIBDIR);
  106. X
  107. X    if ((cfp=fopen("nbatcher.ctl", "r")) == NULL)
  108. X        xerror ("no `batcher.ctl' file found\n");
  109. X
  110. X    if (isatty(0)) {
  111. X        vflg = TRUE;
  112. X        (void) fprintf(stderr, "%s\n", sccsid);
  113. X    }
  114. X
  115. X    nowork = TRUE;
  116. X    while ((fgets(fbuf, sizeof(fbuf), cfp)) != NULL) {
  117. X        if (fbuf[0] == '*' || fbuf[0] == '\n')
  118. X            continue;
  119. X        parse_entry (fbuf);
  120. X        if (!work_to_do())
  121. X            continue;
  122. X        batch_it ();
  123. X        nowork = FALSE;
  124. X    }
  125. X
  126. X    fclose (cfp);
  127. X    fclose (tfp);
  128. X    unlink (tfile);
  129. X    if (vflg == TRUE && nowork == TRUE)
  130. X        (void) fprintf(stderr, "no work to do\n");
  131. X    exit (0);
  132. X}
  133. X    
  134. SHAR_EOF
  135. echo x - extracting parse.c
  136. sed 's/^X//' << 'SHAR_EOF' > parse.c
  137. X/* char    sccsid[] = "@(#)parse.c 1.4 8/14/86"; */
  138. X
  139. X/****************************************************************
  140. X *
  141. X *    parse.c - nbatcher line parser for the control file
  142. X *
  143. X *
  144. X *    R.J. Esposito
  145. X *    Bell of Penna.
  146. X *    June 1986
  147. X *
  148. X ****************************************************************/
  149. X
  150. X#include <stdio.h>
  151. X#include <sys/types.h>
  152. X#include <ctype.h>
  153. X#include "nbatcher.h"
  154. X
  155. X#define MAX_BYTES    1000000L    /* max allowable bytes */
  156. X
  157. Xparse_entry (line)
  158. Xchar *line;
  159. X{
  160. X    register char    *p;
  161. X    short    num, upper;
  162. X    short    lower, dash;
  163. X    long    l_num;
  164. X
  165. X    upper = 23;    /* upper hour limit */
  166. X    lower = 0;    /* lower hour limit */
  167. X    dash = 0;
  168. X
  169. X    clear_entry (&ep);    /* zero out the structure */
  170. X
  171. X    p = (char *) ep.site;
  172. X
  173. X    /* get the site name and copy
  174. X       it to the structure */
  175. X
  176. X    while (*line && *line != COLON)
  177. X        *p++ = *line++;
  178. X    *p = '\0';
  179. X    if (*++line == '\n' || *line == '\0')
  180. X        xerror ("illegal number of fields\n");
  181. X
  182. X    /* check that its valid */
  183. X
  184. X    if (ep.site[0] == '\0')
  185. X        xerror ("null site name in control file\n");
  186. X
  187. X    /* now, parse the hour string and check
  188. X       for valid syntax */
  189. X
  190. X    p = (char *) ep.hour;
  191. X    while (*line && *line != COLON)
  192. X        *p++ = *line++;
  193. X
  194. X    *p = '\0';
  195. X    if (*++line == '\n' || *line == '\0')
  196. X        xerror ("illegal number of fields\n");
  197. X
  198. X    if (ep.hour[0] == '\0')
  199. X        xerror ("null hour string in control file\n");
  200. X
  201. X    /* now re-scan the hour in structure and
  202. X       weed out the badies */
  203. X
  204. X    if (ep.hour[0] == '*' && ep.hour[1] != '\0')
  205. X        xerror ("invalid hour string syntax: %s\n", ep.hour);
  206. X    else if (ep.hour[0] == '*')
  207. X        goto h_skip;
  208. X
  209. X    if (strcmp(ep.hour, "off", 3) == 0 && ep.hour[3] != '\0')
  210. X        xerror ("invalid hour string syntax: %s\n", ep.hour);
  211. X    else if (strncmp(ep.hour, "off", 3) == 0)
  212. X        goto h_skip;
  213. X
  214. X    p = (char *) ep.hour;
  215. X    if (!isdigit(*p))
  216. X        xerror ("non-numeric char in hour string: %c\n", *p);
  217. X
  218. X    while (*p) {
  219. X        num = 0;
  220. X        do {
  221. X            num = num*10 + (*p - '0');
  222. X        } while (isdigit(*++p));
  223. X
  224. X        if (num < lower || num > upper)
  225. X            xerror ("illegal hour: %d\n", num);
  226. X
  227. X        if (!*p)
  228. X            break;
  229. X
  230. X        if (*p == '-' && dash)
  231. X            xerror ("syntax error in hour field\n");
  232. X        else if (*p == '-')
  233. X            dash = TRUE;
  234. X
  235. X        if (*p != ',' && *p != '-')
  236. X            xerror ("non-numeric char in hour string: %c\n", *p);
  237. X        else if (!isdigit(*++p))
  238. X            xerror ("syntax error in hour field\n");
  239. X
  240. X    }
  241. X
  242. X    /* now that thats over with, let do the compression
  243. X       field.  Only 9-16 is allowed, except a null field
  244. X       indicates no compression for this site. */
  245. X
  246. Xh_skip:
  247. X    num = 0;
  248. X    while (*line && *line != COLON) {
  249. X        if (!isdigit(*line))
  250. X            xerror ("non-numeric in compression field\n");
  251. X        num = num*10 + (*line++ - '0');
  252. X    }
  253. X    if (*++line == '\n' || *line == '\0')
  254. X        xerror ("illegal number of fields\n");
  255. X
  256. X    if (num != 0 && (num < 9 || num > 16))
  257. X        xerror ("illegal compression bits: %d\n", num);
  258. X
  259. X    ep.c_bits = num;
  260. X
  261. X    /* now check the max. bytes for UUCP queue.
  262. X       Note: There is a max. allowable # of bytes
  263. X         here, set at 1MB.  Change it at your
  264. X         own risk.
  265. X    */
  266. X
  267. X    l_num = 0;
  268. X    while (*line && *line != COLON) {
  269. X        if (!isdigit(*line))
  270. X            xerror ("non-numeric in max. bytes field\n");
  271. X
  272. X        l_num = l_num*10 + (*line++ - '0');
  273. X    }
  274. X
  275. X    if (l_num > MAX_BYTES)
  276. X        xerror ("%ld max. bytes exceeds allowable maximun\n", l_num);
  277. X
  278. X    if (l_num != 0)
  279. X        ep.m_bytes = l_num;
  280. X    else
  281. X        ep.m_bytes = DFL_BYTES;
  282. X
  283. X    /* and finally the command line (if there is one) */
  284. X
  285. X    p = (char *) ep.command;
  286. X
  287. X    if (*++line != '\n' && *line != '\0') {
  288. X        while (*line && *line != '\n')
  289. X            *p++ = *line++;
  290. X
  291. X        *p = '\0';
  292. X    }
  293. X}
  294. X
  295. X#ifdef USE_PORT_CODE
  296. Xxerror (fmt, a1, a2)
  297. Xchar *fmt;
  298. Xchar *a1, *a2;
  299. X{
  300. X    char    buf[BUFSIZ];
  301. X
  302. X    sprintf (buf, fmt, a1, a2);
  303. X    printf ("\nnbatcher: %s\n", fmt);
  304. X    exit (99);
  305. X}
  306. X
  307. X#else
  308. Xxerror (fmt, argp)
  309. Xchar *fmt;
  310. Xint argp;
  311. X{
  312. X    char    buf[BUFSIZ];
  313. X    char    fbuf[BUFSIZ];
  314. X    FILE    prwbuf;
  315. X    register char    *cp;
  316. X    
  317. X    prwbuf._flag = _IOWRT;
  318. X    prwbuf._file = _NFILE;
  319. X    prwbuf._cnt = 32767;
  320. X    prwbuf._ptr = (unsigned char *)buf;
  321. X    prwbuf._base = (unsigned char *)buf;
  322. X    sprintf (fbuf, "\n%s: %s", "nbatcher", fmt);
  323. X    _doprnt (fbuf, (char *)&argp, &prwbuf);
  324. X    putc ('\0', &prwbuf);
  325. X    for (cp = buf; *cp != '\0'; cp++)
  326. X        putchar (*cp);
  327. X
  328. X    exit (99);
  329. X}
  330. X#endif    /* USE_PORT_CODE */
  331. X
  332. Xclear_entry (s)
  333. Xchar *s;
  334. X{
  335. X    register int i;
  336. X
  337. X    for (i=0; i<sizeof(struct file_entry); *s++ = '\0', i++)
  338. X                ;
  339. X
  340. X}
  341. SHAR_EOF
  342. echo x - extracting checkwork.c
  343. sed 's/^X//' << 'SHAR_EOF' > checkwork.c
  344. X/* char    sccsid[] = "@(#)checkwork.c 1.4 8/14/86"; */
  345. X
  346. X/************************************************************
  347. X *
  348. X *    checkwork.c - look to see if there's any work
  349. X *              to do for a site.
  350. X *
  351. X *    R.J. Esposito
  352. X *    Bell of Penna.
  353. X *    June 1986
  354. X *
  355. X ************************************************************/
  356. X
  357. X#include <stdio.h>
  358. X#include <sys/types.h>
  359. X#include <sys/stat.h>
  360. X#include <sys/utsname.h>
  361. X#include <sys/dir.h>
  362. X#include <ctype.h>
  363. X#include <time.h>
  364. X#include "nbatcher.h"
  365. X
  366. Xwork_to_do ()
  367. X{
  368. X    register char    *p;
  369. X    struct tm    *localtime(), *tp;
  370. X    struct stat    st;
  371. X    char    buf[BUFSIZ];
  372. X    long    time(), clock;
  373. X    int    hour;
  374. X    short    num, upper, lower;
  375. X
  376. X    sprintf (buf, "%s/%s", BATCHDIR, ep.site);
  377. X
  378. X    if (stat(buf, &st) < 0)
  379. X        xerror ("bad stat on %s\n", buf);
  380. X
  381. X    /* if the size of the batch file is
  382. X       zero, return FALSE
  383. X    */
  384. X
  385. X    if (st.st_size == 0)
  386. X        return (FALSE);
  387. X
  388. X    /* now see if it time to do anything */
  389. X
  390. X    clock = time ((long *)0);
  391. X    tp = localtime (&clock);
  392. X    hour = tp->tm_hour;
  393. X
  394. X    p = (char *) ep.hour;
  395. X
  396. X    if (*p == '*')        /* match any hour */
  397. X        return (check_uucp());
  398. X
  399. X    if (strncmp(p, "off", 3) == 0)    /* just what it says, off */
  400. X        return (FALSE);
  401. X
  402. X    /* parse thru hour field to see if
  403. X       this is the hour to do work */
  404. X
  405. X    num = 0;
  406. X    do {
  407. X        num = num*10 + (*p - '0');
  408. X    } while (isdigit(*++p));
  409. X    if (num == hour)
  410. X        return (check_uucp());
  411. X
  412. X    if (*p == '-') {
  413. X        lower = num;
  414. X        p++;
  415. X        num = 0;
  416. X        do {
  417. X            num = num*10 + (*p - '0');
  418. X        } while (isdigit(*++p));
  419. X        upper = num;
  420. X
  421. X        if (lower < upper) {    /* normal hour range */
  422. X            if (hour >= lower && hour <= upper)
  423. X                return (check_uucp());
  424. X        } else if (lower > upper) {    /* 24 hr. cycle thru */
  425. X            if (hour >= lower || hour <= upper)
  426. X                return (TRUE);
  427. X        } else
  428. X            return (FALSE);
  429. X    }
  430. X
  431. X    if (*p == ',') {
  432. X        p++;
  433. X        while (*p) {
  434. X            num = 0;
  435. X            do {
  436. X                num = num*10 + (*p - '0');
  437. X            } while (isdigit(*++p));
  438. X            if (num == hour)
  439. X                return (check_uucp());
  440. X            p++;
  441. X        }
  442. X    }
  443. X
  444. X    return (FALSE);
  445. X}
  446. X
  447. X/*    If check_uucp cannot find the remote site
  448. X *    directory, just bypass the byte counting
  449. X *    routine.  This is necessary because the
  450. X *    uucpcleanup daemon, on some sites, removes
  451. X *    the site directory when there's nothing there.
  452. X */
  453. X
  454. Xcheck_uucp()
  455. X{
  456. X    struct utsname    utsn;
  457. X    struct direct    dp;
  458. X    struct stat    st;
  459. X    FILE    *dfp;
  460. X    char    u_name[9], buf[80];
  461. X    short    prefix_len;
  462. X
  463. X    if (uname(&utsn) < 0)
  464. X        xerror ("can't get local nodename\n");
  465. X
  466. X    sprintf (buf, "%s/%s", UUCPDIR, ep.site);
  467. X    if (chdir(buf) < 0) {
  468. X       fprintf (stderr, "\nnbatcher: can't chdir to %s - bypassing UUCP check\n", buf);
  469. X       return (TRUE);
  470. X    }
  471. X
  472. X    if ((dfp=fopen(".", "r")) == NULL) {
  473. X       fprintf (stderr, "\nnbatcher: fopen error on %s - bypassing UUCP check\n", UUCPDIR);
  474. X       return (TRUE);
  475. X    }
  476. X
  477. X    sprintf (buf, "D.%s", utsn.nodename);
  478. X    prefix_len = (short) strlen(buf);
  479. X    n_bytes = 0;
  480. X    while ((fread((char *)&dp, sizeof(dp), 1, dfp)) == 1) {
  481. X        if (dp.d_ino == 0 || dp.d_name[0] == '.')
  482. X            continue;
  483. X        if (strncmp(dp.d_name, buf, prefix_len))
  484. X            continue;
  485. X        if (stat(dp.d_name, &st) < 0) {
  486. X          fprintf (stderr, "\nnbatcher: bad stat on UUCP_file %s - bypassing\n", dp.d_name);
  487. X          continue;
  488. X        }
  489. X        n_bytes += st.st_size;
  490. X        if (n_bytes > ep.m_bytes) {
  491. X            fclose (dfp);
  492. X            return (FALSE);
  493. X        }
  494. X    }
  495. X    fclose (dfp);
  496. X    if (chdir(LIBDIR) < 0)
  497. X        xerror ("can't chdir back to %s\n", LIBDIR);
  498. X
  499. X    return (TRUE);
  500. X}
  501. SHAR_EOF
  502. echo x - extracting nbatcher.c
  503. sed 's/^X//' << 'SHAR_EOF' > nbatcher.c
  504. X/* char    sccsid[] = "@(#)nbatcher.c 1.4 8/14/86"; */
  505. X
  506. X/****************************************************
  507. X *
  508. X *    nbatcher.c - where it really happens.
  509. X *
  510. X *    R.J. Esposito
  511. X *    Bell of Penna.
  512. X *    June 1986
  513. X *
  514. X ***************************************************/
  515. X
  516. X#include <stdio.h>
  517. X#include <sys/types.h>
  518. X#include <sys/stat.h>
  519. X#include <time.h>
  520. X#include "nbatcher.h"
  521. X
  522. Xbatch_it ()
  523. X{
  524. X    struct stat    st;
  525. X    FILE    *bfp, *afp;
  526. X    char    fbuf[BUFSIZ], lckfile[40];
  527. X    char    tbuf[80];
  528. X    short    count;
  529. X    int    c;
  530. X
  531. X    if (chdir(BATCHDIR) < 0)
  532. X        xerror ("can't chdir to %s\n", BATCHDIR);
  533. X
  534. X    /* we create a lock file for two purposes,
  535. X       first to make sure a previous nbatcher
  536. X       didn't blowup and leave the lock file
  537. X       laying around, and second to put the
  538. X       remaining news article filenames when
  539. X       we go over the max UUCP bytes and there's
  540. X       still files remaining for batching.
  541. X    */
  542. X
  543. X    sprintf (lckfile, ".%s.lock", ep.site);
  544. X    if (!access(lckfile, 0))
  545. X        xerror ("lockfile already exists for %s\n", ep.site);
  546. X
  547. X    if ((lfp=fopen(lckfile, "w")) == NULL)
  548. X        xerror ("can't create lockfile for %s\n", ep.site);
  549. X
  550. X    /* now that we've locked ourselves for this site,
  551. X       lets carry on */
  552. X
  553. X    if ((bfp=fopen(ep.site, "r")) == NULL)
  554. X        xerror ("can't open %s/%s for reading\n", BATCHDIR, ep.site);
  555. X
  556. X    if (tfile == NULL) {
  557. X        tfile = mktemp("/tmp/bnewsXXXXXX");
  558. X        if ((tfp=fopen(tfile, "w")) == NULL)
  559. X            xerror ("can't open %s for writing\n", tfile);
  560. X    }
  561. X
  562. X    count = fcnt = scnt = 0;
  563. X    cu_bytes = 0;
  564. X    while ((fgets(fbuf, sizeof(fbuf), bfp)) != NULL) {
  565. X        fbuf[strlen(fbuf)-1] = '\0';    /* remove the newline */
  566. X        if ((afp=fopen(fbuf, "r")) == NULL) {
  567. X           fprintf (stderr, "\nbypassing article %s: can't read it\n",
  568. X                fbuf);
  569. X            continue;
  570. X        }
  571. X        if (fstat(fileno(afp), &st) < 0)
  572. X            xerror ("fstat failed on %s\n", fbuf);
  573. X
  574. X        cu_bytes += st.st_size;
  575. X
  576. X        /* if the max byte count is exceeded,
  577. X           save the remaining files for later */
  578. X
  579. X        if ((cu_bytes + n_bytes) > ep.m_bytes) {
  580. X            fprintf (lfp, "%s\n", fbuf); /* put the '\n' back */
  581. X            while ((fgets(fbuf, sizeof(fbuf), bfp)) != NULL)
  582. X                fputs (fbuf, lfp);
  583. X            fclose (bfp);
  584. X            fclose (lfp);
  585. X            fclose (afp);
  586. X            unlink (ep.site);
  587. X            if (link(lckfile, ep.site) < 0)
  588. X               xerror ("can't link lockfile to %s\n", ep.site);
  589. X            unlink (lckfile);
  590. X            chown (ep.site, NEWSUID, NEWSGID);
  591. X            if (count)
  592. X                spoolit ();
  593. X            if (cu_bytes - st.st_size)
  594. X                log_it (cu_bytes - st.st_size);
  595. X
  596. X            return;
  597. X        }
  598. X        sprintf (tbuf, "#! rnews %ld\n", st.st_size);
  599. X        fputs (tbuf, tfp);
  600. X        while ((c=getc(afp)) != EOF)
  601. X            putc (c, tfp);
  602. X        fclose (afp);
  603. X
  604. X        if (++count == nfiles) {
  605. X            spoolit ();
  606. X            count = 0;
  607. X        }
  608. X        fcnt++;
  609. X    }
  610. X
  611. X    /* The final spool if lest than nfiles
  612. X       is encountered.  The zero out the
  613. X       batchfile and unlink the lock file */
  614. X
  615. X    spoolit ();
  616. X    fclose (bfp);
  617. X    fclose (lfp);
  618. X    close (creat(ep.site, 0664));
  619. X    chown (ep.site, NEWSUID, NEWSGID);
  620. X    unlink (lckfile);
  621. X
  622. X    /* here we log what we've done, and
  623. X       if vflg is set, a copy to stdout
  624. X       as well */
  625. X
  626. X    log_it (0);
  627. X    if (chdir(LIBDIR) < 0)
  628. X        xerror ("can't chdir back to %s\n", LIBDIR);
  629. X
  630. X}
  631. X
  632. Xspoolit ()
  633. X{
  634. X    struct stat    st;
  635. X    char    cmd[BUFSIZ], cfile[80];
  636. X    FILE    *pfp;
  637. X    int    c;
  638. X
  639. X    fclose (tfp);
  640. X    stat (tfile, &st);
  641. X
  642. X    /* if for some reason the temp file
  643. X       is zero, just return */
  644. X
  645. X    if (st.st_size == 0)
  646. X        return;
  647. X
  648. X    /* if ep.c_bits is set use COMPRESS to compress
  649. X       the temp file first
  650. X    */
  651. X
  652. X    if (ep.c_bits) {
  653. X        sprintf (cmd, "%s -b%d %s", COMPRESS, ep.c_bits, tfile);
  654. X        if (system(cmd) != 0)
  655. X            xerror ("system(%s) failed\n", cmd);
  656. X
  657. X        strcpy (cfile, tfile);
  658. X        strcat (cfile, ".Z");
  659. X        if ((tfp=fopen(cfile, "r")) == NULL)
  660. X            xerror ("can't open %s for reading\n", cfile);
  661. X
  662. X        /* if ep.command has a specific command
  663. X           for UUCP spooling, use it.  If not,
  664. X           use UUX.
  665. X        */
  666. X
  667. X        if (ep.command[0] != '\0')
  668. X            strcpy (cmd, ep.command);
  669. X        else
  670. X            sprintf (cmd, "%s %s!rnews", UUX, ep.site);
  671. X
  672. X        /* now popen the command for writing
  673. X           and send it the contents of tempfile */
  674. X
  675. X        if ((pfp=popen(cmd, "w")) == NULL)
  676. X            xerror ("popen failed on %s\n", cmd);
  677. X
  678. X        /********************************************
  679. X         * for version 2.10.3 and above,
  680. X         * prepend `#! cunbatch'.
  681. X         *
  682. X         * NOTE: The remote site MUST be able to
  683. X         *       except this format, or it will
  684. X         *       be lost!!!
  685. X         *******************************************/
  686. X
  687. X        fputs ("#! cunbatch\n", pfp);
  688. X        while ((c=getc(tfp)) !=  EOF)
  689. X            putc (c, pfp);
  690. X
  691. X        pclose (pfp);
  692. X        fclose (tfp);
  693. X        unlink (cfile);
  694. X    } else {            /* regular batching here */
  695. X        if ((tfp=fopen(tfile, "r")) == NULL)
  696. X            xerror ("can't open %s for reading\n", tfile);
  697. X
  698. X        /* if ep.command has a specific command
  699. X           for UUCP spooling, use it.  If not,
  700. X           use UUX.
  701. X        */
  702. X
  703. X        if (ep.command[0] != '\0')
  704. X            strcpy (cmd, ep.command);
  705. X        else
  706. X            sprintf (cmd, "%s %s!rnews", UUX, ep.site);
  707. X
  708. X        if ((pfp=popen(cmd, "w")) == NULL)
  709. X            xerror ("popen failed on %s\n", cmd);
  710. X
  711. X        while ((c=getc(tfp)) != EOF)
  712. X            putc (c, pfp);
  713. X
  714. X        pclose (pfp);
  715. X        fclose (tfp);
  716. X    }
  717. X    if ((tfp=fopen(tfile, "w")) == NULL)
  718. X        xerror ("can't re-open %s\n", tfile);
  719. X
  720. X    scnt++;
  721. X}
  722. SHAR_EOF
  723. echo x - extracting logger.c
  724. sed 's/^X//' << 'SHAR_EOF' > logger.c
  725. X/* char    sccsid[] = "@(#)logger.c 1.4 8/14/86"; */
  726. X
  727. X/***************************************************
  728. X *
  729. X *    logger.c - log info about nbatcher
  730. X *
  731. X *    R.J. Esposito
  732. X *    Bell of Penna.
  733. X *    June 1986
  734. X *
  735. X **************************************************/
  736. X
  737. X#include <stdio.h>
  738. X#include <time.h>
  739. X#include "nbatcher.h"
  740. X
  741. Xlog_it (bytes)
  742. Xlong    bytes;
  743. X{
  744. X    struct tm    *localtime(), *tp;
  745. X    long    time(), clock;
  746. X    char    logfile[80], buf[BUFSIZ];
  747. X    char    pbuf[BUFSIZ];
  748. X
  749. X    sprintf (logfile, "%s/%s", LIBDIR, "nbatcher.log");
  750. X    if (log == NULL) {
  751. X        if ((log=fopen(logfile, "a")) == NULL)
  752. X           fprintf (stderr, "\ncan't append to logfile\n");
  753. X    }
  754. X
  755. X    if (log != NULL)
  756. X        rewind (log, 0L, 2);    /* just incase */
  757. X
  758. X    clock = time ((long *)0);
  759. X    tp = localtime (&clock);
  760. X    sprintf (buf, "%.2d/%.2d %.2d:%.2d %s: %d %s batched, %d %s queued\n",
  761. X       tp->tm_mon+1, tp->tm_mday, tp->tm_hour, tp->tm_min, ep.site,
  762. X       fcnt, (fcnt==1 ? "file" : "files"), scnt,
  763. X       (scnt==1 ? "file" : "files"));
  764. X
  765. X    if (bytes)
  766. X       sprintf (pbuf, "%s\tmax bytes reached.  UUCP bytes was %ld, byte count = %ld\n",
  767. X            buf, n_bytes, bytes);
  768. X    else
  769. X        sprintf (pbuf, "%s", buf);
  770. X
  771. X    if (vflg)
  772. X        fprintf (stdout, "%s",pbuf);
  773. X
  774. X    if (log != NULL)
  775. X        fputs (pbuf, log);
  776. X
  777. X}
  778. SHAR_EOF
  779. echo x - extracting nbatcher.h
  780. sed 's/^X//' << 'SHAR_EOF' > nbatcher.h
  781. X/* char    sccsid[] = "@(#)nbatcher.h 1.4 8/14/86"; */
  782. X
  783. X/******************************************************
  784. X *    nbatcher.h - defines for nbatcher source
  785. X *
  786. X *
  787. X *    R.J. Esposito
  788. X *    Bell of Penna.
  789. X *    June 1986
  790. X *
  791. X *****************************************************/
  792. X
  793. X/* things you might want to change */
  794. X
  795. X#define UUCPDIR        "/usr/spool/uucp"    /* uucp spool directory */
  796. X#define COMPRESS    "/usr/bin/compress -F -q" /* where compress resides */
  797. X#define UUX        "/usr/bin/uux - -r"    /* default command */
  798. X#define DFL_BYTES    100000L            /* default max. UUCP bytes */
  799. X#define NEWSUID        47            /* USENET used id */
  800. X#define NEWSGID        80            /* USENET group id */
  801. X
  802. X/* things you shouldn't change */
  803. X
  804. X#define FALSE        0
  805. X#define TRUE        1
  806. X#define COLON        ':'
  807. X
  808. Xstruct file_entry {        /* structure of control file */
  809. X    char    site[30];    /* name of remote site */
  810. X    char    hour[80];    /* string for hour to batch */
  811. X    short    c_bits;        /* # of compression bits */
  812. X    long    m_bytes;    /* max. # of bytes on UUCP queue */
  813. X    char    command[128];    /* command string */
  814. X} ep;
  815. X
  816. Xextern FILE    *lfp,            /* lockfile pointer */
  817. X        *tfp,            /* tempfile pointer */
  818. X        *log;            /* logfile pointer */
  819. X
  820. Xextern long    n_bytes;        /* # of bytes already on UUCP queue */
  821. Xextern long    cu_bytes;        /* cumculative bytes of batch files */
  822. X
  823. Xchar    *mktemp(),
  824. X    *strcpy(),
  825. X    *strcat();
  826. X
  827. Xextern char    *tfile;            /* temp file */
  828. X
  829. Xextern short    vflg,            /* verbose flag */
  830. X        nfiles;            /* number of news articles per
  831. X                       UUCP batch file */
  832. X
  833. Xint    system();
  834. X
  835. Xextern int    fcnt,            /* number of files batched */
  836. X        scnt;            /* spool count */
  837. SHAR_EOF
  838. echo x - extracting bst.c
  839. sed 's/^X//' << 'SHAR_EOF' > bst.c
  840. X/* char    sccsid[] = "@(#)bst.c 1.4 8/14/86"; */
  841. X
  842. X/****************************************************************
  843. X *    bst.c - a utility for indicating how many
  844. X *        news articles are ready for batching
  845. X *        for each site in the BACTHDIR directory.
  846. X *
  847. X *    R.J. Esposito
  848. X *    Bell of Penna.
  849. X *    June 1986
  850. X *
  851. X ****************************************************************/
  852. X
  853. X#include <stdio.h>
  854. X#include <sys/types.h>
  855. X#include <sys/stat.h>
  856. X#include <sys/dir.h>
  857. X
  858. X
  859. Xchar buf[512];
  860. XFILE *dd;
  861. Xstruct direct dp;
  862. Xstruct stat st;
  863. X
  864. Xmain()
  865. X{
  866. X    int fd, j;
  867. X    int bcnt, lcnt;
  868. X
  869. X    if(chdir(BATCHDIR) != 0) {
  870. X        perror(BATCHDIR);
  871. X        exit(1);
  872. X    }
  873. X
  874. X    if((dd=fopen(".", "r")) == NULL) {
  875. X        printf("can't open %s\n", BATCHDIR);
  876. X        exit(1);
  877. X    }
  878. X
  879. X    while((fread((char *)&dp, sizeof(dp), 1, dd)) == 1) {
  880. X        if(dp.d_ino == 0 || dp.d_name[0] == '.')
  881. X            continue;
  882. X        if(stat(dp.d_name, &st) != 0) {
  883. X            printf("can't stat %s\n", dp.d_name);
  884. X            exit(1);
  885. X        }
  886. X        if(st.st_size <= 0 )
  887. X            continue;
  888. X        if((fd=open(dp.d_name, 0)) < 0) {
  889. X            printf("can't open %s\n", dp.d_name);
  890. X            exit(1);
  891. X        }
  892. X        lcnt = 0;
  893. X        while((bcnt=read(fd,buf,512)) > 0) {
  894. X            for(j=0; j<=bcnt; j++)
  895. X                if(buf[j] == '\n')
  896. X                    lcnt += 1;
  897. X        }
  898. X        close(fd);
  899. X        printf("%s\t  %d article", dp.d_name, lcnt);
  900. X        printf("%c\n", lcnt > 1 ? 's' : ' ');
  901. X    }
  902. X}
  903. SHAR_EOF
  904. echo x - extracting README
  905. sed 's/^X//' << 'SHAR_EOF' > README
  906. XThe program provides a better way to handling batching of USENET news
  907. Xto neighboring sites.  IT works with 2.10B and later, including
  908. X2.10.3B, which provides compression batching.
  909. X
  910. XPlease send any questions and bug reports to me (bpa!espo) for
  911. Xdistribution to the net.  This software is public domain, and cannot be
  912. Xsold for any profit.
  913. X
  914. XNbatcher was written for UNIX (trademark of AT&T) System V, but should
  915. Xbe compatible with most version currently being used today.  It is
  916. Xpresently running on a VAX (trademark of DEC) 11/780 feeding 5 remote
  917. Xsites with news.  Two important issues MUST be noted here.
  918. X
  919. XSince nbatcher checks the UUCP directory for each site listed in the
  920. Xcontrol file, directory configuration should be UUCPDIR/sitename, e.g.
  921. X/usr/spool/uucp/foo for site foo.  But since not everyone is generic,
  922. XI've allowed nbatcher to skip over the UUCP byte counting routine if
  923. Xthis is not so.  In addition to this, some uucpcleanup daemons remove
  924. Xthe site directory if there's nothing spooled there.  When this
  925. Xhappens, nbatcher will notify you of this and continue on.
  926. X
  927. XThe other issue is that you MUST configure your NEWSLIB/sys file using the
  928. Xbatch syntax as described in the USENET Installation document.  Field 3
  929. Xshould contain the `F' flag indicating a batched transmission for that
  930. Xsite and field 4 should contain the filename where news article's full
  931. Xpathname will be appended to.  Nbatcher requires that the filename in
  932. Xfield 4 match the sitename in the control file.  For example, the entry:
  933. X    foo:net,mod,usa,na,to.foo:F:/usr/spool/batchnews/foo
  934. Xsays that all news articles going to site `foo' will be batched, using
  935. Xthe file `foo' in /usr/spool/batchnews.  Nbatcher's control file entry:
  936. X    foo:3,14,22:16:150000:
  937. Xwill get the news article's full pathname from /usr/spool/batchnews/foo
  938. Xfor batching.  This requirement MUST be adhered to for nbatcher to work
  939. Xcorrectly.  I believe most sites that batch news use this type of
  940. Xconfiguration, since its easy to keep track of a remote site's work.
  941. XNote that the name of the directory "/usr/spool/batchnews" is set
  942. Xin the Makefile.
  943. X
  944. XThe manual page describes the control file, as does nbatcher.doc.  Note
  945. Xthat even though nbatcher indicates max bytes has been reached, if that
  946. Xsite gets compressed batches, the next time nbatcher runs for that site
  947. Xwork could get scheduled.
  948. X
  949. XAlso included is a utility program called "bst," BatchSTatus, which
  950. Xshows who many news articles are currently in the batch file for each
  951. Xsystem.  Just type "make bst" for that and copy it to where you want,
  952. Xusually LIBDIR.  Note that bst does reads on the directory structure
  953. Xdirectly.
  954. X
  955. XInstallation is simple:  look at the first few #define's in nbatcher.h;
  956. Xalso edit the Makefile for the appropriate BATCHDIR and LIBDIR for your
  957. Xsite.  Type "make" or "make install."
  958. X
  959. XNOTE:  Read the comments in parse.c concerning MAX_BYTES.  This is the
  960. Xmaximum amount of bytes per site that's allowed in the control file for
  961. Xm_bytes.  Change it at your own risk!
  962. X
  963. X    Bob Esposito   bpa!espo
  964. X    Bell of Penna.
  965. SHAR_EOF
  966. echo x - extracting nbatcher.ctl
  967. sed 's/^X//' << 'SHAR_EOF' > nbatcher.ctl
  968. X*
  969. X*    NBATCHER.CTL
  970. X*    Edit and install in your NEWSLIB directory.
  971. X*
  972. X*  Comments start with *; data lines look like:
  973. X*    site:hours:bits:queue_size:command
  974. X*  Where
  975. X*    site        = name of the remote site
  976. X*    hour        = when to do work (* is all, off is never, 22-4 is ok)
  977. X*    bits        = passed on to compress via -b; null gets default
  978. X*    queue_size    = Max # bytes allowed in UUCP queue before postponing
  979. X*    command        = optional command line
  980. X*
  981. X*  See manpage and README for more info.
  982. SHAR_EOF
  983. echo x - extracting nbatcher.doc
  984. sed 's/^X//' << 'SHAR_EOF' > nbatcher.doc
  985. X
  986. XDETAILED DESCRIPTION OF nbatcher.ctl FILE
  987. X
  988. X               Document for nbatcher
  989. X
  990. XAs distributed, the nbatcher.ctl contains a terse summary of its
  991. Xformat.  For each site you feed news to, providing that site uses the
  992. X":F:BATCHDIR/site" batching syntax in the sys file, a corresponding
  993. Xentry should exist in nbatcher.ctl  Each line is a five-field,
  994. Xcolon-separated entry indicating what to do for that site.
  995. X
  996. XThe format is:
  997. X    site:hour:c_bits:m_bytes:command
  998. XThe site field is the name of the UUCP site that will get the batched
  999. Xnews.  There MUST be a file in the BATCHDIR (in my case
  1000. X/usr/spool/batchnews) matching this name that contains a listing of
  1001. Xfiles to batch.  This is where rnews puts the news article filenames
  1002. Xwhen batching is used.  Nbatcher will complain about mismatches.
  1003. X
  1004. XNext is the hour field.  The syntax directly imitates the crontab entry
  1005. Xfor hour.  If hour = "*", than assume a match for every hour.  If hour
  1006. X= "off", then no work will ever be spooled for this site.  (This is the
  1007. Xonly difference from crontab).  You can specify a specific hour, like 8
  1008. Xor 09 or 22.  Or a range of hours, like 10-15, meaning check for work
  1009. Xfrom 10 AM thru 3 PM.  (you can also cycle thru a 24 hr. period by
  1010. Xsaying 22-4, which will assume a match for 10PM thru 4AM).  Also, hours
  1011. Xcomma separated like 7,14,21, says check for work at 7 AM, 4PM and 9PM
  1012. Xonly.  This gives lots of flexibility for sites that feed multiple
  1013. Xremotes.
  1014. X
  1015. XNext is the c_bits field, which has a value of 9-16, or may be left
  1016. Xblank.  If non-null, this field is directly passed on to compress with
  1017. Xthe -b flag.  If it is null, then no compression is done for this
  1018. Xsite.
  1019. X
  1020. XThe m_bytes field is the maximum number of bytes allowed on the UUCP
  1021. Xqueue at any time.  It defaults to 100K bytes, and if its greater than
  1022. X1MB (see parse.c about MAX_BYTES), than it uses 1MB as the default
  1023. Xnumber of bytes.
  1024. X
  1025. XWhat nbatcher does is first check the UUCPDIR for that site and sums up
  1026. Xthe number of bytes already on-queue.  The size of each news article is
  1027. Xaccumulated prior to batching to the tempfile, and this accumulation +
  1028. Xthe UUCP on-queue bytes are checked to see if they surpass the m_bytes
  1029. Xvalue.  If not, things proceed normally.  But if it would exceed the
  1030. Xmax value, then spool whats already been batched, and save the
  1031. Xremainder of the articles for the next scheduled batch.
  1032. X
  1033. XThis is so noted in the nbatcher.log file, showing the UUCP bytes that
  1034. Xwere on-queue (if any), and the number of bytes that were spooled.
  1035. XAlso, if nbatcher is run from a terminal instead of from cron, a copy
  1036. Xof what gets logged is sent to the terminal.
  1037. X
  1038. XThe last field is the command field.  This optional field is used for
  1039. Xspecific UUCP command execution.  As written, it defaults to "uux - -r
  1040. Xsite!rnews".  Since my uux doesn't require the -z option for rnews, I
  1041. Xleft it out of the UUX define in nbatcher.h  This can easily be changed
  1042. Xfor your own taste, or just use the command field.
  1043. X
  1044. XExample:
  1045. X    site-A:3,10:16:450000:
  1046. XCheck for work for site-A at 3AM and 10AM.  Use compress with
  1047. X16 bits and only spool up to 450K bytes, using "uux - -r site-A!rnews".
  1048. X
  1049. XAnother example:
  1050. X    foo:23-4::300000:uux - -r -z foo!rnews
  1051. XCheck for work for foo between 11PM and 4AM.  No compression is used
  1052. Xand spool up to 300K bytes using the command field.
  1053. X
  1054. XThis format should help ease UUCP congestion on the local site for
  1055. Xnews.  I currently feed 5 remote sites, compressed and non-compressed
  1056. Xformats, and have noticed a vast improvement in disk space as well as
  1057. Xout port availability for UUCP.  It has allowed me to check for work
  1058. Xfor all sites every hour, since there's a limit on how much gets
  1059. Xqueued.  And if the remote doesn't answer on the hourly UUCP poll, so
  1060. Xwhat!!  Nbatcher just won't spool any more until the m_bytes limit
  1061. Xon-queue is reduced.
  1062. X
  1063. XThe best results is to run nbatcher, via cron as the USENET
  1064. Xadministrator (NEWSUID), at least once per hour.
  1065. X
  1066. XNbatcher was designed to weed out any illegal syntax in the control
  1067. Xfile, but its not bug-proof, so use some discretion.
  1068. X
  1069. XBob Esposito
  1070. XBell of Penna.
  1071. XJune 1986
  1072. SHAR_EOF
  1073. echo x - extracting nbatcher.1
  1074. sed 's/^X//' << 'SHAR_EOF' > nbatcher.1
  1075. X.TH NBATCHER 1 LOCAL
  1076. X.SH NAME
  1077. Xnbatcher  \- new batching system for news
  1078. X.SH SYNOPSIS
  1079. X.B nbatcher
  1080. X.IR "(run out of " cron ".)"
  1081. X.SH DESCRIPTION
  1082. X.PP
  1083. X.I Nbatcher
  1084. Xis a program designed to send batched USENET data out
  1085. Xin an orderly and controlled fashion, while providing alternative
  1086. Xtransmission methods.  As such, it is a replacement for
  1087. X.I csendbatch
  1088. Xand the like, which typically require many entries in
  1089. X.IR crontab .
  1090. X.I Nbatcher
  1091. Xis intended to be run hourly out of
  1092. X.I cron
  1093. Xas the USENET administrator (NEWSID).
  1094. X.PP
  1095. X.I Nbatcher
  1096. Xscans the file
  1097. X.I nbatcher.ctl
  1098. Xin the NEWSLIB directory to determine if work should be spooled
  1099. Xfor a system.  In the control file, lines starting with asterisks
  1100. Xare ignored; data lines are comprised of five colon\-separated
  1101. Xfields:
  1102. X.RS
  1103. Xsite:hour:bits:queue_size:command
  1104. X.RE
  1105. X.TP
  1106. XThe ``site'' field is the USENET neighbor; it is the same as the site in the
  1107. Xnews
  1108. X.I sys
  1109. Xfile.
  1110. X.TP
  1111. XThe ``hours'' field is patterned after
  1112. X.IR cron's.
  1113. XIf the hour is ``off,'' no work is spooled for the site.  An hour of
  1114. X``*'' matches every hour.  It is also possible to specify specific
  1115. Xhours, (e.g., 8, 09, or 22), a comma-separated list (e.g., 8,09,22),
  1116. Xor a twenty\-four range, like 10-\15 for 10am through 3pm and 22\-4,
  1117. Xfor 10pm through 4am.
  1118. X.TP
  1119. XThe ``bits'' field specifies the number of bits to use in compression;
  1120. Xit should be a number between nine and 16, inclusive, or null.  If
  1121. Xa number is specified, it is passed on to the
  1122. X.I compress
  1123. Xprogram via the ``\-b'' flag.
  1124. X.TP
  1125. XThe ``queue_size'' field specifies the maximum number of bytes allowed
  1126. Xin the UUCP queue for this site.  The default is 100K.
  1127. XThe UUCP queue size is determined by lookin in the
  1128. X.IR /usr/spool/uucp/ site
  1129. Xdirectory; if it doesn't exist, the check is bypassed.  If there is
  1130. Xdata in the UUCP queue,
  1131. X.I nbatcher
  1132. Xwill only queue up as many USENET transfers as will fit within the limit
  1133. Xspecified by the ``queue_size'' field.
  1134. X.TP
  1135. XThe ``command'' field is used to specific the UUCP command that should
  1136. Xbe used to queue the job; the default is ``uux \- \-r site!rnews'';
  1137. Xnote the absence of the ``\-z'' flag.
  1138. X.PP
  1139. XTo set up a USENET neighbor to be controlled by nbatcher, the news
  1140. X.I sys
  1141. Xentry for the neighbor must be modified to specify the ``F'' flag,
  1142. Xand the file used to contain the article names must be
  1143. X.RI BATCHDIR/sysname ,
  1144. Xwhere BATCHDIR is set in the Makefile as distributed.
  1145. X.SH "FILES"
  1146. XNEWSLIB/nbatcher.log
  1147. X.br
  1148. X.in +1i
  1149. Xa logfile of failures, postponements, etc.
  1150. X.in -1i
  1151. X.SH BUGS
  1152. XParsing of the control file is fairly robust, but not perfect.
  1153. SHAR_EOF
  1154. echo x - extracting Makefile
  1155. sed 's/^X//' << 'SHAR_EOF' > Makefile
  1156. X#
  1157. X#    Makefile for nbatcher Version 1.4
  1158. X#
  1159. X#    R.J. Esposito
  1160. X#    Bell of Penna.
  1161. X#    June 1986
  1162. X#
  1163. X
  1164. X#    You MUST define BATCHDIR as the place where USENET
  1165. X#    puts the articles to be batched.
  1166. X#
  1167. X#    LIBDIR is where you USENET library is and also
  1168. X#    MUST be defined.
  1169. X#
  1170. X#    Define PCODE for parse.c if you don't have/can't use
  1171. X#    _doprnt.
  1172. X
  1173. XBATCHDIR = /usr/spool/batchnews
  1174. XLIBDIR = /misc/lib/usenet
  1175. X
  1176. XCFLAGS = -O -c
  1177. XLFLAGS = -s
  1178. XDFLAGS = -DBATCHDIR='"$(BATCHDIR)"' -DLIBDIR='"$(LIBDIR)"'
  1179. X# PCODE = -DUSE_PORT_CODE
  1180. X
  1181. XOBJS = define.o main.o parse.o checkwork.o nbatcher.o logger.o
  1182. X
  1183. XSRC = define.c main.c parse.c checkwork.c nbatcher.c logger.c nbatcher.h bst.c
  1184. XDOCS = README nbatcher.ctl nbatcher.doc nbatcher.1
  1185. X
  1186. Xall: $(OBJS)
  1187. X    $(CC) $(DFLAGS) $(LFLAGS) -o nbatcher $(OBJS)
  1188. X    chmod 0755 nbatcher
  1189. X
  1190. Xinstall: all
  1191. X    cp nbatcher $(LIBDIR)
  1192. X    chmod 0755 $(LIBDIR)/nbatcher
  1193. X    cp nbatcher.ctl $(LIBDIR)/nbatcher.ctl
  1194. X    chmod 0644 $(LIBDIR)/nbatcher.ctl
  1195. X
  1196. Xdefine.o: nbatcher.h define.c
  1197. X    $(CC) $(CFLAGS) $(DFLAGS) define.c
  1198. X
  1199. Xmain.o: nbatcher.h main.c
  1200. X    $(CC) $(CFLAGS) $(DFLAGS) main.c
  1201. X
  1202. Xparse.o: nbatcher.h parse.c
  1203. X    $(CC) $(CFLAGS) $(DFLAGS) $(PCODE) parse.c
  1204. X
  1205. Xcheckwork.o: nbatcher.h checkwork.c
  1206. X    $(CC) $(CFLAGS) $(DFLAGS) checkwork.c
  1207. X
  1208. Xnbatcher.o: nbatcher.h nbatcher.c
  1209. X    $(CC) $(CFLAGS) $(DFLAGS) nbatcher.c
  1210. X
  1211. Xlogger.o: nbatcher.h logger.c
  1212. X    $(CC) $(CFLAGS) $(DFLAGS) logger.c
  1213. X
  1214. Xbst: bst.c
  1215. X    $(CC) $(CFLAGS) $(DFLAGS) bst.c
  1216. X    $(CC) $(LFLAGS) -o bst bst.o
  1217. X
  1218. Xclean:
  1219. X    rm -f *.o *.shar
  1220. X
  1221. Xclobber: clean
  1222. X    rm -f nbatcher
  1223. X
  1224. X
  1225. Xshar:
  1226. X    shar -v $(SRC) $(DOCS) Makefile > nbatcher.shar
  1227. SHAR_EOF
  1228. exit
  1229.  
  1230.