home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume34 / fsp / part02 < prev    next >
Encoding:
Text File  |  1992-12-17  |  58.1 KB  |  1,949 lines

  1. Newsgroups: comp.sources.misc
  2. From: wen-king@vlsi.cs.caltech.edu (Wen-King Su)
  3. Subject:  v34i076:  fsp - Internet archive server and client software, Part02/04
  4. Message-ID: <1992Dec18.163934.11378@sparky.imd.sterling.com>
  5. X-Md4-Signature: 09ef8c343e26b31f2b4c05525e5007be
  6. Date: Fri, 18 Dec 1992 16:39:34 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: wen-king@vlsi.cs.caltech.edu (Wen-King Su)
  10. Posting-number: Volume 34, Issue 76
  11. Archive-name: fsp/part02
  12. Environment: UNIX, Sockets
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then feed it
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # Contents:  ChangeLog bsd_src/ls.c bsd_src/random.c client_lock.c
  19. #   client_util.c
  20. # Wrapped by kent@sparky on Fri Dec 18 10:21:24 1992
  21. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  22. echo If this archive is complete, you will see the following message:
  23. echo '          "shar: End of archive 2 (of 4)."'
  24. if test -f 'ChangeLog' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'ChangeLog'\"
  26. else
  27.   echo shar: Extracting \"'ChangeLog'\" \(12910 characters\)
  28.   sed "s/^X//" >'ChangeLog' <<'END_OF_FILE'
  29. XVersion 1.0 -- Dec 91.  Original source created.
  30. X
  31. XVersion 2.0 -- Dec 91.  Added man pages.  Server bug fix.  In 1.0, files
  32. X           in a directory that is protected from deletion can still
  33. X           be written over. In 2.0, it is prohibited as well. 
  34. X
  35. XVersion 2.1 --    Jan 1, 92.
  36. X
  37. X        1) The maximum length of a name in pre-2.1 server is
  38. X           both limited by the 1k-byte udp packet size and, in
  39. X           some cases more severely, by the OS it is running in.
  40. X           On some systems, the OS imposes a limite of 14 chars.
  41. X           For those systems, the server can now be made to hash
  42. X           long names into short ones.  The effect is transparent
  43. X           to the clients except when two long names gets hashed
  44. X           into the same value.  In that case, they will refer
  45. X           to the same file during downloading, and they will
  46. X           displace each others during uploading.
  47. X
  48. X        2) Since directories, unlike files, have undisputable
  49. X           ownership, removal of a directory owned by a client
  50. X           should depends only on the ownership of the directory
  51. X           itself, and not on that of its parent directory.  In
  52. X           pre-2.1 server, the client must have delete permission
  53. X           to the parent directory before it is allowed to delete
  54. X           the subdirectory.  In 2.1, the permission is not needed.
  55. X
  56. XVersion 2.2 --    Feb 15, 92.
  57. X
  58. X        1) The fput and fgetcmd utilities will now accept a list of
  59. X           files from its standward input.  See their man pages for
  60. X           this expanded usage.  This is useful if you don't want
  61. X           file names to show on 'ps' output.
  62. X
  63. X        2) The retransmit timer for client code has been changed
  64. X           to use an adaptive algorithm.  In pre-2.2 versions of
  65. X           FSP, clients will retransmit if it has not received a
  66. X           response from the server after a delay of 3 seconds.
  67. X           In version-2.2, two separate delays are used.  The
  68. X           "busy" delay is used when waiting for a reply for the
  69. X           first try and the second try.  Any time a second try
  70. X           is necessary, the delay is increased by 50%.  Every
  71. X           first try brings the delay 12.5% closer to the initial
  72. X           delay setting (3 seconds by default, settable by the
  73. X           FSP_DELAY variable).  For the third try and beyond,
  74. X           the "idle" delay is used.  For each try, the delay is
  75. X           doubled.
  76. X
  77. X        3) Makes available FSP request code space 0x80 - 0xff for
  78. X           future user extensions.  Each such extension will begin
  79. X           with a code byte in that range, and followed by a control
  80. X           block, which is likely to be different from the existing
  81. X           one.  The basic operations of FSP will not require the
  82. X           use of such extensions.
  83. X
  84. X        Note:  2.2 does not involve changes to the server itself.
  85. X               The server is been checked out and added to by a
  86. X               few people on the net.  I will wait until the
  87. X               modifications stabilize before I consolidate them.
  88. X
  89. XVersion 2.3 -- Mar 9, 92
  90. X
  91. X        1) The bsd_src/glob.c file has a bug in blkfree function
  92. X           in that it tries to free something that is actually
  93. X           on the stack of the glob function. The last call to
  94. X           free has been commented out to fix the bug. 
  95. X
  96. X        2) The fspd has a bug whoes only visible manifestation
  97. X           is the that protection can't be changed.  The fix has
  98. X           required a moderate amount of code change in fspd.
  99. X
  100. X        3) .FSP_NO_DEL and .FSP_NO_ADD mechanism has been replaced
  101. X           by .FSP_OK_DEL and .FSP_OK_ADD mechanism.  Thus by
  102. X           default, a directory is no delete and no add.
  103. X
  104. X        4) fprocmd is modified to relax option checking, allowing
  105. X           arbitrary option characters be passed to the fsp server.
  106. X
  107. X        5) A fls bug is fixed so that a "fls /" in a directory other
  108. X           than the root directory will not cause an error.
  109. X
  110. X        6) A -DDIRENT switch is added in Makefile to help support
  111. X           those machines that does not have /usr/include/dirent.h.
  112. X
  113. XVersion 2.3a -- March 20, 1992
  114. X
  115. X        1) In a few places, non-critical errors of the form:
  116. X               if(errno = EINTR) ....
  117. X           was made.  It obviously should have been == instead.
  118. X           The problem is fixed.
  119. X
  120. X        2) In the previous versions there is a potential problem
  121. X           such that if the first reply packet is dropped or is
  122. X           messed up, making a retransmit necessary, fspd will
  123. X           make the client utility wait for a 1 minute timeout.
  124. X           A potential loop hole for this happening has been
  125. X           closed by modifying server_lib.c where the packet key
  126. X           is checked. 
  127. X
  128. XVersion 2.4 -- March 27, 1992
  129. X
  130. X        1) fgrab/fgrabcmd client utility is added.  It is like
  131. X           fget except it also deletes the named files in such a
  132. X           way that if there are multiple fgrabs for the same
  133. X           file, only one will succeed. One bug/mis-feature of
  134. X           fgrab is that when fgrab is terminated abnormally, the
  135. X           file is not restored. This command is useful for things
  136. X           like sharing bone files for modified versions of nethack. 
  137. X
  138. X        2) FSP now allows multiple client programs to run at the
  139. X           same time if one of the three multiplexing mechanisms
  140. X           are chosen during compile time.  It is likely that at
  141. X           least one of them will work for your system.  The
  142. X           multiplexing is done at the client side, and does not
  143. X           allow the client machine to issue request messages at
  144. X           a higher rate compared to the previous versions.  The
  145. X           FSP_LOCALPORT variable is no longer needed.  However,
  146. X           if used, it will force serialization of client programs,
  147. X           which might be desireable if none of the multiplexing
  148. X           mechanisms are suitable for your machine.  In order to
  149. X           accommodate this change, the server code has been
  150. X           changed to store temporary upload files with a different
  151. X           name from the previous version.  The names now have to
  152. X           identify sender's port as well as sender's internet id.
  153. X           Change is necessary to keep it under 14-character limit
  154. X           of some OS.
  155. X
  156. X        3) Progress report mechanism enabled by FSP_TRACE variable
  157. X           now try to update the kbyte display more promptly.
  158. X
  159. X        4) fcat/fcatcmd will now turn off FSP_TRACE during its
  160. X           file transfer if its stdout is a tty.
  161. X
  162. XVersion 2.5 -- April 8, 1992
  163. X
  164. X        1) A bug introduced during the last release --- fspd will
  165. X           not timeout and exit when running under inetd mode.
  166. X           This bug is now fixed.  It was introduced because it
  167. X           is more convienent at one time for it not to exit when
  168. X           it is still being debugged.  The patch to stop it from
  169. X           exiting was not removed before release time. 
  170. X
  171. X        2) A very rarely seen bug in some OS is circumvented. UDP
  172. X           packet's headers contain a checksum field.  If the
  173. X           checksum option is disabled, the OS will set the
  174. X           checksum field to 0 before sending, and will not check
  175. X           the checksum field when message is received. If the
  176. X           option is enabled, the OS will stuff the checksum into
  177. X           the checksum field.  When a packet is received, the
  178. X           checksum field is checked.  If the checksum field is 0,
  179. X           then the OS assume that the sender does not have option
  180. X           enabled, and therefore the checking is skipped.
  181. X
  182. X           Problem arises when a packet's computed checksum is
  183. X           zero.  Some OS will stuff 0xffff into the checksum
  184. X           field before sending such a message to distinguish it
  185. X           from the case for which checksum is disabled.  Other
  186. X           OS couldn't recognize 0xffff as an indication that the
  187. X           actual checksum could be either 0 or 0xffff, and
  188. X           subsequently reject the message. The client can thus
  189. X           get stuck forever in retransmitting a request that
  190. X           happens to have 0 for the computed checksum, but
  191. X           0xffff for the checksum field.
  192. X
  193. X           To get around the problem, the sequence number field
  194. X           of the request message (which has meaning only to the
  195. X           client software), is partitioned such that 2 of the
  196. X           bits reflect the retry sequence, and the remaining 14
  197. X           bits reflect the request sequence.  This will ensure
  198. X           that if one request got ignored because it happens to
  199. X           have a checksum of 0, the next retry will result in
  200. X           a packet that does not have a checksum of 0.  The only
  201. X           file affected here is client_lib.c.
  202. X
  203. X        3) In response to those who have severely limited UDP
  204. X           packet sizes, the environment variable FSP_BUF_SIZE
  205. X           is supplied to set the data size of file and directory
  206. X           information transfers. The default is 1024.  You cannot
  207. X           set it to be bigger than 1024, but you can set it to
  208. X           be smaller if you find that your system cannot pass
  209. X           UDP packets that includes 1024 bytes of data.  This
  210. X           requires changes both in the server and the client
  211. X           code.  The first parameter field of get-file and
  212. X           get-directory requests contains the path of the file
  213. X           or directory.  The second parameter field was unused,
  214. X           but it is now used to hold the number of bytes to read.
  215. X           This change is backward compatible in the sense that
  216. X           if the second field is empty (old client code), the
  217. X           new server code will default to 1024.  Changes to the
  218. X           client code is confined to client_util.c.
  219. X
  220. XVersion 2.6 -- July 6, 1992
  221. X
  222. X        1) client_lock.c is fixed so that perror is always
  223. X           followed by exit.  Previously, if System-V shared
  224. X           memory mechanism is chosen for locking control in
  225. X           the Makefile, but the mechansim has not in fact
  226. X           been configured into the UNIX kernel, the client
  227. X           utilities would die of a segmentation fault error.
  228. X           The error message will now be more reasonable.
  229. X
  230. X        2) mechanism is added so FSP server can put directory
  231. X           cache files in a special directory other than the one
  232. X           for which the files are intended.  Previously a
  233. X           .FSP_CONTENT file is created in each directory the
  234. X           fspd process controls.  Through variables in the
  235. X           Makefile, provider of fsp service can now elect to put
  236. X           cache files together in one single directory, and put
  237. X           a cap on the total number of such files that can exist
  238. X           simultaneously.  The fsp server will create a cache
  239. X           file in the cache directory when it couldn't find one
  240. X           already exist in the directory being listed by the
  241. X           client.  Changed are minor and invovles the routines
  242. X           server_get_dir, server_get_dir_2 [new] in "server_file.c";
  243. X           the variable declaration section of "server_main.c", and
  244. X           Makefile.
  245. X
  246. X        3) a line in util_cd is changed, and a line in get_dir_blk
  247. X           is added in the file "client_util.c" to prevent fls from
  248. X           sending some spurious requests to the fsp server.
  249. X
  250. X        4) Makefile is changed to allow the option of combining all
  251. X           client utilities into one actual binary files.  This is
  252. X           necessary for space saving reasons on some versions of
  253. X           UNIX.  The various small main C files for the utilities
  254. X           had to be changed as well to accomodate this change.
  255. X
  256. X        5) fver now will take an optional argument.  If none is
  257. X           supplied, it prints the version string of the server.
  258. X           If one is supplied, it prints the versioin string of
  259. X           the client FSP software.
  260. X
  261. XVersion 2.6.1 -- Aug 31, 1992
  262. X
  263. X        1) Small changes to Makefile.  In 2.6, "make" will fail if
  264. X           you needed to define LIB, or if your command shell is not 
  265. X           /bin/sh, and you want to merge client utilities.  Version
  266. X           2.6.1 fixed them.  Only Makefile is changed, everything
  267. X           else is identical to 2.6.
  268. X
  269. XVersion 2.6.2 -- Sep 2, 1992
  270. X
  271. X        1) bsd_src/cmp.c was changed so that flscmd can sort its
  272. X           output by date correctly on all systems.  This particular
  273. X           version of the BSD source made assumptions about what
  274. X           the comparison functions should return for the qsort
  275. X           routine, but those assumptions were not true for all
  276. X           systems.
  277. X
  278. XVersion 2.6.3 -- Sep 19, 1992
  279. X
  280. X        1) client_lock.c is modified to fix a compilation phase
  281. X           bug that occur when NOLOCKING option is used in the
  282. X           Makefile.  This affects only the client code.
  283. X
  284. X        2) server_file.c is modified so that upload uses the
  285. X           directory cache directory instead of the top directory.
  286. X           This is needed for those sites that want the top
  287. X           directory be write protected.  (good for ftp sites).
  288. X
  289. XVersion 2.6.4 -- Dec 12, 1992.
  290. X
  291. X        1) Make main makefile pass CC and CFLAGS definitions to
  292. X           bsd_src's Makefile
  293. X
  294. X        2) Add util_cd2 to client_util and make bsd_src/ls.c use
  295. X           it.  This remove some of the spurious GET_DIR requests.
  296. X           Also, there is a bug in client_util's util_cd routine
  297. X           in that it always requests 1K worth of directory info
  298. X           no matter what FSP_BUF_SIZE setting is used.  Causeing
  299. X           fsp clients to hang under situations where FSP_BUF_SIZE
  300. X           is limited by the network (slip, usually). 
  301. X
  302. X        3) function server_interrupt in server_lib.c was defined
  303. X           to be of type void to avoid complaint from some compilers.
  304. X           There are several other minor fixes in functin variable
  305. X           declarations in several files for the same reason.
  306. X
  307. XWhat needs to be done EVENTUALLY
  308. X
  309. X    Somebody should make a tar equivalent that read and write remote fsp
  310. X    archives.  This will allow transfer of whole directory in one command.
  311. X
  312. X    Sources should be make to pass lint with as little problem as possible.
  313. END_OF_FILE
  314.   if test 12910 -ne `wc -c <'ChangeLog'`; then
  315.     echo shar: \"'ChangeLog'\" unpacked with wrong size!
  316.   fi
  317.   # end of 'ChangeLog'
  318. fi
  319. if test -f 'bsd_src/ls.c' -a "${1}" != "-c" ; then 
  320.   echo shar: Will not clobber existing file \"'bsd_src/ls.c'\"
  321. else
  322.   echo shar: Extracting \"'bsd_src/ls.c'\" \(10953 characters\)
  323.   sed "s/^X//" >'bsd_src/ls.c' <<'END_OF_FILE'
  324. X/*
  325. X * Copyright (c) 1989 The Regents of the University of California.
  326. X * All rights reserved.
  327. X *
  328. X * This code is derived from software contributed to Berkeley by
  329. X * Michael Fischbein.
  330. X *
  331. X * Redistribution and use in source and binary forms are permitted
  332. X * provided that: (1) source distributions retain this entire copyright
  333. X * notice and comment, and (2) distributions including binaries display
  334. X * the following acknowledgement:  ``This product includes software
  335. X * developed by the University of California, Berkeley and its contributors''
  336. X * in the documentation or other materials provided with the distribution
  337. X * and in all advertising materials mentioning features or use of this
  338. X * software. Neither the name of the University nor the names of its
  339. X * contributors may be used to endorse or promote products derived
  340. X * from this software without specific prior written permission.
  341. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  342. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  343. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  344. X */
  345. X
  346. X#ifndef lint
  347. Xchar copyright[] =
  348. X"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
  349. X All rights reserved.\n";
  350. X#endif /* not lint */
  351. X
  352. X#ifndef lint
  353. Xstatic char sccsid[] = "@(#)ls.c    5.42 (Berkeley) 5/17/90";
  354. X#endif /* not lint */
  355. X
  356. X#include "../client_def.h"
  357. X#include <sys/ioctl.h>
  358. X#include <string.h>
  359. X#include "ls.h"
  360. X#include "tweak.h"
  361. X
  362. Xint (*sortfcn)(), (*printfcn)();
  363. Xchar *emalloc();
  364. X
  365. Xint termwidth = 80;        /* default terminal width */
  366. X
  367. X/* flags */
  368. Xint f_accesstime;        /* use time of last access */
  369. Xint f_column;            /* columnated format */
  370. Xint f_group;            /* show group ownership of a file */
  371. Xint f_ignorelink;        /* indirect through symbolic link operands */
  372. Xint f_inode;            /* print inode */
  373. Xint f_kblocks;            /* print size in kilobytes */
  374. Xint f_listalldot;        /* list . and .. as well */
  375. Xint f_listdir;            /* list actual directory, not contents */
  376. Xint f_listdot;            /* list files beginning with . */
  377. Xint f_longform;            /* long listing format */
  378. Xint f_needstat;            /* if need to stat files */
  379. Xint f_newline;            /* if precede with newline */
  380. Xint f_nonprint;            /* show unprintables as ? */
  381. Xint f_nosort;            /* don't sort output */
  382. Xint f_recursive;        /* ls subdirectories also */
  383. Xint f_reversesort;        /* reverse whatever sort is used */
  384. Xint f_singlecol;        /* use single column output */
  385. Xint f_size;            /* list size in short listing */
  386. Xint f_statustime;        /* use time of last mode change */
  387. Xint f_dirname;            /* if precede with directory name */
  388. Xint f_timesort;            /* sort by time vice name */
  389. Xint f_total;            /* if precede with "total" line */
  390. Xint f_type;            /* add type character for non-regular files */
  391. X
  392. Xfls_main(argc, argv)
  393. X    int argc;
  394. X    char **argv;
  395. X{
  396. X    extern int optind;
  397. X    int ch;
  398. X    char *p, *getenv();
  399. X    int acccmp(), modcmp(), namecmp(), prcopy(), printcol();
  400. X    int printlong(), printscol(), revacccmp(), revmodcmp(), revnamecmp();
  401. X    int revstatcmp(), statcmp();
  402. X
  403. X    /* terminal defaults to -Cq, non-terminal defaults to -1 */
  404. X    if (isatty(1)) {
  405. X        f_nonprint = 1;
  406. X        termwidth  = 80;
  407. X#ifdef TIOCGWINSZ
  408. X        {   struct winsize win;
  409. X            if (ioctl(1, TIOCGWINSZ, &win) == -1 || !win.ws_col) {
  410. X                if (p = getenv("COLUMNS"))
  411. X                    termwidth = atoi(p);
  412. X            }
  413. X            else
  414. X                termwidth = win.ws_col;
  415. X        }
  416. X#endif
  417. X        f_column = 1;
  418. X    } else
  419. X        f_singlecol = 1;
  420. X
  421. X    /* root is -A automatically */
  422. X    if (!getuid())
  423. X        f_listdot = 1;
  424. X
  425. X    while ((ch = getopt(argc, argv, "1ACFLRacdfgiklqrstu")) != EOF) {
  426. X        switch (ch) {
  427. X        /*
  428. X         * -1, -C and -l all override each other
  429. X         * so shell aliasing works right
  430. X         */
  431. X        case '1':
  432. X            f_singlecol = 1;
  433. X            f_column = f_longform = 0;
  434. X            break;
  435. X        case 'C':
  436. X            f_column = 1;
  437. X            f_longform = f_singlecol = 0;
  438. X            break;
  439. X        case 'l':
  440. X            f_longform = 1;
  441. X            f_column = f_singlecol = 0;
  442. X            break;
  443. X        /* -c and -u override each other */
  444. X        case 'c':
  445. X            f_statustime = 1;
  446. X            f_accesstime = 0;
  447. X            break;
  448. X        case 'u':
  449. X            f_accesstime = 1;
  450. X            f_statustime = 0;
  451. X            break;
  452. X        case 'F':
  453. X            f_type = 1;
  454. X            break;
  455. X        case 'L':
  456. X            f_ignorelink = 1;
  457. X            break;
  458. X        case 'R':
  459. X            f_recursive = 1;
  460. X            break;
  461. X        case 'a':
  462. X            f_listalldot = 1;
  463. X            /* FALLTHROUGH */
  464. X        case 'A':
  465. X            f_listdot = 1;
  466. X            break;
  467. X        case 'd':
  468. X            f_listdir = 1;
  469. X            break;
  470. X        case 'f':
  471. X            f_nosort = 1;
  472. X            break;
  473. X        case 'g':
  474. X            f_group = 1;
  475. X            break;
  476. X        case 'i':
  477. X            f_inode = 1;
  478. X            break;
  479. X        case 'k':
  480. X            f_kblocks = 1;
  481. X            break;
  482. X        case 'q':
  483. X            f_nonprint = 1;
  484. X            break;
  485. X        case 'r':
  486. X            f_reversesort = 1;
  487. X            break;
  488. X        case 's':
  489. X            f_size = 1;
  490. X            break;
  491. X        case 't':
  492. X            f_timesort = 1;
  493. X            break;
  494. X        default:
  495. X        case '?':
  496. X            usage();
  497. X        }
  498. X    }
  499. X    argc -= optind;
  500. X    argv += optind;
  501. X
  502. X    /* -d turns off -R */
  503. X    if (f_listdir)
  504. X        f_recursive = 0;
  505. X
  506. X    /* if need to stat files */
  507. X    f_needstat = f_longform || f_recursive || f_timesort ||
  508. X        f_size || f_type;
  509. X
  510. X    /* select a sort function */
  511. X    if (f_reversesort) {
  512. X        if (!f_timesort)
  513. X            sortfcn = revnamecmp;
  514. X        else if (f_accesstime)
  515. X            sortfcn = revacccmp;
  516. X        else if (f_statustime)
  517. X            sortfcn = revstatcmp;
  518. X        else /* use modification time */
  519. X            sortfcn = revmodcmp;
  520. X    } else {
  521. X        if (!f_timesort)
  522. X            sortfcn = namecmp;
  523. X        else if (f_accesstime)
  524. X            sortfcn = acccmp;
  525. X        else if (f_statustime)
  526. X            sortfcn = statcmp;
  527. X        else /* use modification time */
  528. X            sortfcn = modcmp;
  529. X    }
  530. X
  531. X    /* select a print function */
  532. X    if (f_singlecol)
  533. X        printfcn = printscol;
  534. X    else if (f_longform)
  535. X        printfcn = printlong;
  536. X    else
  537. X        printfcn = printcol;
  538. X
  539. X    if (!argc) {
  540. X        argc = 1;
  541. X        argv[0] = ".";
  542. X        argv[1] = NULL;
  543. X    }
  544. X    doargs(argc, argv);
  545. X}
  546. X
  547. Xstatic char path[2*1024 + 1];
  548. Xstatic char *endofpath = path;
  549. X
  550. Xdoargs(argc, argv)
  551. X    int argc;
  552. X    char **argv;
  553. X{
  554. X    register LS *dstatp, *rstatp;
  555. X    register int cnt, dircnt, dirmax, maxlen, regcnt, regmax;
  556. X    LS *dstats, *rstats;
  557. X    struct stat sb;
  558. X    char top[2*1024 + 1], **av, *av2[2];
  559. X    unsigned long blocks;
  560. X    extern char **glob();
  561. X
  562. X    /*
  563. X     * walk through the operands, building separate arrays of LS
  564. X     * structures for directory and non-directory files.
  565. X     */
  566. X    dstats = rstats = NULL;
  567. X    dirmax = regmax = 0;
  568. X
  569. X    for (dircnt = regcnt = 0; *argv; ++argv)
  570. X    {
  571. X        if(!(av = glob(*argv))) { av = av2; av2[0] = *argv; av2[1] = 0; }
  572. X
  573. X        for( ; *av; av++)
  574. X        {
  575. X        if (util_stat(*av, &sb)) {
  576. X            perror(*av);
  577. X            if (errno == ENOENT)
  578. X                continue;
  579. X            ls_bad(1);
  580. X        }
  581. X        if ((S_IFDIR & sb.st_mode) && !f_listdir) {
  582. X            if(dirmax == dircnt)
  583. X            {
  584. X                dirmax += 10;
  585. X                if (!dstats)
  586. X                {
  587. X                dstatp = dstats = (LS *)emalloc(dirmax *
  588. X                                (sizeof(LS)));
  589. X                } else 
  590. X                {
  591. X                dstats = (LS *)realloc(dstats,
  592. X                            dirmax * (sizeof(LS)));
  593. X                dstatp = dstats + dircnt;
  594. X                }
  595. X            }
  596. X            dstatp->name = *av;
  597. X            dstatp->lstat = sb;
  598. X            ++dstatp;
  599. X            ++dircnt;
  600. X        }
  601. X        else {
  602. X            if(regmax == regcnt)
  603. X            {
  604. X                regmax += 10;
  605. X
  606. X                if (!rstats)
  607. X                {
  608. X                blocks = 0;
  609. X                maxlen = -1;
  610. X                rstatp = rstats = (LS *)emalloc(regmax *
  611. X                            (sizeof(LS)));
  612. X                } else
  613. X                {
  614. X                rstats = (LS *)realloc(rstats,
  615. X                            regmax * (sizeof(LS)));
  616. X                rstatp = rstats + regcnt;
  617. X                }
  618. X            }
  619. X            rstatp->name = *av;
  620. X            rstatp->lstat = sb;
  621. X
  622. X            /* save name length for -C format */
  623. X            rstatp->len = strlen(*av);
  624. X
  625. X            if (f_nonprint)
  626. X                prcopy(*av, *av, rstatp->len);
  627. X
  628. X            /* calculate number of blocks if -l/-s formats */
  629. X            if (f_longform || f_size)
  630. X                blocks += (sb.st_size + 1023)/1024;
  631. X
  632. X            /* save max length if -C format */
  633. X            if (f_column && maxlen < rstatp->len)
  634. X                maxlen = rstatp->len;
  635. X
  636. X            ++rstatp;
  637. X            ++regcnt;
  638. X        }
  639. X        }
  640. X    }
  641. X    /* display regular files */
  642. X    if (regcnt) {
  643. X        rstats[0].lstat.st_btotal = blocks;
  644. X        rstats[0].lstat.st_maxlen = maxlen;
  645. X        displaydir(rstats, regcnt);
  646. X        f_newline = f_dirname = 1;
  647. X    }
  648. X    /* display directories */
  649. X    if (dircnt) {
  650. X        register char *p;
  651. X
  652. X        f_total = 1;
  653. X        if (dircnt > 1) {
  654. X            (void)util_getwd(top);
  655. X            qsort((char *)dstats, dircnt, sizeof(LS), sortfcn);
  656. X            f_dirname = 1;
  657. X        }
  658. X        for (cnt = 0; cnt < dircnt; ++dstats) {
  659. X            for (endofpath = path, p = dstats->name;
  660. X                *endofpath = *p++; ++endofpath);
  661. X            subdir(dstats);
  662. X            f_newline = 1;
  663. X            if (++cnt < dircnt && util_cd2(top)) {
  664. X                perror(top);
  665. X                ls_bad(1);
  666. X            }
  667. X        }
  668. X    }
  669. X}
  670. X
  671. Xdisplaydir(stats, num)
  672. X    LS *stats;
  673. X    register int num;
  674. X{
  675. X    register char *p, *savedpath;
  676. X    LS *lp;
  677. X
  678. X    if (num > 1 && !f_nosort) {
  679. X        unsigned long save1, save2;
  680. X
  681. X        save1 = stats[0].lstat.st_btotal;
  682. X        save2 = stats[0].lstat.st_maxlen;
  683. X        qsort((char *)stats, num, sizeof(LS), sortfcn);
  684. X        stats[0].lstat.st_btotal = save1;
  685. X        stats[0].lstat.st_maxlen = save2;
  686. X    }
  687. X
  688. X    printfcn(stats, num);
  689. X
  690. X    if (f_recursive) {
  691. X        savedpath = endofpath;
  692. X        for (lp = stats; num--; ++lp) {
  693. X            if (!(S_IFDIR & lp->lstat.st_mode))
  694. X                continue;
  695. X            p = lp->name;
  696. X            if (p[0] == '.' && (!p[1] || p[1] == '.' && !p[2]))
  697. X                continue;
  698. X            if (endofpath != path && endofpath[-1] != '/')
  699. X                *endofpath++ = '/';
  700. X            for (; *endofpath = *p++; ++endofpath);
  701. X            f_newline = f_dirname = f_total = 1;
  702. X            subdir(lp);
  703. X            *(endofpath = savedpath) = '\0';
  704. X        }
  705. X    }
  706. X}
  707. X
  708. Xsubdir(lp)
  709. X    LS *lp;
  710. X{
  711. X    LS *stats;
  712. X    int num;
  713. X
  714. X    if (f_newline)
  715. X        (void)putchar('\n');
  716. X    if (f_dirname)
  717. X        (void)printf("%s:\n", path);
  718. X
  719. X    if (util_cd2(lp->name)) {
  720. X        perror(lp->name);
  721. X        return;
  722. X    }
  723. X    if (num = tabdir(lp, &stats)) {
  724. X        displaydir(stats, num);
  725. X        (void)free((char *)stats);
  726. X    }
  727. X    if (util_cd2("..")) {
  728. X        perror("..");
  729. X        ls_bad(1);
  730. X    }
  731. X}
  732. X
  733. Xtabdir(lp, s_stats)
  734. X    LS *lp, **s_stats;
  735. X{
  736. X    register RDIR *dirp;
  737. X    register int cnt, maxentry, maxlen;
  738. X    register char *p;
  739. X    struct rdirent *dp;
  740. X    unsigned long blocks;
  741. X    LS *stats;
  742. X
  743. X    if (!(dirp = util_opendir("."))) {
  744. X        perror(lp->name);
  745. X        return(0);
  746. X    }
  747. X    blocks = maxentry = maxlen = 0;
  748. X    stats = NULL;
  749. X    for (cnt = 0; dp = util_readdir(dirp);) {
  750. X        /* this does -A and -a */
  751. X        p = dp->d_name;
  752. X        if (p[0] == '.') {
  753. X            if (!f_listdot)
  754. X                continue;
  755. X            if (!f_listalldot && (!p[1] || p[1] == '.' && !p[2]))
  756. X                continue;
  757. X        }
  758. X        if (cnt == maxentry) {
  759. X#define    DEFNUM    256
  760. X            maxentry += DEFNUM;
  761. X            if(stats)
  762. X            {
  763. X              if (!(*s_stats = stats = (LS *)realloc((char *)stats,
  764. X                (unsigned int)maxentry * sizeof(LS))))
  765. X                nomem();
  766. X            } else
  767. X            {
  768. X              if (!(*s_stats = stats = (LS *)malloc(
  769. X                (unsigned int)maxentry * sizeof(LS))))
  770. X                nomem();
  771. X            }
  772. X        }
  773. X        if (f_needstat && util_stat(dp->d_name, &stats[cnt].lstat)) {
  774. X            /*
  775. X             * don't exit -- this could be an NFS mount that has
  776. X             * gone away.  Flush stdout so the messages line up.
  777. X             */
  778. X            (void)fflush(stdout);
  779. X            perror(dp->d_name);
  780. X            continue;
  781. X        }
  782. X        stats[cnt].name = dp->d_name;
  783. X
  784. X        /*
  785. X         * get the inode from the directory, so the -f flag
  786. X         * works right.
  787. X         */
  788. X        stats[cnt].lstat.st_ino = dp->d_ino;
  789. X
  790. X        /* save name length for -C format */
  791. X        stats[cnt].len = dp->d_namlen;
  792. X
  793. X        /* calculate number of blocks if -l/-s formats */
  794. X        if (f_longform || f_size)
  795. X            blocks += (stats[cnt].lstat.st_size + 1023)/1024;
  796. X
  797. X        /* save max length if -C format */
  798. X        if (f_column && maxlen < (int)dp->d_namlen)
  799. X            maxlen = dp->d_namlen;
  800. X        ++cnt;
  801. X    }
  802. X    (void)util_closedir(dirp);
  803. X
  804. X    if (cnt) {
  805. X        stats[0].lstat.st_btotal = blocks;
  806. X        stats[0].lstat.st_maxlen = maxlen;
  807. X    } else if (stats) {
  808. X        (void)free((char *)stats);
  809. X    }
  810. X    return(cnt);
  811. X}
  812. END_OF_FILE
  813.   if test 10953 -ne `wc -c <'bsd_src/ls.c'`; then
  814.     echo shar: \"'bsd_src/ls.c'\" unpacked with wrong size!
  815.   fi
  816.   # end of 'bsd_src/ls.c'
  817. fi
  818. if test -f 'bsd_src/random.c' -a "${1}" != "-c" ; then 
  819.   echo shar: Will not clobber existing file \"'bsd_src/random.c'\"
  820. else
  821.   echo shar: Extracting \"'bsd_src/random.c'\" \(12955 characters\)
  822.   sed "s/^X//" >'bsd_src/random.c' <<'END_OF_FILE'
  823. X/*
  824. X * Copyright (c) 1983 Regents of the University of California.
  825. X * All rights reserved.
  826. X *
  827. X * Redistribution and use in source and binary forms are permitted
  828. X * provided that: (1) source distributions retain this entire copyright
  829. X * notice and comment, and (2) distributions including binaries display
  830. X * the following acknowledgement:  ``This product includes software
  831. X * developed by the University of California, Berkeley and its contributors''
  832. X * in the documentation or other materials provided with the distribution
  833. X * and in all advertising materials mentioning features or use of this
  834. X * software. Neither the name of the University nor the names of its
  835. X * contributors may be used to endorse or promote products derived
  836. X * from this software without specific prior written permission.
  837. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  838. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  839. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  840. X */
  841. X
  842. X#if defined(LIBC_SCCS) && !defined(lint)
  843. Xstatic char sccsid[] = "@(#)random.c    5.7 (Berkeley) 6/1/90";
  844. X#endif /* LIBC_SCCS and not lint */
  845. X
  846. X#include <stdio.h>
  847. X
  848. X/*
  849. X * random.c:
  850. X * An improved random number generation package.  In addition to the standard
  851. X * rand()/srand() like interface, this package also has a special state info
  852. X * interface.  The initstate() routine is called with a seed, an array of
  853. X * bytes, and a count of how many bytes are being passed in; this array is then
  854. X * initialized to contain information for random number generation with that
  855. X * much state information.  Good sizes for the amount of state information are
  856. X * 32, 64, 128, and 256 bytes.  The state can be switched by calling the
  857. X * setstate() routine with the same array as was initiallized with initstate().
  858. X * By default, the package runs with 128 bytes of state information and
  859. X * generates far better random numbers than a linear congruential generator.
  860. X * If the amount of state information is less than 32 bytes, a simple linear
  861. X * congruential R.N.G. is used.
  862. X * Internally, the state information is treated as an array of longs; the
  863. X * zeroeth element of the array is the type of R.N.G. being used (small
  864. X * integer); the remainder of the array is the state information for the
  865. X * R.N.G.  Thus, 32 bytes of state information will give 7 longs worth of
  866. X * state information, which will allow a degree seven polynomial.  (Note: the 
  867. X * zeroeth word of state information also has some other information stored
  868. X * in it -- see setstate() for details).
  869. X * The random number generation technique is a linear feedback shift register
  870. X * approach, employing trinomials (since there are fewer terms to sum up that
  871. X * way).  In this approach, the least significant bit of all the numbers in
  872. X * the state table will act as a linear feedback shift register, and will have
  873. X * period 2^deg - 1 (where deg is the degree of the polynomial being used,
  874. X * assuming that the polynomial is irreducible and primitive).  The higher
  875. X * order bits will have longer periods, since their values are also influenced
  876. X * by pseudo-random carries out of the lower bits.  The total period of the
  877. X * generator is approximately deg*(2**deg - 1); thus doubling the amount of
  878. X * state information has a vast influence on the period of the generator.
  879. X * Note: the deg*(2**deg - 1) is an approximation only good for large deg,
  880. X * when the period of the shift register is the dominant factor.  With deg
  881. X * equal to seven, the period is actually much longer than the 7*(2**7 - 1)
  882. X * predicted by this formula.
  883. X */
  884. X
  885. X
  886. X
  887. X/*
  888. X * For each of the currently supported random number generators, we have a
  889. X * break value on the amount of state information (you need at least this
  890. X * many bytes of state info to support this random number generator), a degree
  891. X * for the polynomial (actually a trinomial) that the R.N.G. is based on, and
  892. X * the separation between the two lower order coefficients of the trinomial.
  893. X */
  894. X
  895. X#define        TYPE_0        0        /* linear congruential */
  896. X#define        BREAK_0        8
  897. X#define        DEG_0        0
  898. X#define        SEP_0        0
  899. X
  900. X#define        TYPE_1        1        /* x**7 + x**3 + 1 */
  901. X#define        BREAK_1        32
  902. X#define        DEG_1        7
  903. X#define        SEP_1        3
  904. X
  905. X#define        TYPE_2        2        /* x**15 + x + 1 */
  906. X#define        BREAK_2        64
  907. X#define        DEG_2        15
  908. X#define        SEP_2        1
  909. X
  910. X#define        TYPE_3        3        /* x**31 + x**3 + 1 */
  911. X#define        BREAK_3        128
  912. X#define        DEG_3        31
  913. X#define        SEP_3        3
  914. X
  915. X#define        TYPE_4        4        /* x**63 + x + 1 */
  916. X#define        BREAK_4        256
  917. X#define        DEG_4        63
  918. X#define        SEP_4        1
  919. X
  920. X
  921. X/*
  922. X * Array versions of the above information to make code run faster -- relies
  923. X * on fact that TYPE_i == i.
  924. X */
  925. X
  926. X#define        MAX_TYPES    5        /* max number of types above */
  927. X
  928. Xstatic  int        degrees[ MAX_TYPES ]    = { DEG_0, DEG_1, DEG_2,
  929. X                                DEG_3, DEG_4 };
  930. X
  931. Xstatic  int        seps[ MAX_TYPES ]    = { SEP_0, SEP_1, SEP_2,
  932. X                                SEP_3, SEP_4 };
  933. X
  934. X
  935. X
  936. X/*
  937. X * Initially, everything is set up as if from :
  938. X *        initstate( 1, &randtbl, 128 );
  939. X * Note that this initialization takes advantage of the fact that srandom()
  940. X * advances the front and rear pointers 10*rand_deg times, and hence the
  941. X * rear pointer which starts at 0 will also end up at zero; thus the zeroeth
  942. X * element of the state information, which contains info about the current
  943. X * position of the rear pointer is just
  944. X *    MAX_TYPES*(rptr - state) + TYPE_3 == TYPE_3.
  945. X */
  946. X
  947. Xstatic  long        randtbl[ DEG_3 + 1 ]    = { TYPE_3,
  948. X                0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 
  949. X                0xde3b81e0, 0xdf0a6fb5, 0xf103bc02, 0x48f340fb, 
  950. X                0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, 
  951. X                0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 
  952. X                0xda672e2a, 0x1588ca88, 0xe369735d, 0x904f35f7, 
  953. X                0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, 
  954. X                0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 
  955. X                    0xf5ad9d0e, 0x8999220b, 0x27fb47b9 };
  956. X
  957. X/*
  958. X * fptr and rptr are two pointers into the state info, a front and a rear
  959. X * pointer.  These two pointers are always rand_sep places aparts, as they cycle
  960. X * cyclically through the state information.  (Yes, this does mean we could get
  961. X * away with just one pointer, but the code for random() is more efficient this
  962. X * way).  The pointers are left positioned as they would be from the call
  963. X *            initstate( 1, randtbl, 128 )
  964. X * (The position of the rear pointer, rptr, is really 0 (as explained above
  965. X * in the initialization of randtbl) because the state table pointer is set
  966. X * to point to randtbl[1] (as explained below).
  967. X */
  968. X
  969. Xstatic  long        *fptr            = &randtbl[ SEP_3 + 1 ];
  970. Xstatic  long        *rptr            = &randtbl[ 1 ];
  971. X
  972. X
  973. X
  974. X/*
  975. X * The following things are the pointer to the state information table,
  976. X * the type of the current generator, the degree of the current polynomial
  977. X * being used, and the separation between the two pointers.
  978. X * Note that for efficiency of random(), we remember the first location of
  979. X * the state information, not the zeroeth.  Hence it is valid to access
  980. X * state[-1], which is used to store the type of the R.N.G.
  981. X * Also, we remember the last location, since this is more efficient than
  982. X * indexing every time to find the address of the last element to see if
  983. X * the front and rear pointers have wrapped.
  984. X */
  985. X
  986. Xstatic  long        *state            = &randtbl[ 1 ];
  987. X
  988. Xstatic  int        rand_type        = TYPE_3;
  989. Xstatic  int        rand_deg        = DEG_3;
  990. Xstatic  int        rand_sep        = SEP_3;
  991. X
  992. Xstatic  long        *end_ptr        = &randtbl[ DEG_3 + 1 ];
  993. X
  994. X
  995. X
  996. X/*
  997. X * srandom:
  998. X * Initialize the random number generator based on the given seed.  If the
  999. X * type is the trivial no-state-information type, just remember the seed.
  1000. X * Otherwise, initializes state[] based on the given "seed" via a linear
  1001. X * congruential generator.  Then, the pointers are set to known locations
  1002. X * that are exactly rand_sep places apart.  Lastly, it cycles the state
  1003. X * information a given number of times to get rid of any initial dependencies
  1004. X * introduced by the L.C.R.N.G.
  1005. X * Note that the initialization of randtbl[] for default usage relies on
  1006. X * values produced by this routine.
  1007. X */
  1008. X
  1009. Xsrandom( x )
  1010. X
  1011. X    unsigned        x;
  1012. X{
  1013. X        register  int        i, j;
  1014. X    long random();
  1015. X
  1016. X    if(  rand_type  ==  TYPE_0  )  {
  1017. X        state[ 0 ] = x;
  1018. X    }
  1019. X    else  {
  1020. X        j = 1;
  1021. X        state[ 0 ] = x;
  1022. X        for( i = 1; i < rand_deg; i++ )  {
  1023. X        state[i] = 1103515245*state[i - 1] + 12345;
  1024. X        }
  1025. X        fptr = &state[ rand_sep ];
  1026. X        rptr = &state[ 0 ];
  1027. X        for( i = 0; i < 10*rand_deg; i++ )  random();
  1028. X    }
  1029. X}
  1030. X
  1031. X
  1032. X
  1033. X/*
  1034. X * initstate:
  1035. X * Initialize the state information in the given array of n bytes for
  1036. X * future random number generation.  Based on the number of bytes we
  1037. X * are given, and the break values for the different R.N.G.'s, we choose
  1038. X * the best (largest) one we can and set things up for it.  srandom() is
  1039. X * then called to initialize the state information.
  1040. X * Note that on return from srandom(), we set state[-1] to be the type
  1041. X * multiplexed with the current value of the rear pointer; this is so
  1042. X * successive calls to initstate() won't lose this information and will
  1043. X * be able to restart with setstate().
  1044. X * Note: the first thing we do is save the current state, if any, just like
  1045. X * setstate() so that it doesn't matter when initstate is called.
  1046. X * Returns a pointer to the old state.
  1047. X */
  1048. X
  1049. Xchar  *
  1050. Xinitstate( seed, arg_state, n )
  1051. X
  1052. X    unsigned        seed;            /* seed for R. N. G. */
  1053. X    char        *arg_state;        /* pointer to state array */
  1054. X    int            n;            /* # bytes of state info */
  1055. X{
  1056. X    register  char        *ostate        = (char *)( &state[ -1 ] );
  1057. X
  1058. X    if(  rand_type  ==  TYPE_0  )  state[ -1 ] = rand_type;
  1059. X    else  state[ -1 ] = MAX_TYPES*(rptr - state) + rand_type;
  1060. X    if(  n  <  BREAK_1  )  {
  1061. X        if(  n  <  BREAK_0  )  {
  1062. X        fprintf( stderr, "initstate: not enough state (%d bytes); ignored.\n", n );
  1063. X        return 0;
  1064. X        }
  1065. X        rand_type = TYPE_0;
  1066. X        rand_deg = DEG_0;
  1067. X        rand_sep = SEP_0;
  1068. X    }
  1069. X    else  {
  1070. X        if(  n  <  BREAK_2  )  {
  1071. X        rand_type = TYPE_1;
  1072. X        rand_deg = DEG_1;
  1073. X        rand_sep = SEP_1;
  1074. X        }
  1075. X        else  {
  1076. X        if(  n  <  BREAK_3  )  {
  1077. X            rand_type = TYPE_2;
  1078. X            rand_deg = DEG_2;
  1079. X            rand_sep = SEP_2;
  1080. X        }
  1081. X        else  {
  1082. X            if(  n  <  BREAK_4  )  {
  1083. X            rand_type = TYPE_3;
  1084. X            rand_deg = DEG_3;
  1085. X            rand_sep = SEP_3;
  1086. X            }
  1087. X            else  {
  1088. X            rand_type = TYPE_4;
  1089. X            rand_deg = DEG_4;
  1090. X            rand_sep = SEP_4;
  1091. X            }
  1092. X        }
  1093. X        }
  1094. X    }
  1095. X    state = &(  ( (long *)arg_state )[1]  );    /* first location */
  1096. X    end_ptr = &state[ rand_deg ];    /* must set end_ptr before srandom */
  1097. X    srandom( seed );
  1098. X    if(  rand_type  ==  TYPE_0  )  state[ -1 ] = rand_type;
  1099. X    else  state[ -1 ] = MAX_TYPES*(rptr - state) + rand_type;
  1100. X    return( ostate );
  1101. X}
  1102. X
  1103. X
  1104. X
  1105. X/*
  1106. X * setstate:
  1107. X * Restore the state from the given state array.
  1108. X * Note: it is important that we also remember the locations of the pointers
  1109. X * in the current state information, and restore the locations of the pointers
  1110. X * from the old state information.  This is done by multiplexing the pointer
  1111. X * location into the zeroeth word of the state information.
  1112. X * Note that due to the order in which things are done, it is OK to call
  1113. X * setstate() with the same state as the current state.
  1114. X * Returns a pointer to the old state information.
  1115. X */
  1116. X
  1117. Xchar  *
  1118. Xsetstate( arg_state )
  1119. X
  1120. X    char        *arg_state;
  1121. X{
  1122. X    register  long        *new_state    = (long *)arg_state;
  1123. X    register  int        type        = new_state[0]%MAX_TYPES;
  1124. X    register  int        rear        = new_state[0]/MAX_TYPES;
  1125. X    char            *ostate        = (char *)( &state[ -1 ] );
  1126. X
  1127. X    if(  rand_type  ==  TYPE_0  )  state[ -1 ] = rand_type;
  1128. X    else  state[ -1 ] = MAX_TYPES*(rptr - state) + rand_type;
  1129. X    switch(  type  )  {
  1130. X        case  TYPE_0:
  1131. X        case  TYPE_1:
  1132. X        case  TYPE_2:
  1133. X        case  TYPE_3:
  1134. X        case  TYPE_4:
  1135. X        rand_type = type;
  1136. X        rand_deg = degrees[ type ];
  1137. X        rand_sep = seps[ type ];
  1138. X        break;
  1139. X
  1140. X        default:
  1141. X        fprintf( stderr, "setstate: state info has been munged; not changed.\n" );
  1142. X    }
  1143. X    state = &new_state[ 1 ];
  1144. X    if(  rand_type  !=  TYPE_0  )  {
  1145. X        rptr = &state[ rear ];
  1146. X        fptr = &state[ (rear + rand_sep)%rand_deg ];
  1147. X    }
  1148. X    end_ptr = &state[ rand_deg ];        /* set end_ptr too */
  1149. X    return( ostate );
  1150. X}
  1151. X
  1152. X
  1153. X
  1154. X/*
  1155. X * random:
  1156. X * If we are using the trivial TYPE_0 R.N.G., just do the old linear
  1157. X * congruential bit.  Otherwise, we do our fancy trinomial stuff, which is the
  1158. X * same in all ther other cases due to all the global variables that have been
  1159. X * set up.  The basic operation is to add the number at the rear pointer into
  1160. X * the one at the front pointer.  Then both pointers are advanced to the next
  1161. X * location cyclically in the table.  The value returned is the sum generated,
  1162. X * reduced to 31 bits by throwing away the "least random" low bit.
  1163. X * Note: the code takes advantage of the fact that both the front and
  1164. X * rear pointers can't wrap on the same call by not testing the rear
  1165. X * pointer if the front one has wrapped.
  1166. X * Returns a 31-bit random number.
  1167. X */
  1168. X
  1169. Xlong
  1170. Xrandom()
  1171. X{
  1172. X    long        i;
  1173. X    
  1174. X    if(  rand_type  ==  TYPE_0  )  {
  1175. X        i = state[0] = ( state[0]*1103515245 + 12345 )&0x7fffffff;
  1176. X    }
  1177. X    else  {
  1178. X        *fptr += *rptr;
  1179. X        i = (*fptr >> 1)&0x7fffffff;    /* chucking least random bit */
  1180. X        if(  ++fptr  >=  end_ptr  )  {
  1181. X        fptr = state;
  1182. X        ++rptr;
  1183. X        }
  1184. X        else  {
  1185. X        if(  ++rptr  >=  end_ptr  )  rptr = state;
  1186. X        }
  1187. X    }
  1188. X    return( i );
  1189. X}
  1190. X
  1191. END_OF_FILE
  1192.   if test 12955 -ne `wc -c <'bsd_src/random.c'`; then
  1193.     echo shar: \"'bsd_src/random.c'\" unpacked with wrong size!
  1194.   fi
  1195.   # end of 'bsd_src/random.c'
  1196. fi
  1197. if test -f 'client_lock.c' -a "${1}" != "-c" ; then 
  1198.   echo shar: Will not clobber existing file \"'client_lock.c'\"
  1199. else
  1200.   echo shar: Extracting \"'client_lock.c'\" \(5943 characters\)
  1201.   sed "s/^X//" >'client_lock.c' <<'END_OF_FILE'
  1202. X    /*********************************************************************\
  1203. X    *  Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu)   *
  1204. X    *                                                                     *
  1205. X    *  You may copy or modify this file in any manner you wish, provided  *
  1206. X    *  that this notice is always included, and that you hold the author  *
  1207. X    *  harmless for any loss or damage resulting from the installation or *
  1208. X    *  use of this software.                                              *
  1209. X    \*********************************************************************/
  1210. X
  1211. X#include "client_def.h"
  1212. X
  1213. X#ifndef NOLOCKING
  1214. Xstatic char key_string[sizeof(KEY_PREFIX)+32];
  1215. X
  1216. Xstatic char code_str[] =
  1217. X    "0123456789:_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  1218. X
  1219. Xstatic make_key_string(server_addr,server_port)
  1220. X    unsigned long  server_addr; 
  1221. X    unsigned short server_port;
  1222. X{
  1223. X    unsigned long v1, v2;
  1224. X    char *p;
  1225. X
  1226. X    strcpy(key_string,KEY_PREFIX);
  1227. X    for(p = key_string; *p; p++);
  1228. X    v1 = server_addr;
  1229. X    v2 = server_port;
  1230. X
  1231. X    *p++ = code_str[v1 & 0x3f]; v1 >>= 6;
  1232. X    *p++ = code_str[v1 & 0x3f]; v1 >>= 6;
  1233. X    *p++ = code_str[v1 & 0x3f]; v1 >>= 6; v1 = v1 | (v2 << (32-3*6));
  1234. X    *p++ = code_str[v1 & 0x3f]; v1 >>= 6;
  1235. X    *p++ = code_str[v1 & 0x3f]; v1 >>= 6;
  1236. X    *p++ = code_str[v1 & 0x3f]; v1 >>= 6;
  1237. X    *p++ = code_str[v1 & 0x3f]; v1 >>= 6;
  1238. X    *p++ = code_str[v1 & 0x3f]; v1 >>= 6;
  1239. X    *p   = 0;
  1240. X}
  1241. X#endif
  1242. X
  1243. X/********************************************************************/
  1244. X/******* For those systems that has flock function call *************/
  1245. X/********************************************************************/
  1246. X#ifdef USE_FLOCK
  1247. X
  1248. X#include <sys/file.h>
  1249. X
  1250. Xint key_persists = 1;
  1251. Xstatic unsigned int lock_fd;
  1252. Xstatic unsigned short okey;
  1253. X
  1254. Xclient_get_key()
  1255. X{
  1256. X    if(flock(lock_fd,LOCK_EX)           == -1) { perror("flock"); exit(1); }
  1257. X    if(read(lock_fd,&okey,sizeof(okey)) == -1) { perror("readk"); exit(1); }
  1258. X    if(lseek(lock_fd,0L,0)              == -1) { perror("seek"); exit(1); }
  1259. X    return(okey);
  1260. X}
  1261. X
  1262. Xclient_put_key(key)
  1263. X    unsigned short key;
  1264. X{
  1265. X    if(write(lock_fd,&key,sizeof(key)) == -1) { perror("write"); exit(1); }
  1266. X    if(lseek(lock_fd,0L,0)             == -1) { perror("seek"); exit(1); }
  1267. X    if(flock(lock_fd,LOCK_UN)          == -1) { perror("unflock"); exit(1); }
  1268. X}
  1269. X
  1270. Xclient_init_key(server_addr,server_port,key)
  1271. X    unsigned long  server_addr; 
  1272. X    unsigned short server_port;
  1273. X    unsigned short key;
  1274. X{
  1275. X    unsigned long omask;
  1276. X    okey = key;
  1277. X
  1278. X    make_key_string(server_addr,server_port);
  1279. X
  1280. X    omask = umask(0);
  1281. X    lock_fd = open(key_string,O_RDWR|O_CREAT,0666);
  1282. X    umask(omask);
  1283. X}
  1284. X
  1285. X#endif
  1286. X/********************************************************************/
  1287. X/******* For those systems that has lockf function call *************/
  1288. X/********************************************************************/
  1289. X#ifdef USE_LOCKF
  1290. X
  1291. X#include <unistd.h>
  1292. X
  1293. Xint key_persists = 1;
  1294. Xstatic unsigned int lock_fd;
  1295. Xstatic unsigned short okey;
  1296. X
  1297. Xclient_get_key()
  1298. X{
  1299. X    if(lockf(lock_fd,F_LOCK,sizeof(okey)) == -1) { perror("lockf"); exit(1); }
  1300. X    if(read(lock_fd,&okey,sizeof(okey))   == -1) { perror("readlk"); exit(1); }
  1301. X    if(lseek(lock_fd,0L,0)                == -1) { perror("seek"); exit(1); }
  1302. X    return(okey);
  1303. X}
  1304. X
  1305. Xclient_put_key(key)
  1306. X    unsigned short key;
  1307. X{
  1308. X    if(write(lock_fd,&key,sizeof(key))    == -1) { perror("write"); exit(1); }
  1309. X    if(lseek(lock_fd,0L,0)                == -1) { perror("seek"); exit(1); }
  1310. X    if(lockf(lock_fd,F_ULOCK,sizeof(key)) == -1) { perror("unlockf"); exit(1); }
  1311. X}
  1312. X
  1313. Xclient_init_key(server_addr,server_port,key)
  1314. X    unsigned long  server_addr; 
  1315. X    unsigned short server_port;
  1316. X    unsigned short key;
  1317. X{
  1318. X    unsigned long omask;
  1319. X    okey = key;
  1320. X
  1321. X    make_key_string(server_addr,server_port);
  1322. X
  1323. X    omask = umask(0);
  1324. X    lock_fd = open(key_string,O_RDWR|O_CREAT,0666);
  1325. X    umask(omask);
  1326. X}
  1327. X
  1328. X#endif
  1329. X/********************************************************************/
  1330. X/******* For those systems that has SysV shared memory + lockf ******/
  1331. X/********************************************************************/
  1332. X#ifdef USE_SHAREMEM_AND_LOCKF
  1333. X
  1334. X#include <unistd.h>
  1335. X#include <sys/ipc.h>
  1336. Xextern char *shmat();
  1337. X
  1338. Xint key_persists = 0;
  1339. Xstatic unsigned short *share_key;
  1340. Xstatic unsigned int lock_fd;
  1341. X
  1342. Xclient_get_key()
  1343. X{
  1344. X    if(lockf(lock_fd,F_LOCK,2) == -1) { perror("lockf"); exit(1); }
  1345. X    return(*share_key);
  1346. X}
  1347. X
  1348. Xclient_put_key(key)
  1349. X    unsigned short key;
  1350. X{
  1351. X    *share_key = key;
  1352. X    if(lockf(lock_fd,F_ULOCK,2) == -1) { perror("unlockf"); exit(1); }
  1353. X}
  1354. X
  1355. Xclient_init_key(server_addr,server_port,key)
  1356. X    unsigned long  server_addr; 
  1357. X    unsigned short server_port;
  1358. X    unsigned short key;
  1359. X{
  1360. X    unsigned long omask;
  1361. X    key_t lock_key;
  1362. X    int   lock_shm;
  1363. X
  1364. X    make_key_string(server_addr,server_port);
  1365. X
  1366. X    omask = umask(0);
  1367. X    lock_fd = open(key_string,O_RDWR|O_CREAT,0666);
  1368. X    umask(omask);
  1369. X
  1370. X    if((lock_key = ftok(key_string,3432)) == -1){ perror("ftok"); exit(1); }
  1371. X    if((lock_shm = shmget(lock_key,sizeof(short),IPC_CREAT|0666)) == -1)
  1372. X                        { perror("shmget"); exit(1); }
  1373. X    if(!(share_key = (unsigned short *) shmat(lock_shm,(char*)0,0)))
  1374. X                        { perror("shmat"); exit(1); }
  1375. X}
  1376. X
  1377. X#endif
  1378. X/********************************************************************/
  1379. X/******* For those who does not want to use locking *****************/
  1380. X/********************************************************************/
  1381. X#ifdef NOLOCKING
  1382. X
  1383. Xint key_persists = 0;
  1384. Xstatic unsigned short okey;
  1385. X
  1386. Xclient_get_key()
  1387. X{
  1388. X    return(okey);
  1389. X}
  1390. X
  1391. Xclient_put_key(key)
  1392. X    unsigned short key;
  1393. X{
  1394. X    okey = key;
  1395. X}
  1396. X
  1397. Xclient_init_key(server_addr,server_port,key)
  1398. X    unsigned long  server_addr; 
  1399. X    unsigned short server_port;
  1400. X    unsigned short key;
  1401. X{
  1402. X    okey = key;
  1403. X}
  1404. X
  1405. X#endif
  1406. X/********************************************************************/
  1407. X/********************************************************************/
  1408. X/********************************************************************/
  1409. END_OF_FILE
  1410.   if test 5943 -ne `wc -c <'client_lock.c'`; then
  1411.     echo shar: \"'client_lock.c'\" unpacked with wrong size!
  1412.   fi
  1413.   # end of 'client_lock.c'
  1414. fi
  1415. if test -f 'client_util.c' -a "${1}" != "-c" ; then 
  1416.   echo shar: Will not clobber existing file \"'client_util.c'\"
  1417. else
  1418.   echo shar: Extracting \"'client_util.c'\" \(11516 characters\)
  1419.   sed "s/^X//" >'client_util.c' <<'END_OF_FILE'
  1420. X    /*********************************************************************\
  1421. X    *  Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu)   *
  1422. X    *                                                                     *
  1423. X    *  You may copy or modify this file in any manner you wish, provided  *
  1424. X    *  that this notice is always included, and that you hold the author  *
  1425. X    *  harmless for any loss or damage resulting from the installation or *
  1426. X    *  use of this software.                                              *
  1427. X    \*********************************************************************/
  1428. X
  1429. X#include "client_def.h"
  1430. X
  1431. Xextern char *realloc(), *malloc(), *getenv();
  1432. Xextern long atol();
  1433. Xextern int errno;
  1434. X
  1435. Xstatic int env_dir_malloced = 0;
  1436. Xchar *env_dir = "/";
  1437. Xchar *env_myport;
  1438. Xchar *env_host;
  1439. Xchar *env_port;
  1440. Xunsigned short client_buf_len;
  1441. Xunsigned short client_net_len;
  1442. X
  1443. Xchar *util_abs_path(s2)
  1444. X    char *s2;
  1445. X{
  1446. X    char *path, *s, *d, *t;
  1447. X
  1448. X    if(!env_dir) env_dir = "";
  1449. X    if(!s2) s2 = "";
  1450. X
  1451. X    if(*s2 == '/')
  1452. X    {
  1453. X    path = malloc(strlen(s2)+2);
  1454. X    sprintf(path,"/%s",s2);
  1455. X    } else
  1456. X    {
  1457. X    path = malloc(strlen(env_dir)+strlen(s2)+3);
  1458. X    sprintf(path,"/%s/%s",env_dir,s2);
  1459. X    }
  1460. X
  1461. X    for(t = path; *t; )
  1462. X    {
  1463. X    if(t[0] == '/')
  1464. X    {
  1465. X        while(t[1] == '/') for(d = t, s = t+1; *d++ = *s++; );
  1466. X        if(t != path && t[1] == 0) { t[0] = 0; return(path); }
  1467. X    }
  1468. X    if(t[0] == '.' && t[1] == '.')
  1469. X    {
  1470. X        if(t-1 == path && t[2] ==  0 ) { *t = 0; return(path); }
  1471. X        if(t-1 == path && t[2] == '/')
  1472. X        {
  1473. X        for(d = t, s = t + 3; *d++ = *s++; );
  1474. X        continue;
  1475. X        }
  1476. X        if(t[-1] == '/' && (t[2] == '/' || t[2] ==  0))
  1477. X        {
  1478. X        s = t + 2;    /* point to either slash or nul */
  1479. X        t -= 2;        /* guaranteed that t >= path here */
  1480. X        while(t > path && t[0] != '/') t--;
  1481. X        if(t != path || *s == '/') { for(d = t; *d++ = *s++; ); }
  1482. X                      else { t[1] = 0; return(path);    }
  1483. X        continue;
  1484. X        }
  1485. X    }
  1486. X    if(t[0] == '.')
  1487. X    {
  1488. X        if(t-1 == path && t[1] ==  0 ) { *t = 0; return(path); }
  1489. X        if(t-1 == path && t[1] == '/')
  1490. X        {
  1491. X        for(d = t, s = t + 2; *d++ = *s++; );
  1492. X        continue;
  1493. X        }
  1494. X        if(t[-1] == '/' && (t[1] == '/' || t[1] ==  0))
  1495. X        {
  1496. X        s = t + 1;    /* point to either slash or nul */
  1497. X        for(d = t-1; *d++ = *s++; ); 
  1498. X        t--;
  1499. X        continue;
  1500. X        }
  1501. X    }
  1502. X    t++;
  1503. X    }
  1504. X    return(path);
  1505. X}
  1506. X
  1507. Xchar *util_getwd(p)
  1508. X    char *p;
  1509. X{
  1510. X    if(p) strcpy(p,env_dir);
  1511. X    return(p);
  1512. X}
  1513. X
  1514. XRDIRENT **get_dir_blk(path)
  1515. X    char *path;
  1516. X{
  1517. X    RDIRENT **dp;
  1518. X    char *p1, *p2, *fpath, buf[2*UBUF_SPACE];
  1519. X    unsigned long pos;
  1520. X    int cnt, k, len, rem, acc, at_eof;
  1521. X    UBUF *ub;
  1522. X
  1523. X    fpath = util_abs_path(path);
  1524. X
  1525. X    for(pos = 0, at_eof = acc = cnt = 0; ; )
  1526. X    {
  1527. X    while((acc < UBUF_SPACE) && !at_eof)
  1528. X    {
  1529. X        ub = client_interact(CC_GET_DIR,pos,
  1530. X                  strlen(fpath),fpath+1, 2,&client_net_len);
  1531. X
  1532. X        if(ub->cmd == CC_ERR)
  1533. X        {
  1534. X        fprintf(stderr,"directory reading error: %s\n",ub->buf);
  1535. X        free(fpath);
  1536. X        errno = EACCES;
  1537. X        return((RDIRENT **) 0);
  1538. X        }
  1539. X
  1540. X        if(ub->len < client_buf_len) at_eof = 1;
  1541. X        for(p1 = ub->buf, p2 = buf + acc, k = ub->len; k--; ) *p2++ = *p1++;
  1542. X        acc += ub->len;
  1543. X        pos += ub->len;
  1544. X    }
  1545. X
  1546. X    if(acc >= UBUF_SPACE) len = UBUF_SPACE;
  1547. X             else len = acc;
  1548. X
  1549. X    for(p2 = buf, rem = len, k = 0; ; k++)
  1550. X    {
  1551. X        if(rem < RDHSIZE) break;
  1552. X        if(((RDIRENT *) p2)->type == RDTYPE_SKIP) break;
  1553. X        if(((RDIRENT *) p2)->type == RDTYPE_END ) { k++; break; }
  1554. X        p2 += RDHSIZE; rem -= (RDHSIZE+1);
  1555. X        while(*p2++             ) {       rem--; }
  1556. X        while((p2 - buf) & 3) { p2++; rem--; }
  1557. X    }
  1558. X
  1559. X    p1 = malloc(p2-buf);
  1560. X    if(cnt) dp = (RDIRENT **) realloc(dp,(cnt+k+1)*sizeof(RDIRENT *));
  1561. X       else dp = (RDIRENT **)  malloc(   (cnt+k+1)*sizeof(RDIRENT *));
  1562. X
  1563. X    if(!p1 || !dp) { free(fpath);
  1564. X              fputs("directory reading out of memory\n",stderr);
  1565. X              return((RDIRENT **) 0); }
  1566. X
  1567. X    for(p2 = buf, rem = len; ; cnt++)
  1568. X    {
  1569. X        if(rem < RDHSIZE) break;
  1570. X        if(((RDIRENT *) p2)->type == RDTYPE_SKIP) break;
  1571. X        if(((RDIRENT *) p2)->type == RDTYPE_END )
  1572. X                        { dp[cnt] = 0; return(dp); }
  1573. X        dp[cnt] = (RDIRENT *) p1;
  1574. X        ((RDIRENT *) p1)->time = ntohl(((RDIRENT *) p2)->time);
  1575. X        ((RDIRENT *) p1)->size = ntohl(((RDIRENT *) p2)->size);
  1576. X        ((RDIRENT *) p1)->type =       ((RDIRENT *) p2)->type ;
  1577. X
  1578. X        p2 += RDHSIZE; p1 += RDHSIZE; rem -= (RDHSIZE+1);
  1579. X        while(*p1++ = *p2++     ) {            rem--; }
  1580. X        while((p2 - buf) & 3) { p2++; p1++; rem--; }
  1581. X    }
  1582. X
  1583. X    if(acc < UBUF_SPACE) { dp[cnt] = 0; return(dp); }
  1584. X    for(p1 = buf + UBUF_SPACE, p2 = buf, k = (acc -= UBUF_SPACE); k--; )
  1585. X                                *p2++ = *p1++;
  1586. X    }
  1587. X}
  1588. X
  1589. Xutil_download_main(path,fpath,fp,cmd)
  1590. X    char *path, *fpath;
  1591. X    FILE *fp;
  1592. X    int cmd;
  1593. X{   
  1594. X    unsigned long pos;
  1595. X    unsigned tmax, wrote, sent_time;
  1596. X    UBUF *ub;
  1597. X    for(tmax = 1, pos = 0, sent_time = 0; ; )
  1598. X    {   
  1599. X        ub = client_interact(cmd,pos, strlen(fpath),fpath+1, 2,&client_net_len);
  1600. X
  1601. X    if(client_trace && (udp_sent_time != sent_time))
  1602. X    {
  1603. X        sent_time = udp_sent_time;
  1604. X        if(client_buf_len == UBUF_SPACE)
  1605. X                    fprintf(stderr,"\r%luk  ",1+(pos>>10));
  1606. X                   else fprintf(stderr,"\r%lu   ",   pos     );
  1607. X        fflush(stderr);
  1608. X    }
  1609. X
  1610. X        if(ub->cmd == CC_ERR)
  1611. X        {    
  1612. X            fprintf(stderr,"downloading %s: %s\n",path,ub->buf);
  1613. X        return(-1); 
  1614. X        }   
  1615. X        wrote = fwrite(ub->buf,1,ub->len,fp);
  1616. X        pos  += wrote;
  1617. X        if(ub->len < client_buf_len || ub->len != wrote) break;
  1618. X    }
  1619. X
  1620. X    if(client_trace) { fprintf(stderr,"\r%luk : %s \n",1+(pos>>10),path);
  1621. X               fflush(stderr); }
  1622. X
  1623. X    return(0);
  1624. X}
  1625. X
  1626. Xutil_download(path,fp)
  1627. X    char *path;
  1628. X    FILE *fp;
  1629. X{   
  1630. X    int code;
  1631. X    char *fpath;
  1632. X
  1633. X    fpath = util_abs_path(path);
  1634. X    code = util_download_main(path,fpath,fp,CC_GET_FILE);
  1635. X    free(fpath);
  1636. X    return(code);
  1637. X}
  1638. X
  1639. Xutil_grab_file(path,fp)
  1640. X    char *path;
  1641. X    FILE *fp;
  1642. X{   
  1643. X    int code;
  1644. X    char *fpath;
  1645. X    UBUF *ub;
  1646. X
  1647. X    fpath = util_abs_path(path);
  1648. X    code = util_download_main(path,fpath,fp,CC_GRAB_FILE);
  1649. X    if(code) { free(fpath); return(code); }
  1650. X
  1651. X    ub = client_interact(CC_GRAB_DONE,0L, strlen(fpath),fpath+1, 0,NULLP);    
  1652. X
  1653. X    if(ub->cmd == CC_ERR)
  1654. X    {
  1655. X    fprintf(stderr,"Warning, unexpected grab error: %s\n",ub->buf);
  1656. X    }
  1657. X
  1658. X    free(fpath);
  1659. X    return(code);
  1660. X}
  1661. X
  1662. Xutil_upload(path,fp)
  1663. X    char *path;
  1664. X    FILE *fp;
  1665. X{   
  1666. X    unsigned long pos;
  1667. X    unsigned bytes, first, tmax, sent_time;
  1668. X    char *fpath, buf[UBUF_SPACE];
  1669. X    UBUF *ub;
  1670. X    fpath = util_abs_path(path);
  1671. X    for(tmax = 1, sent_time = 0, pos = 0, first = 1; ; first = 0)
  1672. X    {   
  1673. X    if((bytes = fread(buf,1,client_buf_len,fp)) || first)
  1674. X    {
  1675. X        ub = client_interact(CC_UP_LOAD,pos, bytes,buf, 0,NULLP);
  1676. X
  1677. X        if(client_trace && (udp_sent_time != sent_time))
  1678. X        {
  1679. X        sent_time = udp_sent_time;
  1680. X        if(client_buf_len == UBUF_SPACE)
  1681. X                    fprintf(stderr,"\r%luk  ",1+(pos>>10));
  1682. X                   else fprintf(stderr,"\r%lu   ",   pos     );
  1683. X        fflush(stderr);
  1684. X        }
  1685. X
  1686. X    } else
  1687. X    {
  1688. X        ub = client_interact(CC_INSTALL,pos,strlen(fpath),fpath+1,0,NULLP);
  1689. X    }
  1690. X        if(ub->cmd == CC_ERR)
  1691. X        {    
  1692. X            fprintf(stderr,"uploading %s: %s\n",path,ub->buf);
  1693. X        free(fpath); return(1); 
  1694. X        }   
  1695. X    if(!bytes && !first) break;
  1696. X        pos += bytes;
  1697. X    }
  1698. X
  1699. X    if(client_trace) { fprintf(stderr,"\r%luk : %s \n",1+(pos>>10),path);
  1700. X               fflush(stderr); }
  1701. X
  1702. X    free(fpath); return(0);
  1703. X}
  1704. X
  1705. Xutil_get_env()
  1706. X{
  1707. X    char *p;
  1708. X
  1709. X    if(!(env_host = getenv("FSP_HOST")))
  1710. X        { fputs("Env var FSP_HOST not defined\n",stderr); exit(1); }
  1711. X    if(!(env_port = getenv("FSP_PORT")))
  1712. X        { fputs("Env var FSP_PORT not defined\n",stderr); exit(1); }
  1713. X    if(!(env_dir  = getenv("FSP_DIR")))
  1714. X        { fputs("Env var FSP_DIR not defined\n",stderr); exit(1); }
  1715. X
  1716. X    if(!(env_myport  = getenv("FSP_LOCALPORT"))) env_myport = "0";
  1717. X
  1718. X    client_trace  = !!getenv("FSP_TRACE");
  1719. X
  1720. X    if(p = getenv("FSP_BUF_SIZE")) client_buf_len = atoi(p);
  1721. X                  else client_buf_len = UBUF_SPACE;
  1722. X
  1723. X    if(client_buf_len > UBUF_SPACE) client_buf_len = UBUF_SPACE; 
  1724. X    client_net_len = htons(client_buf_len);
  1725. X
  1726. X    if(p = getenv("FSP_DELAY")) target_delay = atol(p);
  1727. X}
  1728. X
  1729. Xvoid client_intr()
  1730. X{
  1731. X    switch(client_intr_state)
  1732. X    {
  1733. X    case 0: exit(2);
  1734. X    case 1: client_intr_state = 2; break;
  1735. X    case 2: exit(3);
  1736. X    }
  1737. X}
  1738. X
  1739. Xenv_client()
  1740. X{
  1741. X    util_get_env();
  1742. X    init_client(env_host,atoi(env_port),atoi(env_myport));
  1743. X    signal(SIGINT,client_intr);
  1744. X}
  1745. X
  1746. X/*****************************************************************************/
  1747. X
  1748. Xstatic DDLIST *ddroot = 0;
  1749. X
  1750. XRDIR *util_opendir(path)
  1751. X    char *path;
  1752. X{
  1753. X    char *fpath;
  1754. X    RDIRENT **dep;
  1755. X    DDLIST   *ddp;
  1756. X    RDIR   *rdirp;
  1757. X
  1758. X    fpath = util_abs_path(path);
  1759. X
  1760. X    for(ddp = ddroot; ddp; ddp = ddp->next) if(!strcmp(ddp->path,fpath)) break;
  1761. X
  1762. X    if(!ddp)
  1763. X    {
  1764. X    if(!(dep = get_dir_blk(fpath))) return((RDIR *) 0);
  1765. X    ddp = (DDLIST *) malloc(sizeof(DDLIST));
  1766. X    ddp->dep_root = dep;
  1767. X    ddp->path     = fpath;
  1768. X    ddp->ref_cnt  = 0;
  1769. X    ddp->next     = ddroot;
  1770. X    ddroot        = ddp;
  1771. X
  1772. X    } else free(fpath);
  1773. X
  1774. X    ddp->ref_cnt++;
  1775. X
  1776. X    rdirp = (RDIR *) malloc(sizeof(RDIR));
  1777. X    rdirp->ddp = ddp;
  1778. X    rdirp->dep = ddp->dep_root;
  1779. X    return(rdirp);
  1780. X}
  1781. X
  1782. Xutil_closedir(rdirp)
  1783. X    RDIR *rdirp;
  1784. X{
  1785. X    rdirp->ddp->ref_cnt--;
  1786. X    free(rdirp);
  1787. X}
  1788. X
  1789. Xrdirent *util_readdir(rdirp)
  1790. X    RDIR *rdirp;
  1791. X{
  1792. X    static rdirent rde;
  1793. X    RDIRENT **dep;
  1794. X
  1795. X    dep = rdirp->dep;
  1796. X
  1797. X    if(!*dep) return((rdirent *) 0);
  1798. X
  1799. X    rde.d_fileno = 10;
  1800. X    rde.d_reclen = 10;
  1801. X    rde.d_namlen = strlen((*dep)->name);
  1802. X    rde.d_name   = (*dep)->name;
  1803. X    rdirp->dep   = dep+1;
  1804. X
  1805. X    return(&rde);
  1806. X}
  1807. X
  1808. Xutil_split_path(path,p1,p2,p3)
  1809. X    char *path, **p1, **p2, **p3;
  1810. X{
  1811. X    char *s;
  1812. X    static char junk;
  1813. X
  1814. X    *p1 = "/";
  1815. X    if(*path == '/') { *p2 =  path; *p3 = path+1; }
  1816. X        else { *p2 = &junk; *p3 = path  ; }
  1817. X
  1818. X    for(s = *p3; *s; s++)
  1819. X    {
  1820. X    if(*s == '/')
  1821. X    {
  1822. X        *p1 = path;
  1823. X        *p2 = s;
  1824. X        *p3 = s+1;
  1825. X    }
  1826. X    }
  1827. X
  1828. X    if (**p3 == '\0') *p3 = ".";
  1829. X    return(1);
  1830. X}
  1831. X
  1832. Xutil_stat(path,sbuf)
  1833. X    char *path;
  1834. X    struct stat *sbuf;
  1835. X{
  1836. X    RDIR *drp;
  1837. X    RDIRENT **dep;
  1838. X    char *fpath, *ppath, *p1, *pfile;
  1839. X
  1840. X    fpath = util_abs_path(path);
  1841. X
  1842. X    if(!strcmp(fpath,env_dir))
  1843. X    {
  1844. X    ppath = fpath;
  1845. X    pfile = ".";
  1846. X
  1847. X    } else
  1848. X    {
  1849. X    util_split_path(fpath,&ppath,&p1,&pfile); *p1 = 0;
  1850. X    }
  1851. X
  1852. X    if(drp = util_opendir(ppath))
  1853. X    {
  1854. X    for(dep = drp->dep; *dep; dep++)
  1855. X    {
  1856. X        if(!strcmp((*dep)->name,pfile))
  1857. X        {
  1858. X        if((*dep)->type & RDTYPE_DIR) sbuf->st_mode = 0777 | S_IFDIR;
  1859. X                     else sbuf->st_mode = 0666 | S_IFREG;
  1860. X
  1861. X        if((*dep)->type & RDTYPE_DIR) sbuf->st_nlink  = 2;
  1862. X                     else sbuf->st_nlink  = 1;
  1863. X        sbuf->st_uid    = 0;
  1864. X        sbuf->st_gid    = 0;
  1865. X        sbuf->st_size   = (*dep)->size;
  1866. X        sbuf->st_atime  = (*dep)->time;
  1867. X        sbuf->st_mtime  = (*dep)->time;
  1868. X        sbuf->st_ctime  = (*dep)->time;
  1869. X        util_closedir(drp); free(fpath); return(0);
  1870. X        }
  1871. X    }
  1872. X    util_closedir(drp);
  1873. X    }
  1874. X
  1875. X    free(fpath); errno = ENOENT; return(-1);
  1876. X}
  1877. X
  1878. Xutil_cd(p)
  1879. X    char *p;
  1880. X{
  1881. X    char *fpath;
  1882. X    UBUF *ub;
  1883. X    DDLIST   *ddp;
  1884. X
  1885. X    fpath = util_abs_path(p);
  1886. X    for(ddp = ddroot; ddp; ddp = ddp->next) if(!strcmp(ddp->path,fpath)) break;
  1887. X
  1888. X    if(!ddp && strcmp(p,".") && strcmp(p,".."))
  1889. X    {
  1890. X    ub = client_interact(CC_GET_DIR,0L, strlen(fpath),fpath+1,
  1891. X                            2,&client_net_len);
  1892. X    if(ub->cmd == CC_ERR)
  1893. X    {
  1894. X        free(fpath);
  1895. X        fprintf(stderr,"cd error: %s\n",ub->buf);
  1896. X        errno = EACCES;
  1897. X        return(-1);
  1898. X    }
  1899. X    }
  1900. X
  1901. X    if(env_dir_malloced) free(env_dir);
  1902. X    env_dir_malloced = 1;
  1903. X    env_dir = fpath;
  1904. X    return(0);
  1905. X}
  1906. X
  1907. Xutil_cd2(p)    /* Perform a cd, but don't verify path.  Assume the path */
  1908. X    char *p;    /* has been verified by another mechanism.         */
  1909. X{
  1910. X    char *fpath;
  1911. X
  1912. X    fpath = util_abs_path(p);
  1913. X
  1914. X    if(env_dir_malloced) free(env_dir);
  1915. X    env_dir_malloced = 1;
  1916. X    env_dir = fpath;
  1917. X    return(0);
  1918. X}
  1919. END_OF_FILE
  1920.   if test 11516 -ne `wc -c <'client_util.c'`; then
  1921.     echo shar: \"'client_util.c'\" unpacked with wrong size!
  1922.   fi
  1923.   # end of 'client_util.c'
  1924. fi
  1925. echo shar: End of archive 2 \(of 4\).
  1926. cp /dev/null ark2isdone
  1927. MISSING=""
  1928. for I in 1 2 3 4 ; do
  1929.     if test ! -f ark${I}isdone ; then
  1930.     MISSING="${MISSING} ${I}"
  1931.     fi
  1932. done
  1933. if test "${MISSING}" = "" ; then
  1934.     echo You have unpacked all 4 archives.
  1935.     rm -f ark[1-9]isdone
  1936. else
  1937.     echo You still must unpack the following archives:
  1938.     echo "        " ${MISSING}
  1939. fi
  1940. exit 0
  1941. exit 0 # Just in case...
  1942.