home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume6 / getpaths < prev    next >
Text File  |  1986-11-30  |  19KB  |  638 lines

  1. /* Written  3:39 pm  Jun 19, 1986 by sources-request@mirror.UUCP in mirror:mod.sources */
  2. /* ---------- "v06i009:  Tools for analyzing netne" ---------- */
  3. Submitted by: talcott!seismo!epiwrl!epimass!jbuck
  4. Mod.sources: Volume 6, Issue 9
  5. Archive-name: getpaths
  6.  
  7. [ I had to reformat the AWK script in histog, strangely enough;
  8.   otherwise AWK crashed.  My version is in the file histog.mod
  9.     --r$ ]
  10.  
  11. # This is a shell archive.  Remove anything before this line,
  12. # then unpack it by saving it in a file and typing "sh file".
  13. # Contents:  6sites README backbone-list closure getopt.c getpaths.1 getpaths.c
  14. #    histog histog.mod hostcount makefile makefile.42 makefile.sysv
  15. #    makefile.v7 oscantree.c scantree.c threelink twolink
  16.  
  17. echo x - 6sites
  18. sed 's/^XX//' > "6sites" <<'@//E*O*F 6sites//'
  19. XXBACKBONE!decvax!seismo!ihnp4!tektronix!sdcrdcf!decwrl
  20. @//E*O*F 6sites//
  21. chmod u=rw,g=rw,o=rw 6sites
  22.  
  23. echo x - README
  24. sed 's/^XX//' > "README" <<'@//E*O*F README//'
  25. XX        A Collection of Usenet path-counting tools
  26. XX        Joseph T. Buck - Entropic Processing, Inc.
  27.  
  28. XXThis is a set of tools for computing statistics on the Usenet paths
  29. XXon your machine.
  30.  
  31. XXThe program 'getpaths' gathers paths from your news spool, taking cross
  32. XXpostings into account (each path appears in the output once).
  33. XXSee the man page supplied.
  34.  
  35. XXThere are three makefiles provided; I hope getpaths can be made to
  36. XXrun on anything.  Use makefile.42 for 4.2bsd or 4.3bsd; makefile.sysv
  37. XXfor System III or System V; use makefile.v7 for Version 7 or 4.1bsd.
  38.  
  39. XXIf you have trouble, there are three questions you have to answer:
  40.  
  41. XX    1) Do you have the 4.2 directory access library?  If so, use
  42. XX       scantree.c, otherwise use oscantree.c.
  43.  
  44. XX    2) v7 and bsd systems have functions "index" and "rindex".
  45. XX       SysIII and SysV changed the names to strchr and strrchr,
  46. XX       for no good reason.  See the definition of CFLAGS in
  47. XX       makefile.sysv.
  48.  
  49. XX    3) Do you have getopt? (SysIII,V do, bsd, v7 don't).  I'm
  50. XX       including Henry Spencer's public domain version, since
  51. XX       it's short and valuable and Berkeley folks can't run the
  52. XX       program without it.
  53.  
  54. XXYou may find the scantree functions useful in other programs.  You're
  55. XXwelcome to them, but leave my name in, please.
  56.  
  57. XXWith no options, getpaths prints the paths in every article on the standard
  58. XXoutput.  If you expire news after one week, this will result in about 300 Kbytes
  59. XXof output.  To restrict yourself to a subtree, you may give an option, which
  60. XXis a pathname that uses /usr/spool/news as a base.
  61.  
  62. XX    getpaths mod
  63. XX    getpaths net/politics
  64.  
  65. XXOnce you've used getpaths to gather some paths, you can use the shell scripts
  66. XXto compute some statistics on them:
  67.  
  68. XXhistog -
  69. XX    Computes the average path length and prints a histogram.
  70. XXhostcount -
  71. XX    Counts hostnames that occur anywhere in a path and prints them
  72. XX    in declining order of frequency.
  73. XXtwolink -
  74. XX    Prints connected pairs of sites in declining order of frequency.
  75. XX    I used twolink to prepare my most recent map.
  76. XXthreelink -
  77. XX    Prints connected triplets of sites in declining order of frequency.
  78.  
  79. XXFinally, there is "closure", which will give "awk" a good workout on your
  80. XXsystem.  It is an automated version of the procedure that I used to build
  81. XXan extended backbone map.
  82.  
  83. XXclosure takes three arguments.  The first argument is the name of a
  84. XXfile containing the "core" sites you wish to start with (you can
  85. XXthink of these as "backbone" sites, but I'm not claiming to define what
  86. XX"backbone" really means).
  87.  
  88. XXThe file must be in a somewhat peculiar format; each line must begin
  89. XXwith the word BACKBONE (in caps), followed by the site names,
  90. XXseparated by !  marks.  For example, if you want to start with hosts
  91. XXalpha, beta, and gamma, the backbone file could be 
  92.  
  93. XXBACKBONE!alpha!beta!gamma
  94.  
  95. XXor
  96.  
  97. XXBACKBONE!alpha
  98. XXBACKBONE!beta
  99. XXBACKBONE!gamma
  100.  
  101. XXYes, it's ugly.
  102.  
  103. XXThe second argument is the name of the file containing a list of paths
  104. XX(as output by getpaths, perhaps).  Finally, the third argument, an
  105. XXinteger, is a threshold.
  106.  
  107. XXclosure searches the paths file for chains of paths that connect two
  108. XX"core" sites; a chain is disregarded unless it occurs at least
  109. XX"threshold" times, where "threshold" is the third argument.  Every
  110. XXsite in each such chain is added to the "core".  This is repeated
  111. XXuntil no more sites can be added to the "core".  A report of each
  112. XXiteration and what paths are added to the core is printed on the
  113. XXstandard output.
  114.  
  115. XXI've supplied two "initial cores" you can use; "6sites" includes
  116. XXihnp4, seismo, decvax, decwrl, tektronix, and sdcrdcf, and
  117. XX"backbone-list" contains all sites on Gene Spafford's backbone map.
  118.  
  119. XXTry the commands
  120.  
  121. XXgetpaths net > net.paths
  122. XXclosure 6sites net.paths 20
  123.  
  124. XXor
  125.  
  126. XXclosure backbone-list net.paths 20
  127.  
  128. XXI'm interested in seeing the results for sites far from the SF Bay
  129. XXArea.  You can write me at
  130.  
  131. XX        oliveb-\
  132. XX            \
  133. XX    ihnp4---pesnta--epimass!jbuck
  134. XX        /
  135. XX    hplabs-/
  136. @//E*O*F README//
  137. chmod u=rw,g=rw,o=rw README
  138.  
  139. echo x - backbone-list
  140. sed 's/^XX//' > "backbone-list" <<'@//E*O*F backbone-list//'
  141. XXBACKBONE!cbosgd!clyde!watmath!utzoo
  142. XXBACKBONE!ihnp4!cuae2!alberta!ubc-vision!burl!ulysses!bellcore
  143. XXBACKBONE!uw-beaver!tektronix!decvax!linus
  144. XXBACKBONE!qantel!hplabs!oliveb!glacier!decwrl
  145. XXBACKBONE!sdcrdcf!hao!sdcsvax!drillsys!gatech!akgua!mcnc!philabs
  146. XXBACKBONE!lll-lcc!lll-crg!cmcl2!seismo
  147. @//E*O*F backbone-list//
  148. chmod u=rw,g=rw,o=rw backbone-list
  149.  
  150. echo x - closure
  151. sed 's/^XX//' > "closure" <<'@//E*O*F closure//'
  152. XX#! /bin/sh
  153. XX# closure: Joseph T. Buck, Entropic Processing, Inc.
  154. XX# Usage: closure startfile paths thresh
  155. XX# This rather awk-ward script builds a "transitive closure" of a backbone.
  156. XXif test $# != 3
  157. XXthen echo Usage: $0 backbone-list paths threshold >&2; exit 1
  158. XXfi
  159. XX# The file /tmp/$$c contains the current backbone list; /tmp/$$a contains
  160. XX# The latest set of additions.
  161. XXcp $1 /tmp/$$c
  162. XXecho "------ Original backbone: ------"
  163. XXawk -F! '{ for (i=1; i<=NF; i++) if ($i != "BACKBONE") printf ("%s ",$i); }
  164. XXEND { printf ("\n");}' /tmp/$$c
  165. XXi=1
  166. XXwhile true
  167. XXdo
  168. XX   awk -F! '{
  169. XX    if ($1 == "BACKBONE") {
  170. XX    for (i = 2; i <= NF; i++)
  171. XX        backbone[$i] = 1;
  172. XX    }
  173. XX    else {
  174. XX    i = 1;
  175. XX    while (i <= NF && !backbone[$i])
  176. XX        i++;
  177. XX    if (i > NF)
  178. XX        next;
  179. XX    while (1) {
  180. XX        while (i <= NF && backbone[$i])
  181. XX        i++;
  182. XX        if (i > NF)
  183. XX        break;
  184. XX        first = i - 1;
  185. XX        while (i <= NF && !backbone[$i])
  186. XX        i++;
  187. XX        if (i > NF)
  188. XX        break;
  189. XX        for (j = first; j < i; j++)
  190. XX        printf ("%s!", $j);
  191. XX        printf ("%s\n", $i);
  192. XX    }
  193. XX    }
  194. XX}' /tmp/$$c $2 | sort | uniq -c |\
  195. XX   awk '{ if ($1 >= thr) printf("BACKBONE!%s\n", $2); }' thr=$3 - > /tmp/$$a
  196. XX   if test ! -s /tmp/$$a
  197. XX     then echo "------ Final backbone: ------"
  198. XX      awk -F! '{for (i=2; i<NF; i++) print $i}' /tmp/$$c | sort -u
  199. XX      rm /tmp/$$c /tmp/$$a
  200. XX      exit 0
  201. XX   fi
  202. XX   echo "------ Pass $i: add the following: ------"
  203. XX   awk -F! '{ for (i=2; i<NF; i++) printf("%s!", $i); printf("%s\n", $NF);}' /tmp/$$a
  204. XX   cat /tmp/$$a >> /tmp/$$c
  205. XX   i=`expr $i + 1`
  206. XXdone
  207.  
  208. @//E*O*F closure//
  209. chmod u=rwx,g=rwx,o=rwx closure
  210.  
  211. echo x - getopt.c
  212. sed 's/^XX//' > "getopt.c" <<'@//E*O*F getopt.c//'
  213. XX/*
  214. XX * getopt - get option letter from argv
  215. XX * by Henry Spencer
  216. XX * posted to Usenet net.sources list
  217. XX */
  218. XX#include <stdio.h>
  219.  
  220. XXchar    *optarg;    /* Global argument pointer. */
  221. XXint    optind = 0;    /* Global argv index. */
  222.  
  223. XXstatic char    *scan = NULL;    /* Private scan pointer. */
  224.  
  225. XXextern char    *index();
  226.  
  227. XXint
  228. XXgetopt (argc, argv, optstring)
  229. XXint     argc;
  230. XXchar   *argv[];
  231. XXchar   *optstring;
  232. XX{
  233. XX    register char   c;
  234. XX    register char  *place;
  235.  
  236. XX    optarg = NULL;
  237.  
  238. XX    if (scan == NULL || *scan == '\0') {
  239. XX    if (optind == 0)
  240. XX        optind++;
  241.  
  242. XX    if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
  243. XX        return (EOF);
  244. XX    if (strcmp (argv[optind], "--") == 0) {
  245. XX        optind++;
  246. XX        return (EOF);
  247. XX    }
  248. XX    scan = argv[optind] + 1;
  249. XX    optind++;
  250. XX    }
  251. XX    c = *scan++;
  252. XX    place = index (optstring, c);
  253.  
  254. XX    if (place == NULL || c == ':') {
  255. XX    fprintf (stderr, "%s: unknown option -%c\n", argv[0], c);
  256. XX    return ('?');
  257. XX    }
  258. XX    place++;
  259. XX    if (*place == ':') {
  260. XX    if (*scan != '\0') {
  261. XX        optarg = scan;
  262. XX        scan = NULL;
  263. XX    }
  264. XX    else {
  265. XX        optarg = argv[optind];
  266. XX        optind++;
  267. XX    }
  268. XX    }
  269. XX    return (c);
  270. XX}
  271. @//E*O*F getopt.c//
  272. chmod u=rw,g=rw,o=rw getopt.c
  273.  
  274. echo x - getpaths.1
  275. sed 's/^XX//' > "getpaths.1" <<'@//E*O*F getpaths.1//'
  276. XX.TH GETPATHS LOCAL 6/2/86
  277. XX.SH NAME
  278. XXgetpaths \- gather Usenet article paths
  279. XX.SH SYNOPSIS
  280. XX.B getpaths
  281. XX[
  282. XX.BI \-n " file"
  283. XX] [
  284. XX.BI \-u
  285. XX] [
  286. XX.I distrib
  287. XX]
  288. XX.SH DESCRIPTION
  289. XX.PP
  290. XX.I Getpaths
  291. XXscans through the news spool and prints out all article paths.  Crossposted
  292. XXarticles have their paths printed only once.
  293. XX.PP
  294. XXBy default, usernames are removed from the paths.  If the
  295. XX.B \-u
  296. XXflag is given, usernames are left on.
  297. XX.PP
  298. XXThe
  299. XX.BI \-n " file"
  300. XXoption causes paths to be included only from articles that are newer
  301. XX(in terms of file modification time) than
  302. XX.IR file .
  303. XX.PP
  304. XXIf no argument is given, the entire news spool will be scanned.  The
  305. XX.I distrib
  306. XXargument is a relative path from /usr/spool/news.  For example,
  307. XX.PP
  308. XXgetpaths net
  309. XX.PP
  310. XXgets paths from net.*, and
  311. XX.PP
  312. XXgetpaths net/micro/atari
  313. XX.PP
  314. XXdoes what you think.
  315. XX.SH BUGS
  316. XXThe algorithm for eliminating crosspostings only prints a path if
  317. XXthe first newsgroup on the Newsgroups: line matches the directory currently
  318. XXbeing scanned.  So if you say "getpaths na", an article with the header
  319. XXline
  320. XX.PP
  321. XXNewsgroups: net.wanted,na.forsale
  322. XX.PP
  323. XXwill not have its path printed (though it will print if the groups are given
  324. XXin the reverse order).  In other words, the first group is always considered
  325. XXthe primary group, and other groups are always considered crossposts.
  326. XX.SH AUTHOR
  327. XXJoseph T. Buck, Entropic Processing, Inc.
  328. XX.br
  329. XX{pesnta,oliveb}!epimass!jbuck
  330. @//E*O*F getpaths.1//
  331. chmod u=rw,g=rw,o=rw getpaths.1
  332.  
  333. echo x - getpaths.c
  334. sed 's/^XX//' > "getpaths.c" <<'@//E*O*F getpaths.c//'
  335. XX/*
  336. XX    getpaths.c
  337. XX    Program to snarf up lots of Usenet paths
  338. XX    Joseph T. Buck, Entropic Processing, Inc.
  339. XX*/
  340. XX#define SPOOLDIR "/usr/spool/news"
  341. XX#include <stdio.h>
  342. XX#define LINLEN 512
  343. XXchar *strcpy();
  344.  
  345. XXint stripuser = 1;
  346.  
  347. XX/* This function assumes the current directory is SPOOLDIR, and that
  348. XX   the paths are of the form net/news/group/2345.
  349. XX*/
  350. XXvoid perror(), exit();
  351.  
  352. XXwp (name, ino)
  353. XXchar *name;
  354. XXint ino;
  355. XX{
  356. XX    int status = 0, lng;
  357. XX    char line[LINLEN], savpath[LINLEN];
  358. XX    FILE *fd;
  359. XX    char *p, *q, *rindex();
  360. XX    char curngr[40];    /* current newsgroup */
  361.  
  362. XX/* Figure out the current newsgroup, by deleting whatever is
  363. XX   after the last /, and changing '/' to '.'. Skip initial "./"
  364. XX   if present
  365. XX*/
  366. XX    if (name[0] == '.' && name[1] == '/') name += 2;
  367. XX    (void) strcpy (curngr, name);
  368. XX    p = rindex (curngr, '/');
  369. XX    if (p == NULL) return;
  370. XX    *p = 0;
  371. XX    while (p >= curngr) {
  372. XX    if (*p == '/') *p = '.';
  373. XX    p--;
  374. XX    }
  375. XX    lng = strlen (curngr);
  376. XX/* Open the file */
  377. XX    if ((fd = fopen (name, "r")) == NULL) {
  378. XX    perror (name);
  379. XX    return;
  380. XX    }
  381. XX    while (status != 3) {
  382. XX    if (fgets (line, LINLEN, fd) == NULL) break;
  383. XX    line[strlen(line)-1] = 0; /* delete \n */
  384. XX    if (strncmp (line, "Newsgroups:", 11) == 0) {
  385. XX        p = line + 11;
  386. XX        while (*p == ' ' || *p == '\t') p++;
  387. XX/* Detect cases like curngr == "net.micro", NG == "net.micro.pc,net.micro" */
  388. XX        if (p[lng] && p[lng] != ',' && p[lng] != ' ' && p[lng] != '\t')
  389. XX        break;
  390. XX        else if (strncmp (p, curngr, lng) != 0) break;
  391. XX        status |= 2;
  392. XX    }
  393. XX    else if (strncmp (line, "Path:", 5) == 0) {
  394. XX        p = line + 5;
  395. XX        while (*p == ' ' || *p == '\t') p++;
  396. XX/* Strip the username from the end of the path. Don't write anything
  397. XX   if there's no ! in the path (a locally posted article)
  398. XX*/
  399. XX        if (stripuser) {
  400. XX        q = rindex (line, '!');
  401. XX        if (q == NULL) break;
  402. XX        *q = '\0'; /* Delete the tail */
  403. XX        }
  404. XX        (void) strcpy (savpath, p);
  405. XX        status |= 1;
  406. XX    }
  407. XX    }
  408. XX    if (status == 3) (void) printf ("%s\n", savpath);
  409. XX    (void) fclose (fd);
  410. XX    return;
  411. XX}
  412.  
  413. XXmain (argc, argv)
  414. XXchar **argv;
  415. XX{
  416. XX    if (chdir (SPOOLDIR) != 0) {
  417. XX    (void) fprintf (stderr, "Can't chdir to ");
  418. XX    perror ("/usr/spool/news");
  419. XX    exit (1);
  420. XX    }
  421. XX    if (argc > 1 && strcmp (argv[1], "-u") == 0) {
  422. XX    stripuser = 0;
  423. XX    argv++;
  424. XX    argc--;
  425. XX    }
  426. XX    if (argc !=2) argv[1] = ".";
  427. XX    scan_tree (argv[1], wp);
  428. XX    return 0;
  429. XX}
  430.  
  431. XX#include <sys/types.h>
  432. XX#include <sys/stat.h>
  433.  
  434. XXis_dir (name)
  435. XXchar *name;
  436. XX{
  437. XX    struct stat sbuf;
  438. XX    return (stat (name, &sbuf) == 0 && (sbuf.st_mode & S_IFMT) == S_IFDIR);
  439. XX}
  440. @//E*O*F getpaths.c//
  441. chmod u=rw,g=rw,o=rw getpaths.c
  442.  
  443. echo x - histog
  444. sed 's/^XX//' > "histog" <<'@//E*O*F histog//'
  445. XX#! /bin/sh
  446. XXawk -F! '{ count[NF] += 1; if (NF > mx) mx = NF; sum += NF; }
  447. XXEND { printf ("Path length statistics\nAverage length: %f\nHistogram:\n",
  448. XX        sum / NR);
  449. XX      for (i = 1; i <= mx; i++) printf ("%d %d\n",i,count[i]); }'
  450. @//E*O*F histog//
  451. chmod u=rwx,g=rwx,o=rwx histog
  452.  
  453. echo x - histog.mod
  454. sed 's/^XX//' > "histog.mod" <<'@//E*O*F histog.mod//'
  455. XX#! /bin/sh
  456. XXawk -F! '{ count[NF] += 1; if (NF > mx) mx = NF; sum += NF; }
  457. XXEND {
  458. XX    printf "Path length statistics\nAverage length: %f\nHistogram:\n", sum / NR;
  459. XX    for (i = 1; i <= mx; i++) printf ("%d %d\n",i,count[i]);
  460. XX}'
  461. @//E*O*F histog.mod//
  462. chmod u=rwx,g=rwx,o=rwx histog.mod
  463.  
  464. echo x - hostcount
  465. sed 's/^XX//' > "hostcount" <<'@//E*O*F hostcount//'
  466. XX#! /bin/sh
  467. XX# This script takes a list of paths as input.
  468. XX# It prints a list of the sites encountered in the paths, sorted
  469. XX# according to their frequency.
  470. XXawk -F! '{ for (i = 1; i <= NF; i++) print $i }' $* |\
  471. XXsort | uniq -c | sort -nr
  472.  
  473.  
  474.  
  475. @//E*O*F hostcount//
  476. chmod u=rwx,g=rwx,o=rwx hostcount
  477.  
  478. echo x - makefile
  479. sed 's/^XX//' > "makefile" <<'@//E*O*F makefile//'
  480. XX# This makefile is appropriate for 4.2bsd.  For SysV or V7,
  481. XX# replace "scantree" by "oscantree" everywhere.
  482. XXCFLAGS = -O
  483. XX# Use the following for Sys V.
  484. XX# CFLAGS = -O -Dindex=strchr -Drindex=strrchr
  485.  
  486. XXgetpaths: getpaths.o scantree.o 
  487. XX    cc $(CFLAGS)  getpaths.o scantree.o  -o getpaths
  488. @//E*O*F makefile//
  489. chmod u=rw,g=rw,o=rw makefile
  490.  
  491. echo x - makefile.42
  492. sed 's/^XX//' > "makefile.42" <<'@//E*O*F makefile.42//'
  493. XX# This makefile is appropriate for 4.2bsd or 4.3bsd.
  494. XXCFLAGS = -O
  495.  
  496. XXgetpaths: getpaths.o scantree.o getopt.o
  497. XX    cc $(CFLAGS)  getpaths.o scantree.o getopt.o  -o getpaths
  498. @//E*O*F makefile.42//
  499. chmod u=rw,g=rw,o=rw makefile.42
  500.  
  501. echo x - makefile.sysv
  502. sed 's/^XX//' > "makefile.sysv" <<'@//E*O*F makefile.sysv//'
  503. XX# This makefile is appropriate for System III and System V.
  504. XXCFLAGS = -O -Dindex=strchr -Drindex=strrchr
  505.  
  506. XXgetpaths: getpaths.o oscantree.o 
  507. XX    cc $(CFLAGS)  getpaths.o oscantree.o  -o getpaths
  508. @//E*O*F makefile.sysv//
  509. chmod u=rw,g=rw,o=rw makefile.sysv
  510.  
  511. echo x - makefile.v7
  512. sed 's/^XX//' > "makefile.v7" <<'@//E*O*F makefile.v7//'
  513. XX# This makefile is appropriate for Version 7, or any system that
  514. XX# has neither getopt nor the 4.2 directory library.
  515.  
  516. XXCFLAGS = -O
  517.  
  518. XXgetpaths: getpaths.o oscantree.o 
  519. XX    cc $(CFLAGS)  getpaths.o oscantree.o  -o getpaths
  520. @//E*O*F makefile.v7//
  521. chmod u=rw,g=rw,o=rw makefile.v7
  522.  
  523. echo x - oscantree.c
  524. sed 's/^XX//' > "oscantree.c" <<'@//E*O*F oscantree.c//'
  525. XX/*
  526. XX   scan_tree: Joseph T. Buck, Entropic Processing, Inc.
  527. XX          Old-style version
  528.  
  529. XX   scan_tree applies a function to each file in a directory tree
  530. XX   (excluding directories), and returns the number of files processed.
  531. XX   This version reads directories directly and will not work with 4.2bsd.
  532. XX*/
  533. XX#include <sys/types.h>
  534. XX#include <sys/dir.h>
  535. XX#define MAXL 256
  536.  
  537.  
  538. XXscan_tree (path, func)
  539. XXchar *path;
  540. XXint (*func)();
  541. XX{
  542. XX    char name[MAXL], *strcpy(), *strncpy(), *pos;
  543. XX    struct direct dirent;
  544. XX    int fd = open (path), nf = 0, len;
  545.  
  546. XX    if (fd < 0) return 0;
  547. XX    
  548. XX    (void) strcpy (name, path);
  549. XX    len = strlen (path);
  550. XX    name[len] = '/';
  551. XX    pos = name + len + 1;
  552. XX    pos[DIRSIZ] = '\0'; /* req'd in case dirent has length DIRSIZ */
  553. XX    while (read (fd, (char *) &dirent, sizeof dirent) == sizeof dirent) {
  554. XX    if (dirent.d_ino == 0) continue;
  555. XX    (void) strncpy (pos, dirent.d_name, DIRSIZ);
  556. XX    if (strcmp (pos, ".") == 0 || strcmp (pos, "..") == 0) continue;
  557. XX    if (is_dir (name)) nf += scan_tree (name, func);
  558. XX    else {
  559. XX        (func) (name, dirent.d_ino);
  560. XX        nf += 1;
  561. XX    }
  562. XX    }
  563. XX    (void) close (fd);
  564. XX    return nf;
  565. XX}
  566. @//E*O*F oscantree.c//
  567. chmod u=rw,g=rw,o=rw oscantree.c
  568.  
  569. echo x - scantree.c
  570. sed 's/^XX//' > "scantree.c" <<'@//E*O*F scantree.c//'
  571. XX/*
  572. XX   scan_tree: Joseph T. Buck, Entropic Processing, Inc.
  573. XX          New-style version
  574.  
  575. XX   scan_tree applies a function to each file in a directory tree
  576. XX   (excluding directories), and returns the number of files processed.
  577. XX   This version uses the 4.2bsd directory access library; another version
  578. XX   that reads directories directly is available.
  579. XX*/
  580. XX#include <sys/types.h>
  581. XX#include <sys/dir.h>
  582. XX#define MAXL 256
  583. XXscan_tree (path, func)
  584. XXchar *path;
  585. XXint (*func)();
  586. XX{
  587. XX    char name[MAXL], *strcpy(), *pos;
  588. XX    DIR *dirp = opendir (path);
  589. XX    struct direct *de;
  590. XX    int nf = 0, len;
  591.  
  592. XX    if (dirp == NULL) return 0;
  593. XX    (void) strcpy (name, path);
  594. XX    len = strlen (path);
  595. XX    name[len] = '/';
  596. XX    pos = name + len + 1;
  597. XX    while ((de = readdir (dirp)) != NULL) {
  598. XX    if (strcmp (de->d_name, ".") == 0 || strcmp (de->d_name, "..") == 0)
  599. XX        continue;
  600. XX    (void) strcpy (pos, de->d_name); 
  601. XX    if (is_dir (name)) nf += scan_tree (name, func);
  602. XX    else {
  603. XX        (func) (name,de->d_ino);
  604. XX        nf += 1;
  605. XX    }
  606. XX    }
  607. XX    (void) closedir (dirp);
  608. XX    return nf;
  609. XX}
  610. @//E*O*F scantree.c//
  611. chmod u=rw,g=rw,o=rw scantree.c
  612.  
  613. echo x - threelink
  614. sed 's/^XX//' > "threelink" <<'@//E*O*F threelink//'
  615. XX#! /bin/sh
  616. XX# This script takes a list of paths as input.
  617. XXcat $* |\
  618. XXawk -F! '{ for (i=1; i<NF-1; i++) printf ("%s!%s!%s\n", $i,$(i+1),$(i+2)); }' |\
  619. XXsort | uniq -c | sort -nr
  620. @//E*O*F threelink//
  621. chmod u=rwx,g=rwx,o=rwx threelink
  622.  
  623. echo x - twolink
  624. sed 's/^XX//' > "twolink" <<'@//E*O*F twolink//'
  625. XX#! /bin/sh
  626. XX# This script takes a list of paths as input.
  627. XXcat $* |\
  628. XXawk -F! '{ for (i = 1; i < NF; i++) printf ("%s!%s\n", $i, $(i+1)); }' |\
  629. XXsort | uniq -c | sort -nr
  630.  
  631.  
  632.  
  633. @//E*O*F twolink//
  634. chmod u=rwx,g=rwx,o=rwx twolink
  635.  
  636. exit 0
  637. /* End of text from mirror:mod.sources */
  638.