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

  1. Newsgroups: comp.sources.misc
  2. From: wen-king@vlsi.cs.caltech.edu (Wen-King Su)
  3. Subject:  v34i075:  fsp - Internet archive server and client software, Part01/04
  4. Message-ID: <csm-v34i075=fsp.103634@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: e53f6328197817d4cfab9d251250eef6
  6. Date: Fri, 18 Dec 1992 16:38:16 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 75
  11. Archive-name: fsp/part01
  12. Environment: UNIX, Sockets
  13.  
  14. This is version 2.6.4 of FSP.  This supersedes the version previously
  15. posted in comp.sources.unix.
  16.  
  17. FSP is a set of programs that implements a public-access archive
  18. similar to an anonymous-FTP archive.  It is not meant to be a
  19. replacement for ftp; it is only meant to do what anonymous-ftp
  20. does, but in a manner more acceptible to the provider of the
  21. service and more friendly to the clients. 
  22.  
  23. Providing anonymous-FTP service can be costly --- each active
  24. session consumes one process slot in the OS and one stream socket
  25. entry in the network sub-system.  The servers can also run
  26. concurrently, adding to the system load.  A popular archive site
  27. can easily be overwhelmed as a result.
  28.  
  29. FSP seeks to overcome the problem using a single server that
  30. handles an arbitrary number of concurrent transactions while
  31. keeping the load added to the server machine to one or below.
  32. ---
  33. #! /bin/sh
  34. # This is a shell archive.  Remove anything before this line, then feed it
  35. # into a shell via "sh file" or similar.  To overwrite existing files,
  36. # type "sh file -c".
  37. # Contents:  INFO Makefile bsd_src server_file.c server_lib.c
  38. # Wrapped by kent@sparky on Fri Dec 18 10:21:24 1992
  39. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  40. echo If this archive is complete, you will see the following message:
  41. echo '          "shar: End of archive 1 (of 4)."'
  42. if test -f 'INFO' -a "${1}" != "-c" ; then 
  43.   echo shar: Will not clobber existing file \"'INFO'\"
  44. else
  45.   echo shar: Extracting \"'INFO'\" \(16037 characters\)
  46.   sed "s/^X//" >'INFO' <<'END_OF_FILE'
  47. X                        Interested party please email
  48. X                        wen-king@vlsi.cs.caltech.edu
  49. X    What is the purpose of FSP (V2.6):
  50. X
  51. X    FSP is a set of programs that implements a public-access archive
  52. X    similar to an anonymous-FTP archive.  It is not meant to be a
  53. X    replacement for ftp; it is only meant to do what anonymous-ftp
  54. X    does, but in a manner more acceptible to the provider of the
  55. X    service and more friendly to the clients. 
  56. X
  57. X    Providing anonymous-FTP service can be costly --- each active
  58. X    session consumes one process slot in the OS and one stream socket
  59. X    entry in the network sub-system.  The servers can also run
  60. X    concurrently, adding to the system load.  A popular archive site
  61. X    can easily be overwhelmed as a result.  Some were forced to
  62. X    shutdown or and some impose inconvienent access restrictions. 
  63. X
  64. X    Unlike FTP, FSP is connection-less and virtually state-less.  One
  65. X    server handles requests from all clients machines.  Each active
  66. X    client machine takes up 16-bytes in a dynamically extensible
  67. X    table.  Since only one server exists on a server machine at any
  68. X    time, the load added to the server machine is no more than one. 
  69. X
  70. X    In exchange for allowing site operators to keep their sites open
  71. X    and do away with cumbersome access restrictions, this is what the
  72. X    clients accept with FSP: 
  73. X
  74. X     1) Lower transfer rate.  The maximum rate is 1 kbyte per UDP
  75. X        message round-trip time between the client and the server.
  76. X    
  77. X    In addition to the potential for more abundant sites and more
  78. X    accessible sites, this is what the clients gain with FSP:
  79. X
  80. X     1) Robustness.  Since FSP is connectionless, flucturations in
  81. X        the network will not abort a FSP transaction.  Furthermore,
  82. X        the 16-bytes of data for each client can be regenerated at
  83. X        any point during any transaction.  Thus, if the server goes
  84. X        down at any point during a transaction, the transaction will
  85. X        resume when the server is restarted.  (like NFS) 
  86. X
  87. X     2) Friendlier user interface.  FSP does not have its own command
  88. X        interpretor like FTP.  Since it is connectionless, there is
  89. X        no reason to carry much information from one command to the
  90. X        next, and the commands can all be made into individual unix
  91. X        programs.  For instance, there is one program you run to list
  92. X        the directory and another you run to download a file. 
  93. X
  94. X     3) Client protection.  FSP oversees a directory structure similar
  95. X        to that of an anonymous-FTP.  However, a directory created
  96. X        via FSP transaction is owned by the client machine that issued
  97. X        the creation request.  The client can create and delete files
  98. X        and subdirectories in that directory.  In addition, the client
  99. X        can enable any of the two attributes for that directory: 
  100. X
  101. X        A) Give all other clients the permission to create files
  102. X           and subdirectries.
  103. X
  104. X        B) Give all other clients the permission to delete files
  105. X           and subdirectories.
  106. X
  107. X        Note: A subdirectory can be deleted if it is empty and the
  108. X          client owns the subdirectory.
  109. X
  110. X     4) Server protection.  FSP server does not spawn sub-programs.
  111. X        It will accept only paths that are downward relative to its
  112. X        designated working directory.  On systems with symbolic links,
  113. X        the server will follow symbolic links, but it does not follow
  114. X        uplinks ("..").  Clients cannot create symbolic links and
  115. X        care should be taken so that other users on the server machine
  116. X        cannot create symbolic links in the server's work space. 
  117. X
  118. X        It is also fairly difficult to formuate an attack to force a
  119. X        shutdown of a FSP site by actions of a rogue site.  About the
  120. X        only way to distrupt a FSP service is to flood the FSP site
  121. X        with network packets.  FSP server prevents itself from
  122. X        'counter-flooding' by filtering for legitimate requests using
  123. X        the following method:
  124. X
  125. X        A) Each request message contains a key.  For each client,
  126. X           server database contains the keys to be used for the
  127. X           next client request and for the previous client request.
  128. X
  129. X        B) If the next request does not contain a key that matches
  130. X           either of the two keys, it is accepted only if at least
  131. X           one minute has elapsed since the last time a request
  132. X           is accepted.  If the key does match the old key
  133. X           (retransmit by client) it is accepted if the elapse time
  134. X           is greater than 3 seconds.
  135. X
  136. X        C) Every request message accepted is acknowledged with
  137. X           one reply message.  The reply message contains a new
  138. X           key to used for the next request.  The new key is
  139. X           computed by the server with a pseudo-random number
  140. X           generator. 
  141. X
  142. X        Flooding is a ballant violation of network etiquette because
  143. X        a site can be subjected to flooding attack whether it has FSP
  144. X        running or not, and flooding congests every link and gateway
  145. X        between the rogue client and the server.  As a further measure
  146. X        of protection, the server loads a table of rogue clients on
  147. X        startup.  The server will not respond to requests from any of
  148. X        those clients.
  149. X
  150. X    The software set:
  151. X
  152. X    common_def.h    This C header file contains definitions common to
  153. X            both the server code and the client code.
  154. X
  155. X    client_def.h    This C header file contains definitions for the
  156. X            client code.
  157. X
  158. X    server_def.h    This C header file contains definitions for the
  159. X            server code.
  160. X
  161. X    udp_io.c    This file contains the lowest level routines that
  162. X            deal with the unix inet sockets.  This file is
  163. X            used by both the server code and the client code.
  164. X
  165. X    server_main.c    Main routine and dispatch loop for the server.
  166. X    server_host.c    Routines for maintaining client database.
  167. X    server_file.c    Routines for file i/o.
  168. X    server_lib.c    Routines for inet socket i/o.
  169. X
  170. X    client_lib.c    Core routines of the client library.
  171. X    client_util.c    Supplementry routines of the client library.
  172. X    client_lock.c    udp packet multiplexing mechanism.
  173. X
  174. X    bsd_src/    Directory containing additional sources derived
  175. X            from those in public archive on uunet.uu.net.  It
  176. X            contains a BSD random/srandom routine, a modified
  177. X            BSD globbing routine, a modified "ls" source.
  178. X
  179. X    fcdcmd.c    These compiles into individual client utilities.
  180. X    fgetcmd.c    Those with a "cmd" in their name will do their
  181. X    flscmd.c    own globbing on their argv base on directory
  182. X    fprocmd.c    information obtained from the server.
  183. X    frmcmd.c
  184. X    frmdircmd.c
  185. X    fcatcmd.c
  186. X    fmkdir.c
  187. X    fput.c
  188. X    fver.c
  189. X    fgrab.c
  190. X
  191. X    merge.c        This file is used to call the other client programs
  192. X            when program merging option is used.  Rather than
  193. X            compiling into individual client utility programs,
  194. X            users may opt to build a single program which
  195. X            contains all client funtionalities, which are to
  196. X            be distinguished at run time by the name used to
  197. X            activate the program.  Significant space saving can
  198. X            be achieved on some machines. 
  199. X
  200. X    Compilation:
  201. X
  202. X    FSP has been compiled and tested by me on a SS-2 running SunOs
  203. X    4.1.1, a HP-9000 running HP UNIX, a VAX-780 running 4.3-tahoe,
  204. X    and a 386 box running system-V UNIX with old Excelan ethernet
  205. X    interface.  It has also been compiled on a variety of machines
  206. X    by over hundreds users all over the world. 
  207. X
  208. X    To compile the software, you must first successfully complete a
  209. X    "make" in the bsd_src directory.  You may have to change a few
  210. X    files.  In particular, you may have to edit "Makefile" and "tweak.h"
  211. X    in bsd_src directory. 
  212. X
  213. X    When that is done, you can edit the Makefile on the top directory
  214. X    and run "make" in the top directory, or "make merge" if you want
  215. X    to combine all client programs into one single file.  You may wish
  216. X    to read through the rest of this document first before making
  217. X    changes to the Makefile. 
  218. X
  219. X    After "make" or "make merge" finished, you may use "make install"
  220. X    or "make install-merge" to install the programs.  Man pages may be
  221. X    installed by "make installm".
  222. X
  223. X    IMPORTANT NOTE: You do not need to run the fspd process if you only
  224. X    want to access existing fsp archives.  fspd processs is needed only
  225. X    if you want to setup and archive for public access.
  226. X
  227. X    Server Administration:
  228. X
  229. X    The only things you need for setting up a FSP server is a work
  230. X    directory for the service and and the FSP server itself (fspd).
  231. X    fspd can run independently or it can be run under inetd.  When
  232. X    running independently, fspd waits for messages through a UDP
  233. X    socket whoes port number is defined in the Makefile.  When running
  234. X    under inetd, fspd is involked as in.fspd.  inetd will spawn fspd
  235. X    when a message arrives for the FSP socket.  The fspd process will
  236. X    take over and stick around to wait on additional messages.  After
  237. X    it has become idle for 2 minutes, fspd will exit and return control
  238. X    to inetd. 
  239. X
  240. X    Sample setup for inetd operation:
  241. X
  242. X        In /etc/services file:
  243. X
  244. X        fsp             21/udp          fspd
  245. X
  246. X        In /etc/inetd.conf file:
  247. X
  248. X        fsp dgram   udp wait ftp /usr/etc/fspd in.fspd
  249. X
  250. X        In this sample, the same port number for ftp is used for the
  251. X        fsp socket.  There will not be a conflict because ftp uses
  252. X        stream protocol, and fsp uses UDP protocol.  The fspd program
  253. X        in this example is ran under user 'ftp'. 
  254. X
  255. X    In addition, fspd will accept these flags:
  256. X
  257. X        -h absolute_path    Set fsp work directory.  Overrides the
  258. X                compiled-in default.
  259. X
  260. X        -p udp_port_number  Set UDP port number.  Overrides the
  261. X                compiled-in default.
  262. X
  263. X        -u uid_number       Assume this uid after startup.  If present,
  264. X                fspd will attempt a setuid() to this uid
  265. X                number.  It will exit if setuid() fails.
  266. X
  267. X        -d                  Turn on debug mode.  The stdio files will
  268. X                remain open in debugging mode.
  269. X
  270. X    When fspd starts, it chdir to its work directory where it looks
  271. X    for (and reads in if found) a list of internet numbers in the
  272. X    standard 4-part form: ddd.ddd.ddd.ddd in the file ".ROGUE_HOSTS".
  273. X    This file is prepared by the FSP maintainer, and is used to
  274. X    indicate that fspd should not respond to any requests from these
  275. X    machines.   After that, it begins to service any requests it gets
  276. X    on the UDP socket.
  277. X
  278. X    If a file .OWN.XXXXXXXX, where XXXXXXXX is an 8-digit hex number,
  279. X    exists in a directory in fspd's work space, the directory is owned
  280. X    by the machine whoes inet number is XXXXXXXX (an integer stored
  281. X    in the network byte order), where the number is printed as a
  282. X    hexadecimal number.  If no such file exists, the directory has
  283. X    no owner.  (Note, the 'dot' files are hidden from clients). 
  284. X
  285. X    If the file .FSP_OK_DEL does not exists in a directory, only the
  286. X    owner is allowed to remove items from that directory. 
  287. X
  288. X    If the file .FSP_OK_ADD does not exists in a directory, only the
  289. X    owner is allowed to add items into that directory. 
  290. X
  291. X    Thus, you typically want to protect the top directory by leaving
  292. X    out the .FSP_OK_DEL, .FSP_OK_ADD files, and .OWN.XXXXXXXX files
  293. X    in the top directory. 
  294. X
  295. X    Clients do not get to read the directory information directly.
  296. X    Instead, fspd maintains a directory listing for each directory
  297. X    in a cache file.  If the directory is writable by fspd, or if a
  298. X    writable file in it is prepared beforehand, fspd will store the
  299. X    directory information in .FSP_CONTENT file in that directory.
  300. X    Otherwise, it will store the information in a pair of files (with
  301. X    hashed names) in a special directory specified by the variable
  302. X    DEF_DIRECTORY_CACHE in Makefile.  The later allows read-only
  303. X    directories to be exported. 
  304. X
  305. X    When a client requests information for a directory, the cache
  306. X    file is created if it doesn't exist, and it is rebuilt if it is
  307. X    out of date.  The information is accessed by having the client
  308. X    read the directory listing file. Care is taken so that the client
  309. X    will not get corrupted entries when the directory is changed while
  310. X    the listing is being read.
  311. X
  312. X    Files being uploaded are first written to a temporary file in the
  313. X    work directory: .TXXXXXXXXYYYY where XXXXXXXX is the inet number
  314. X    of the client, and YYYY is the port number of the client program.
  315. X    When upload is compelete, the file is moved into the intended
  316. X    location. 
  317. X
  318. X    Sending it an 'alarm' signal will cause fspd to dump its current
  319. X    client database into the file .HTAB_DUMP in the work directory.
  320. X    This can be useful for debugging and for catching rogue clients.
  321. X
  322. X    Client utilities:
  323. X
  324. X    All inter-command states are kept in these three shell environment
  325. X    variables.
  326. X
  327. X        FSP_PORT        Port number of the fspd you wish to contact.
  328. X        FSP_HOST        Host name or number of the fspd.
  329. X        FSP_DIR        Your current working directory in the archive.
  330. X
  331. X    When multiple client utilities are run at the same time on the
  332. X    same client machine, packet multiplexing mechanisms can be used
  333. X    to enable concurrent access to the same fsp database.  If none
  334. X    of the mechanisms are selected at compile time, FSP_LOCALPORT
  335. X    can be used to ensure that only once client utility can run at
  336. X    any time.  In this case, FSP_LOCALPORT can be set to any port
  337. X    number not current used on the client machine.
  338. X
  339. X    FSP_TRACE can be set if you want status reports be printed while
  340. X    files are being transferred.  FSP_DELAY variable can be used to
  341. X    set the retransmit interval for client utilities (in thousandth
  342. X    of a second).  The retransmit rate is adjusted in an exponential
  343. X    manner, until the retry rate reaches 5 mintes per retry.
  344. X
  345. X    FSP_BUF_SIZE can be set to a positive number less than or equal
  346. X    to 1024.  When set, it determines the size of data to be send for
  347. X    each request during file and directory information transfer.  The
  348. X    default is 1024.  Some sites are connected via links that cannot
  349. X    transmit buffers containing 1024 bytes of data in addition to the
  350. X    header information.  Setting FSP_BUF_SIZE to a lower value will
  351. X    allow these sites to access fsp archives.
  352. X
  353. X    A typical setup looks like this:
  354. X
  355. X        setenv FSP_PORT     21
  356. X        setenv FSP_HOST     131.215.131.97
  357. X        setenv FSP_DIR     /
  358. X        setenv FSP_TRACE
  359. X        setenv FSP_DELAY     3000
  360. X        setenv FSP_BUF_SIZE  1024
  361. X
  362. X    (All examples will be in csh.  However, it is assumed that similar
  363. X     things can be done with other shells)
  364. X
  365. X    For commands that do globbing using remote directory info, normal
  366. X    shell globbing needs to be turned off.  In csh, it can be done
  367. X    with a set of aliases: 
  368. X
  369. X        alias fcd setenv FSP_DIR \`\(set noglob\; exec fcdcmd \!\*\)\`
  370. X        alias fls    \(set noglob\; exec flscmd    \!\*\)
  371. X        alias fget   \(set noglob\; exec fgetcmd   \!\*\)
  372. X        alias fgrab  \(set noglob\; exec fgrabcmd  \!\*\)
  373. X        alias fcat   \(set noglob\; exec fcatcmd   \!\*\)
  374. X        alias frm    \(set noglob\; exec frmcmd    \!\*\)
  375. X        alias frmdir \(set noglob\; exec frmdircmd \!\*\)
  376. X        alias fpro   \(set noglob\; exec fprocmd   \!\*\)
  377. X    
  378. X    In addtion, these alias are useful:
  379. X
  380. X        alias fpwd echo \$FSP_DIR on \$FSP_HOST port \$FSP_PORT
  381. X        alias fsethost setenv FSP_DIR \/\; setenv FSP_HOST \!\:1\; \
  382. X                           setenv FSP_PORT \!\:2
  383. X
  384. X        The second one is a user contribution.  It allows one to set
  385. X        the FSP_HOST, FSP_PORT, and to initialize FSP_DIR in one command.
  386. X
  387. X    Commands:
  388. X
  389. X        fver    display server's version number.
  390. X        fcd        change current remote directory, like cd.
  391. X        fls        list directory.  works like ls.
  392. X        fget    get the named files.
  393. X        fgrab    get the named file and delete it from remote directory.
  394. X        fput    put the named files.
  395. X        fcat    get the named files and send them to stdout.
  396. X        fmkdir    make named directories.
  397. X        frm        delete named files.
  398. X        frmdir    delete named directories.
  399. X
  400. X        fpro    no arg: display directory protection modes.
  401. X                +c: give others permission to create new items.
  402. X                -c: deny others permission to create new items.
  403. X                +d: give others permission to delete old items.
  404. X                -d: deny others permission to delete old items.
  405. X
  406. X    ***********************************************************************
  407. X
  408. X    This is a free software.  Be creative; make your own macros and tools
  409. X    and let me know of any bugs and suggestions.
  410. X
  411. X    A mailing list for the discussion of the FSP software is now available
  412. X    (started Oct 2, 1992.)  To get on the list, send an email stating
  413. X    that you want to be on the FSP list to the following address:
  414. X
  415. X        listmaster@Germany.EU.net
  416. X
  417. X    Articles to be distributed to the subscribers should be sent to the
  418. X    following email address:
  419. X
  420. X        fsp-discussion@Germany.EU.net
  421. END_OF_FILE
  422.   if test 16037 -ne `wc -c <'INFO'`; then
  423.     echo shar: \"'INFO'\" unpacked with wrong size!
  424.   fi
  425.   # end of 'INFO'
  426. fi
  427. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  428.   echo shar: Will not clobber existing file \"'Makefile'\"
  429. else
  430.   echo shar: Extracting \"'Makefile'\" \(13388 characters\)
  431.   sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  432. X#############################################################################
  433. X# You need to do a successful 'make' in the bsd_src directory first before
  434. X# trying to run 'make' in this directory.  The bsd_src directory contains
  435. X# several files derived from those found in the ftp.uu.net archive.
  436. X# Run "make install" to install binaries.
  437. X# Run "make installm" to install man pages.
  438. X# Run "make de-install" to remove installed binaries and man pages.
  439. X
  440. X#############################################################################
  441. X# This is where you want to install the binary
  442. X#
  443. XBIN=/usr/local/bin
  444. X
  445. X#############################################################################
  446. X# This is where you want to install the man pages, don't worry about it if
  447. X# you don't plan to install man pages.
  448. X#
  449. XMAN=/usr/local/man/man1
  450. X
  451. X#############################################################################
  452. X# If you want to provide FSP service, this should be set to the working
  453. X# directory of the FSP server.  Don't worry about it and other server-related
  454. X# definitions if you do not plan to start a FSP server.
  455. X#
  456. XDEF_FSP_HOME=/usr/tmp/fsp_home
  457. X
  458. X#############################################################################
  459. X# If the server is to run on a machine with file name length limit, set the
  460. X# following variable to the length.  Otherwise, set it to something big.
  461. X#
  462. XFILE_NAME_LIMIT=99999
  463. X
  464. X#############################################################################
  465. X# If you want to provide FSP service, this should be set to the UDP socket
  466. X# port number the FSP server should use.
  467. X#
  468. XDEF_FSP_PORT=21
  469. X
  470. X#############################################################################
  471. X# FSP servers normally keep a directory listing file in each directory it
  472. X# exports.  In situation where this is not appropriate, FSP can store the
  473. X# listing in another directory instead.  DEF_DIRECTORY_CACHE should contain
  474. X# a directory where such a listing is to be placed.  The path is relative
  475. X# to DEF_FSP_HOME unless it starts with a '/'.  FSP server also uses this
  476. X# directory to hold temporary files during upload, so this variable must
  477. X# refer to a valid directory even if all subdirectories are writable by
  478. X# the fspd process.
  479. X
  480. XDEF_DIRECTORY_CACHE=.
  481. X
  482. X# MAX_DIR_CACHE_COUNT should contain the number of listings to be cached in
  483. X# DEF_DIRECTORY_CACHE.  The number should be a power of 2.
  484. X
  485. XMAX_DIR_CACHE_COUNT=16
  486. X
  487. X# ALWAYS_USE_CACHE_DIR should be 1 if you want it used as the default way to
  488. X# store directory listing files.  (Note, .FSP_CONTENT files will still be
  489. X# used if they alreay exist.
  490. X
  491. XALWAYS_USE_CACHE_DIR=0
  492. X
  493. X#############################################################################
  494. X# This is where the version number string comes from:
  495. X#
  496. XVERSION_STR="Original Caltech version 2.6.4, December 1992"
  497. X
  498. X#############################################################################
  499. X# FSP uses BSD random/srandom functions.  If your system does not have
  500. X# them, include them from the bsd_src directory.
  501. X#
  502. X#RANDOM=bsd_src/random.o
  503. X
  504. X#############################################################################
  505. X# Below are definitions related to the client utilities.
  506. X#############################################################################
  507. X# If your machine has either lockf or flock functions, you may be able to
  508. X# compile the client codes so that multiple client commands can be run
  509. X# concurrently.  Uncomment one of the following and set the LOCK_PREFIX
  510. X# string appropriately.  In most cases, they are prefixes used to create 
  511. X# a lock file in your file system.  There are some restrictions, for example
  512. X# on SunOS, lock files may not be on a file system of type tmp.  The most
  513. X# efficient locking choice is the one that uses SysV shared memory plus lockf.
  514. X# Note, it is possible for some UNIX to have hooks for the locking mechanism
  515. X# exist in the C library but unsupported in the kernel.  In such a case,
  516. X# compilation will complete normally, but you will get run time errors.
  517. X#
  518. X#LOCK_FLAGS= -DUSE_SHAREMEM_AND_LOCKF -DKEY_PREFIX=\"/usr/tmp/.FL\"
  519. X#LOCK_FLAGS= -DUSE_FLOCK -DKEY_PREFIX=\"/usr/tmp/.FL\"
  520. X#LOCK_FLAGS= -DUSE_LOCKF -DKEY_PREFIX=\"/usr/tmp/.FL\"
  521. XLOCK_FLAGS= -DNOLOCKING
  522. X
  523. X#############################################################################
  524. X# The following variable defines the compiler to use in your compilation.
  525. XCC=cc
  526. X
  527. X#############################################################################
  528. X# Include -DDIRENT in CFLAGS if you have /usr/include/dirent.h.
  529. X# Remove  -DDIRENT if you do not.
  530. XCFLAGS=-g -DDIRENT
  531. X
  532. X#############################################################################
  533. X# If you need to link in any additional libraries, do it here.
  534. X# AT&T 3B2/600G + AT&T Unix Sys V R 3.2.3 + WIN/TCP R 3.2 use -lnet -lnsl_s 
  535. XLIB=
  536. X
  537. XSHELL=/bin/sh
  538. X
  539. XPROGS=    flscmd fcdcmd fgetcmd frmcmd frmdircmd fprocmd \
  540. X    fmkdir fput fver fcatcmd fgrabcmd
  541. X
  542. XIPROGS=    ${BIN}/flscmd ${BIN}/fcdcmd \
  543. X    ${BIN}/fgetcmd ${BIN}/frmcmd ${BIN}/frmdircmd ${BIN}/fprocmd \
  544. X    ${BIN}/fmkdir ${BIN}/fput ${BIN}/fver ${BIN}/fcatcmd ${BIN}/fgrabcmd
  545. X
  546. XIMANS=    ${MAN}/fcatcmd.1 ${MAN}/fcat.1 ${MAN}/fcdcmd.1 ${MAN}/fcd.1 \
  547. X    ${MAN}/fgetcmd.1 ${MAN}/fget.1 ${MAN}/flscmd.1 ${MAN}/fls.1 \
  548. X    ${MAN}/fmkdir.1 ${MAN}/fprocmd.1 ${MAN}/fpro.1 ${MAN}/fput.1 \
  549. X    ${MAN}/frmcmd.1 ${MAN}/frm.1 ${MAN}/frmdircmd.1 ${MAN}/frmdir.1 \
  550. X    ${MAN}/fspd.1 ${MAN}/fver.1 ${MAN}/fgrab.1 ${MAN}/fgrabcmd.1
  551. X
  552. Xall:
  553. X    @ cd bsd_src; make CC="${CC}" CFLAGS="${CFLAGS}"
  554. X    @ make all1
  555. X
  556. Xmerge:
  557. X    @ cd bsd_src; make
  558. X    @ make fspd fsp_client_merge
  559. X
  560. Xall1:      ${PROGS} fspd
  561. Xinstall:  ${IPROGS} ${BIN}/fspd
  562. Xinstallm: ${IMANS}
  563. X
  564. Xinstall-merge: ${BIN}/fspd fsp_client_merge
  565. X    - rm -f ${IPROGS} ${BIN}/fsp_client_merge
  566. X    cp fsp_client_merge ${BIN}/fsp_client_merge
  567. X    for A in ${IPROGS} ; do ln ${BIN}/fsp_client_merge $$A; done
  568. X    rm -f ${BIN}/fsp_client_merge
  569. X
  570. XSERVER_OBJ= server_main.o server_lib.o server_host.o udp_io.o server_file.o
  571. XCLIENT_OBJ= client_lib.o udp_io.o client_util.o client_lock.o
  572. XGLOB_OBJ= bsd_src/glob.o
  573. XUTIL_LS_OBJ= bsd_src/cmp.o bsd_src/ls.o bsd_src/print.o bsd_src/util.o \
  574. X        ${GLOB_OBJ}
  575. X
  576. X#############################################################################
  577. X
  578. Xfspd: ${SERVER_OBJ} ${RANDOM}
  579. X    ${CC} ${CFLAGS} -o fspd ${SERVER_OBJ} ${RANDOM} ${LIB}
  580. X
  581. Xfgetcmd: fgetcmd.o ${CLIENT_OBJ} ${GLOB_OBJ}
  582. X    ${CC} ${CFLAGS} -o fgetcmd fgetcmd.o ${CLIENT_OBJ} ${GLOB_OBJ} ${LIB}
  583. X
  584. Xfgrabcmd: fgrabcmd.o ${CLIENT_OBJ} ${GLOB_OBJ}
  585. X    ${CC} ${CFLAGS} -o fgrabcmd fgrabcmd.o ${CLIENT_OBJ} ${GLOB_OBJ} ${LIB}
  586. X
  587. Xfcatcmd: fcatcmd.o ${CLIENT_OBJ} ${GLOB_OBJ}
  588. X    ${CC} ${CFLAGS} -o fcatcmd fcatcmd.o ${CLIENT_OBJ} ${GLOB_OBJ} ${LIB}
  589. X
  590. Xfput: fput.o ${CLIENT_OBJ}
  591. X    ${CC} ${CFLAGS} -o fput fput.o ${CLIENT_OBJ} ${LIB}
  592. X
  593. Xfrmcmd: frmcmd.o ${CLIENT_OBJ} ${GLOB_OBJ}
  594. X    ${CC} ${CFLAGS} -o frmcmd frmcmd.o ${CLIENT_OBJ} ${GLOB_OBJ} ${LIB}
  595. X
  596. Xflscmd: flscmd.o ${CLIENT_OBJ} ${UTIL_LS_OBJ}
  597. X    ${CC} ${CFLAGS} -o flscmd flscmd.o ${CLIENT_OBJ} ${UTIL_LS_OBJ} ${LIB}
  598. X
  599. Xfcdcmd: fcdcmd.o ${CLIENT_OBJ} ${GLOB_OBJ}
  600. X    ${CC} ${CFLAGS} -o fcdcmd fcdcmd.o ${CLIENT_OBJ} ${GLOB_OBJ} ${LIB}
  601. X
  602. Xfrmdircmd: frmdircmd.o ${CLIENT_OBJ} ${GLOB_OBJ}
  603. X    ${CC} ${CFLAGS} -o frmdircmd frmdircmd.o ${CLIENT_OBJ} ${GLOB_OBJ} \
  604. X                                    ${LIB}
  605. X
  606. Xfprocmd: fprocmd.o ${CLIENT_OBJ} ${GLOB_OBJ}
  607. X    ${CC} ${CFLAGS} -o fprocmd fprocmd.o ${CLIENT_OBJ} ${GLOB_OBJ} ${LIB}
  608. X
  609. Xfmkdir: fmkdir.o ${CLIENT_OBJ}
  610. X    ${CC} ${CFLAGS} -o fmkdir fmkdir.o ${CLIENT_OBJ} ${LIB}
  611. X
  612. Xfver: fver.o ${CLIENT_OBJ}
  613. X    ${CC} ${CFLAGS} -o fver fver.o ${CLIENT_OBJ} ${LIB}
  614. X
  615. Xfver.o: fver.c client_def.h common_def.h Makefile
  616. X    ${CC} ${CFLAGS} -c -DVERSION_STR=\"${VERSION_STR}\" fver.c
  617. X
  618. X#############################################################################
  619. X
  620. XMERGE_OBJ = fcatcmd_merge.o fcdcmd_merge.o fgetcmd_merge.o fgrabcmd_merge.o \
  621. X        flscmd_merge.o fmkdir_merge.o fprocmd_merge.o fput_merge.o \
  622. X        frmcmd_merge.o frmdircmd_merge.o fver_merge.o
  623. X
  624. Xfgetcmd_merge.o: fgetcmd.o
  625. X    echo '#include "fgetcmd.c"' > fgetcmd_merge.c
  626. X    ${CC} ${CFLAGS} -c -Dmain=fgetcmd_main fgetcmd_merge.c
  627. X    rm -f fgetcmd_merge.c
  628. X
  629. Xfgrabcmd_merge.o: fgrabcmd.o
  630. X    echo '#include "fgrabcmd.c"' > fgrabcmd_merge.c
  631. X    ${CC} ${CFLAGS} -c -Dmain=fgrabcmd_main fgrabcmd_merge.c
  632. X    rm -f fgrabcmd_merge.c
  633. X
  634. Xfcatcmd_merge.o: fcatcmd.o
  635. X    echo '#include "fcatcmd.c"' > fcatcmd_merge.c
  636. X    ${CC} ${CFLAGS} -c -Dmain=fcatcmd_main fcatcmd_merge.c
  637. X    rm -f fcatcmd_merge.c
  638. X
  639. Xfput_merge.o: fput.o
  640. X    echo '#include "fput.c"' > fput_merge.c
  641. X    ${CC} ${CFLAGS} -c -Dmain=fput_main fput_merge.c
  642. X    rm -f fput_merge.c
  643. X
  644. Xfrmcmd_merge.o: frmcmd.o
  645. X    echo '#include "frmcmd.c"' > frmcmd_merge.c
  646. X    ${CC} ${CFLAGS} -c -Dmain=frmcmd_main frmcmd_merge.c
  647. X    rm -f frmcmd_merge.c
  648. X
  649. Xflscmd_merge.o: flscmd.o
  650. X    echo '#include "flscmd.c"' > flscmd_merge.c
  651. X    ${CC} ${CFLAGS} -c -Dmain=flscmd_main flscmd_merge.c
  652. X    rm -f flscmd_merge.c
  653. X
  654. Xfcdcmd_merge.o: fcdcmd.o
  655. X    echo '#include "fcdcmd.c"' > fcdcmd_merge.c
  656. X    ${CC} ${CFLAGS} -c -Dmain=fcdcmd_main fcdcmd_merge.c
  657. X    rm -f fcdcmd_merge.c
  658. X
  659. Xfrmdircmd_merge.o: frmdircmd.o
  660. X    echo '#include "frmdircmd.c"' > frmdircmd_merge.c
  661. X    ${CC} ${CFLAGS} -c -Dmain=frmdircmd_main frmdircmd_merge.c
  662. X    rm -f frmdircmd_merge.c
  663. X
  664. Xfprocmd_merge.o: fprocmd.o
  665. X    echo '#include "fprocmd.c"' > fprocmd_merge.c
  666. X    ${CC} ${CFLAGS} -c -Dmain=fprocmd_main fprocmd_merge.c
  667. X    rm -f fprocmd_merge.c
  668. X
  669. Xfmkdir_merge.o: fmkdir.o
  670. X    echo '#include "fmkdir.c"' > fmkdir_merge.c
  671. X    ${CC} ${CFLAGS} -c -Dmain=fmkdir_main fmkdir_merge.c
  672. X    rm -f fmkdir_merge.c
  673. X
  674. Xfver_merge.o: fver.o Makefile
  675. X    echo '#include "fver.c"' > fver_merge.c
  676. X    ${CC} ${CFLAGS} -c -Dmain=fver_main -DVERSION_STR=\"${VERSION_STR}\" \
  677. X                fver_merge.c
  678. X    rm -f fver_merge.c
  679. X
  680. Xfsp_client_merge: merge.o ${MERGE_OBJ} ${CLIENT_OBJ} ${UTIL_LS_OBJ}
  681. X    ${CC} -o fsp_client_merge merge.o ${MERGE_OBJ} \
  682. X                ${CLIENT_OBJ} ${UTIL_LS_OBJ} ${LIB}
  683. X
  684. X#############################################################################
  685. X
  686. X
  687. X${BIN}/fspd     : fspd      ; cp fspd      ${BIN}/fspd
  688. X${BIN}/fgetcmd  : fgetcmd   ; cp fgetcmd   ${BIN}/fgetcmd
  689. X${BIN}/fgrabcmd : fgrabcmd  ; cp fgrabcmd  ${BIN}/fgrabcmd
  690. X${BIN}/fcatcmd  : fcatcmd   ; cp fcatcmd   ${BIN}/fcatcmd
  691. X${BIN}/fput     : fput      ; cp fput      ${BIN}/fput
  692. X${BIN}/frmcmd   : frmcmd    ; cp frmcmd    ${BIN}/frmcmd
  693. X${BIN}/flscmd   : flscmd    ; cp flscmd    ${BIN}/flscmd
  694. X${BIN}/fcdcmd   : fcdcmd    ; cp fcdcmd    ${BIN}/fcdcmd
  695. X${BIN}/frmdircmd: frmdircmd ; cp frmdircmd ${BIN}/frmdircmd
  696. X${BIN}/fprocmd  : fprocmd   ; cp fprocmd   ${BIN}/fprocmd
  697. X${BIN}/fmkdir   : fmkdir    ; cp fmkdir    ${BIN}/fmkdir
  698. X${BIN}/fver     : fver      ; cp fver      ${BIN}/fver
  699. X
  700. X#############################################################################
  701. X
  702. X${MAN}/fcat.1     : fcatcmd.1  ; cp fcat.1      ${MAN}/fcat.1
  703. X${MAN}/fcatcmd.1  : fcatcmd.1  ; cp fcatcmd.1   ${MAN}/fcatcmd.1
  704. X${MAN}/fcd.1      : fcdcmd.1   ; cp fcd.1       ${MAN}/fcd.1
  705. X${MAN}/fcdcmd.1   : fcdcmd.1   ; cp fcdcmd.1    ${MAN}/fcdcmd.1
  706. X${MAN}/fget.1     : fgetcmd.1  ; cp fget.1      ${MAN}/fget.1
  707. X${MAN}/fgetcmd.1  : fgetcmd.1  ; cp fgetcmd.1   ${MAN}/fgetcmd.1
  708. X${MAN}/fgrab.1    : fgrabcmd.1 ; cp fgrab.1     ${MAN}/fgrab.1
  709. X${MAN}/fgrabcmd.1 : fgrabcmd.1 ; cp fgrabcmd.1  ${MAN}/fgrabcmd.1
  710. X${MAN}/fls.1      : flscmd.1   ; cp fls.1       ${MAN}/fls.1
  711. X${MAN}/flscmd.1   : flscmd.1   ; cp flscmd.1    ${MAN}/flscmd.1
  712. X${MAN}/fmkdir.1   : fmkdir.1   ; cp fmkdir.1    ${MAN}/fmkdir.1
  713. X${MAN}/fpro.1     : fprocmd.1  ; cp fpro.1      ${MAN}/fpro.1
  714. X${MAN}/fprocmd.1  : fprocmd.1  ; cp fprocmd.1   ${MAN}/fprocmd.1
  715. X${MAN}/fput.1     : fput.1     ; cp fput.1      ${MAN}/fput.1
  716. X${MAN}/frm.1      : frmcmd.1   ; cp frm.1       ${MAN}/frm.1
  717. X${MAN}/frmcmd.1   : frmcmd.1   ; cp frmcmd.1    ${MAN}/frmcmd.1
  718. X${MAN}/frmdir.1   : frmdircmd.1; cp frmdir.1    ${MAN}/frmdir.1
  719. X${MAN}/frmdircmd.1: frmdircmd.1; cp frmdircmd.1 ${MAN}/frmdircmd.1
  720. X${MAN}/fspd.1     : fspd.1     ; cp fspd.1      ${MAN}/fspd.1
  721. X${MAN}/fver.1     : fver.1     ; cp fver.1      ${MAN}/fver.1
  722. X
  723. X#############################################################################
  724. X
  725. Xserver_main.o: server_main.c server_def.h common_def.h Makefile
  726. X    ${CC} ${CFLAGS} -DDEF_FSP_PORT=${DEF_FSP_PORT}    \
  727. X             -DDEF_FSP_HOME=\"${DEF_FSP_HOME}\"    \
  728. X             -DVERSION_STR=\"${VERSION_STR}\"    \
  729. X             -DFILE_NAME_LIMIT=${FILE_NAME_LIMIT} \
  730. X             -DALWAYS_USE_CACHE_DIR=${ALWAYS_USE_CACHE_DIR} \
  731. X             -DMAX_DIR_CACHE_COUNT=${MAX_DIR_CACHE_COUNT} \
  732. X             -DDEF_DIRECTORY_CACHE=\"${DEF_DIRECTORY_CACHE}\"    \
  733. X             -c server_main.c
  734. X
  735. Xclient_lock.o: client_lock.c client_def.h common_def.h Makefile
  736. X    ${CC} ${CFLAGS} ${LOCK_FLAGS} -c client_lock.c
  737. X
  738. Xclient_lib.o: client_lib.c client_def.h common_def.h
  739. Xclient_util.o: client_util.c client_def.h common_def.h
  740. Xfcatcmd.o: fcatcmd.c client_def.h common_def.h
  741. Xfcdcmd.o: fcdcmd.c client_def.h common_def.h
  742. Xfgetcmd.o: fgetcmd.c client_def.h common_def.h
  743. Xfgrabcmd.o: fgrabcmd.c client_def.h common_def.h
  744. Xflscmd.o: flscmd.c client_def.h common_def.h
  745. Xfmkdir.o: fmkdir.c client_def.h common_def.h
  746. Xfprocmd.o: fprocmd.c client_def.h common_def.h
  747. Xfput.o: fput.c client_def.h common_def.h
  748. Xfrmcmd.o: frmcmd.c client_def.h common_def.h
  749. Xfver.o: fver.c client_def.h common_def.h
  750. Xfrmdircmd.o: frmdircmd.c client_def.h common_def.h
  751. Xserver_host.o: server_host.c server_def.h common_def.h
  752. Xserver_file.o: server_file.c server_def.h common_def.h
  753. Xserver_lib.o: server_lib.c server_def.h common_def.h
  754. Xserver_main.o: server_main.c server_def.h common_def.h
  755. Xudp_io.o: udp_io.c common_def.h
  756. X
  757. Xclean:
  758. X    rm -f *.o fspd fsp_client_merge ${PROGS}
  759. X    @ cd bsd_src; make clean
  760. X
  761. Xde-install:
  762. X    rm -f ${BIN}/fspd ${IPROGS} ${IMANS}
  763. END_OF_FILE
  764.   if test 13388 -ne `wc -c <'Makefile'`; then
  765.     echo shar: \"'Makefile'\" unpacked with wrong size!
  766.   fi
  767.   # end of 'Makefile'
  768. fi
  769. if test ! -d 'bsd_src' ; then
  770.     echo shar: Creating directory \"'bsd_src'\"
  771.     mkdir 'bsd_src'
  772. fi
  773. if test -f 'server_file.c' -a "${1}" != "-c" ; then 
  774.   echo shar: Will not clobber existing file \"'server_file.c'\"
  775. else
  776.   echo shar: Extracting \"'server_file.c'\" \(17362 characters\)
  777.   sed "s/^X//" >'server_file.c' <<'END_OF_FILE'
  778. X    /*********************************************************************\
  779. X    *  Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu)   *
  780. X    *                                                                     *
  781. X    *  You may copy or modify this file in any manner you wish, provided  *
  782. X    *  that this notice is always included, and that you hold the author  *
  783. X    *  harmless for any loss or damage resulting from the installation or *
  784. X    *  use of this software.                                              *
  785. X    \*********************************************************************/
  786. X
  787. X#include "server_def.h"
  788. X
  789. X/*****************************************************************************
  790. X* This is a modified server_file that hash file names.                 *
  791. X*****************************************************************************/
  792. X
  793. X#define NBSIZE (2*sizeof(UBUF))
  794. X
  795. Xextern *malloc();
  796. X
  797. X#define fexist(A) (!access(A,0))
  798. X#define touch(A) close(open(A,O_CREAT,0777))
  799. X#define LF_PFX '&'
  800. X#define LP_PFX '\\'
  801. X
  802. X/*****************************************************************************
  803. X* Routine to check a path string given by the client.
  804. X* Will replace null string by ".".
  805. X* In case of error, returns the error string.
  806. X*****************************************************************************/
  807. X
  808. X/*****************************************************************************
  809. X*  The PPATH structure is filled in by the function check_path when given a
  810. X*  path string.  The elements are filled in as such:
  811. X* 
  812. X*    fullp      pointer to a string containing the full path name
  813. X*    f_ptr      pointer to begining of the last component of the path
  814. X*       f_len      length of the last component of the path
  815. X*    d_ptr      pointer to begining of the directory part of path
  816. X*       d_len      length of the directory part of the path
  817. X*
  818. X*  fullp is a null-terminated full path string.
  819. X*  f_ptr is always a null-terminated sub-string of fullp.
  820. X*  p_ptr is generally not null-terminated.
  821. X*****************************************************************************/
  822. X
  823. Xchar *check_path(fullp,len,pp)
  824. X    char *fullp;
  825. X    int   len;
  826. X    PPATH *pp;
  827. X{
  828. X    char *s;
  829. X    int state;
  830. X
  831. X    if(len < 1) return("Path must have non-zero length");
  832. X    if(fullp[len-1]) return("Path not null terminated");
  833. X
  834. X    pp->d_ptr = "."; pp->d_len = 1;    /* initial dir part ---> root */
  835. X
  836. X    if(len == 1 && fullp[0] == 0)    /* null path --> root */
  837. X    {
  838. X    pp->fullp = pp->f_ptr = ".";
  839. X    pp->f_len = 1;
  840. X    return(NULLP);
  841. X    }
  842. X
  843. X    for(s = pp->fullp = pp->f_ptr = fullp, state = 0; *s; s++)
  844. X    {
  845. X    if(*s <= ' ' || *s >= '~') return("Path contains illegal chars");
  846. X
  847. X    switch(*s)
  848. X    {
  849. X        case LF_PFX:
  850. X        case LP_PFX:
  851. X        case    '.': if(!state) return("Path can't begin with '.'");
  852. X             break;
  853. X
  854. X        case    '/': if(!state) return("Path can't contain '//'");
  855. X             pp->d_ptr = fullp;
  856. X             pp->d_len = s - fullp;
  857. X             pp->f_ptr = s+1;
  858. X             state = 0;
  859. X             break;
  860. X
  861. X        default    : state = 1;
  862. X             break;
  863. X    }
  864. X    }
  865. X
  866. X    pp->f_len = s - pp->f_ptr;
  867. X    return(NULLP);
  868. X}
  869. X
  870. X/*****************************************************************************
  871. X* Put the directory part of the path pp into dbuf.
  872. X* return pointer to the null character.
  873. X*****************************************************************************/
  874. X
  875. Xchar *copy_dir(dbuf,pp)
  876. X    char *dbuf;
  877. X    PPATH *pp;
  878. X{
  879. X    char *p1,*p2;
  880. X    int cnt;
  881. X
  882. X    for(p1 = dbuf, p2 = pp->d_ptr, cnt = pp->d_len; cnt--; *p1++ = *p2++);
  883. X    *p1 = 0; return(p1);
  884. X}
  885. X
  886. X/*****************************************************************************
  887. X* Reads directory and write directory listing file.
  888. X*****************************************************************************/
  889. X
  890. Xstatic build_dir_file(fp)
  891. X    FILE *fp;
  892. X{
  893. X    int nlen, skip, rem;
  894. X    DIR *dir_f;
  895. X#ifdef DIRENT
  896. X    struct dirent *dp;
  897. X#else
  898. X    struct direct *dp;
  899. X#endif
  900. X    struct stat    sb;
  901. X    register char  *s;
  902. X    RDIRENT rdb;
  903. X    static char marker[] = "******************";
  904. X    char longname[UBUF_SPACE];
  905. X    FILE *lfp;
  906. X
  907. X    if(!(dir_f = opendir(".")))    /* assume I have cd to path already */
  908. X    { fprintf(stderr,"Can't open dir during initialization\n"); exit(1); }
  909. X
  910. X    for(rem = UBUF_SPACE; dp = readdir(dir_f); )
  911. X    {
  912. X    if (dp->d_ino == 0) continue;
  913. X    s = dp->d_name;
  914. X
  915. X    if(s[0] == LF_PFX)
  916. X    {
  917. X        s[0] = LP_PFX;
  918. X        if(!(lfp = fopen(s,"r"))) { unlink(s); *s = LF_PFX; unlink(s); }
  919. X        fgets(longname,UBUF_SPACE,lfp);  fclose(lfp);
  920. X        s[0] = LF_PFX; s = longname; longname[UBUF_SPACE-1] = 0;
  921. X    }
  922. X
  923. X    if(s[0] == LP_PFX) continue;
  924. X                        /* hide dot files */
  925. X    if((s[0] == '.') && ((s[1] !=  0 ) &&
  926. X                 (s[1] != '.' || s[2] != 0))) continue;
  927. X
  928. X    if(stat(dp->d_name,&sb)) continue;
  929. X
  930. X    nlen = strlen(s)+1;
  931. X
  932. X    if(rem < RDHSIZE + nlen)
  933. X    {
  934. X        rdb.type = RDTYPE_SKIP;
  935. X        if(rem <= RDHSIZE) { fwrite(marker,1,rem    ,fp); }
  936. X              else { fwrite(marker,1,RDHSIZE,fp);
  937. X                 fwrite(s, 1,rem-RDHSIZE,fp); }
  938. X        rem = UBUF_SPACE;
  939. X    }
  940. X
  941. X    rdb.type = ((S_IFDIR & sb.st_mode)) ? RDTYPE_DIR : RDTYPE_FILE;
  942. X    rdb.size = htonl(sb.st_size);
  943. X    rdb.time = htonl(sb.st_mtime);
  944. X
  945. X    fwrite((char *) &rdb,1,RDHSIZE,fp);
  946. X    fwrite(s,1,nlen,fp);
  947. X    rem -= (nlen + RDHSIZE);
  948. X
  949. X    if((skip = (nlen + RDHSIZE) & 0x3))
  950. X        { fwrite((char *) &rdb,1,4-skip,fp); rem -= (4-skip); }
  951. X
  952. X    if(!rem) rem = UBUF_SPACE;
  953. X    }
  954. X
  955. X    rdb.type = RDTYPE_END;
  956. X    fwrite((char *) &rdb,1,RDHSIZE,fp);
  957. X
  958. X    fflush(fp);
  959. X    closedir(dir_f);
  960. X}
  961. X
  962. X/***************************************************************************/
  963. X
  964. Xchar *server_get_dir(pp,fp)
  965. X    PPATH *pp;            /* returned file may not point at BOF */
  966. X    FILE **fp;
  967. X{
  968. X    char *server_get_dir_2();
  969. X    struct stat sd, sf;
  970. X    char   list_p[NBSIZE];
  971. X    int    fsp_content_exists;
  972. X
  973. X    if(stat(pp->fullp,&sd)) return("Can't find directory");
  974. X    if(!(S_IFDIR & sd.st_mode)) return("Not a directory");
  975. X
  976. X    sprintf(list_p,"%s/.FSP_CONTENT",pp->fullp);
  977. X
  978. X    if(fsp_content_exists = !stat(list_p,&sf))
  979. X    {
  980. X    if(sf.st_mtime >= sd.st_mtime)
  981. X    {
  982. X        *fp = fopen(list_p,"r");
  983. X        if(!*fp) return("Can't read directory listing");
  984. X        return((char *)0);
  985. X    }
  986. X    }
  987. X
  988. X    if(!fsp_content_exists &&
  989. X    always_use_cache_dir) return(server_get_dir_2(pp,fp,&sd));
  990. X
  991. X    if(!(*fp = fopen(list_p,"w+")))
  992. X    {
  993. X    if(!fsp_content_exists &&
  994. X       !always_use_cache_dir) return(server_get_dir_2(pp,fp,&sd));
  995. X    return("directory unreadable");
  996. X    }
  997. X    if(chdir(pp->fullp)) return("Can't cd to directory");
  998. X    build_dir_file(*fp);
  999. X    if(chdir(home_dir) == -1) { perror("chdir2"); exit(1); }
  1000. X    return(NULLP);
  1001. X}
  1002. X
  1003. Xchar *server_get_dir_2(pp,fp,sd)
  1004. X    PPATH *pp;
  1005. X    FILE **fp;
  1006. X    struct stat *sd;
  1007. X{
  1008. X    struct stat sf;
  1009. X    char   name_p[NBSIZE], list_p[NBSIZE], tmp[UBUF_SPACE];
  1010. X    unsigned int hash, i, mask, new_namefile;
  1011. X    unsigned char *p;
  1012. X    FILE *np;
  1013. X
  1014. X    mask = dir_cache_limit << 8;
  1015. X
  1016. X    for(hash = 0, p = (unsigned char *) pp->fullp; *p; p++)
  1017. X    {
  1018. X    hash = (hash << 1) ^ *p;
  1019. X    if(hash & mask) hash ^= (mask+1);
  1020. X    }
  1021. X
  1022. X    for(i = 8; i--; )
  1023. X    {
  1024. X    hash <<= 1;
  1025. X    if(hash & mask) hash ^= (mask+1);
  1026. X    }
  1027. X
  1028. X    hash = (hash >> 8) & (mask-1);
  1029. X
  1030. X    sprintf(name_p,"%s/.N%x",dir_cache_dir,hash);
  1031. X    sprintf(list_p,"%s/.L%x",dir_cache_dir,hash);
  1032. X
  1033. X    if(!(np = fopen(name_p,"r"))) new_namefile = 1; else
  1034. X    {
  1035. X    fgets(tmp,UBUF_SPACE,np); fclose(np);
  1036. X
  1037. X    if(strcmp(tmp,pp->fullp)) new_namefile = 1; else
  1038. X    {
  1039. X        if(!stat(list_p,&sf) && (sf.st_mtime >= sd->st_mtime))
  1040. X        {
  1041. X        *fp = fopen(list_p,"r");
  1042. X        if(!*fp) return("Can't read directory listing");
  1043. X        return((char *)0);
  1044. X        }
  1045. X        new_namefile = 0;
  1046. X    }
  1047. X    }
  1048. X
  1049. X    if(new_namefile)
  1050. X    {
  1051. X    if(!(np = fopen(name_p,"w")))
  1052. X        return("Can't write directory listing name file");
  1053. X    fputs(pp->fullp,np); fclose(np);
  1054. X    }
  1055. X
  1056. X    if(!(*fp = fopen(list_p,"w+"))) return("directory unreadable");
  1057. X    if(chdir(pp->fullp)) return("Can't cd to directory");
  1058. X    build_dir_file(*fp);
  1059. X    if(chdir(home_dir) == -1) { perror("chdir2"); exit(1); }
  1060. X    return(NULLP);
  1061. X}
  1062. X
  1063. X/**********************************************************************/
  1064. X
  1065. Xchar *server_del_file(pp,inet_num)        /* assume path is validated */
  1066. X    PPATH *pp;
  1067. X    unsigned long inet_num;
  1068. X{
  1069. X    int is_long;
  1070. X    struct stat sb;
  1071. X    char   ok_del_p[NBSIZE], owner_p[NBSIZE];
  1072. X
  1073. X    if(is_long = (pp->f_len > max_nlen)) fold_path(pp);
  1074. X
  1075. X    if(stat(pp->fullp,&sb)) return("unlink: file not accessible");
  1076. X    if(!(S_IFREG & sb.st_mode)) return("unlink: not an ordinary file");
  1077. X
  1078. X    sprintf(copy_dir( owner_p,pp),"/.OWN.%08X"  ,inet_num);
  1079. X     strcpy(copy_dir(ok_del_p,pp),"/.FSP_OK_DEL"         );
  1080. X
  1081. X    if(!fexist(owner_p) && !fexist(ok_del_p))
  1082. X            return("no permission for removing this file");
  1083. X
  1084. X    if(unlink(pp->fullp) == -1) return("unlink: cannot unlink");
  1085. X
  1086. X    if(is_long) { *pp->f_ptr = LP_PFX; unlink(pp->fullp); }
  1087. X
  1088. X    return(NULLP);
  1089. X}
  1090. X
  1091. X/**********************************************************************/
  1092. X
  1093. Xchar *server_del_dir(pp,inet_num)
  1094. X    PPATH *pp;
  1095. X    unsigned long inet_num;
  1096. X{
  1097. X    struct stat sb;
  1098. X    char   list_p[NBSIZE], ok_del_p[NBSIZE], ok_add_p[NBSIZE], owner_p[NBSIZE];
  1099. X    int    has_ok_del_p, has_ok_add_p;
  1100. X
  1101. X    if(stat(pp->fullp,&sb)) return("rmdir: directory not accessible");
  1102. X    if(!(S_IFDIR & sb.st_mode)) return("rmdir: not an ordinary directory");
  1103. X
  1104. X    sprintf( owner_p,"%s/.OWN.%08X"   ,pp->fullp,inet_num);
  1105. X    sprintf(  list_p,"%s/.FSP_CONTENT",pp->fullp         );
  1106. X    sprintf(ok_del_p,"%s/.FSP_OK_DEL" ,pp->fullp         );
  1107. X    sprintf(ok_add_p,"%s/.FSP_OK_ADD" ,pp->fullp         );
  1108. X
  1109. X    if(!fexist(owner_p)) return("no permission for removing this directory");
  1110. X
  1111. X    unlink(owner_p); unlink( list_p);
  1112. X    has_ok_del_p = !unlink(ok_del_p);
  1113. X    has_ok_add_p = !unlink(ok_add_p);
  1114. X
  1115. X    if(rmdir(pp->fullp) != 0)
  1116. X    {
  1117. X    if(has_ok_del_p) touch(ok_del_p);
  1118. X    if(has_ok_add_p) touch(ok_add_p);
  1119. X    if(     owner_p) touch( owner_p);
  1120. X    return("rmdir: cannot unlink");
  1121. X    }
  1122. X
  1123. X    return(NULLP);
  1124. X}
  1125. X
  1126. X/**********************************************************************/
  1127. X
  1128. Xchar *server_make_dir(pp,inet_num)
  1129. X    PPATH *pp;
  1130. X    unsigned long inet_num;
  1131. X{
  1132. X    char ok_add_p[NBSIZE], owner_p[NBSIZE];
  1133. X
  1134. X    sprintf(copy_dir( owner_p,pp),"/.OWN.%08X"  ,inet_num);
  1135. X     strcpy(copy_dir(ok_add_p,pp),"/.FSP_OK_ADD"         );
  1136. X
  1137. X    if(!fexist(owner_p) && !fexist(ok_add_p))
  1138. X            return("no permission for directory creation");
  1139. X
  1140. X    sprintf(owner_p,"%s/.OWN.%08X",pp->fullp,inet_num);
  1141. X
  1142. X    if(mkdir(pp->fullp,0777) != 0) return("Can't create directory");
  1143. X
  1144. X    touch(owner_p);
  1145. X    return(NULLP);
  1146. X}
  1147. X
  1148. X/**********************************************************************/
  1149. X
  1150. Xchar *server_get_file(pp,fp)
  1151. X    PPATH *pp;
  1152. X    FILE **fp;
  1153. X{
  1154. X    struct stat sb;
  1155. X
  1156. X    if(pp->f_len > max_nlen) fold_path(pp);
  1157. X
  1158. X    if(stat(pp->fullp,&sb)) return("Can't find file");
  1159. X    if(!(S_IFREG & sb.st_mode)) return("Not a file");
  1160. X    if(!(*fp = fopen(pp->fullp,"r"))) return("Can't open file");
  1161. X    return(NULLP);
  1162. X}
  1163. X
  1164. X/**********************************************************************/
  1165. X
  1166. Xchar *server_get_pro(pp,result,inet_num) /* result and pp->fullp may overlap */
  1167. X    PPATH *pp;
  1168. X    char *result;
  1169. X    unsigned long inet_num;
  1170. X{
  1171. X    struct stat sb;
  1172. X    char   buf[NBSIZE];
  1173. X    char  *owner_s, *del_s, *add_s;
  1174. X
  1175. X    if(stat(pp->fullp,&sb)) return("getpro: directory not accessible");
  1176. X    if(!(S_IFDIR & sb.st_mode)) return("getpro: not an ordinary directory");
  1177. X
  1178. X    sprintf(buf,"%s/.OWN.%08X",pp->fullp,inet_num);
  1179. X    owner_s = ( fexist(buf)) ? "your" : "some other";
  1180. X    sprintf(buf,"%s/.FSP_OK_DEL" ,pp->fullp);
  1181. X    del_s   = (!fexist(buf)) ? "NO" : "YES";
  1182. X    sprintf(buf,"%s/.FSP_OK_ADD" ,pp->fullp);
  1183. X    add_s   = (!fexist(buf)) ? "NO" : "YES";
  1184. X
  1185. X    sprintf(result,"(owner: %s machine)(delete: %s)(create: %s)",
  1186. X                        owner_s, del_s, add_s);
  1187. X    return(NULLP);
  1188. X}
  1189. X
  1190. X/**********************************************************************/
  1191. X
  1192. Xchar *server_set_pro(pp,key,inet_num)
  1193. X    PPATH *pp;
  1194. X    char *key;
  1195. X    unsigned long inet_num;
  1196. X{
  1197. X    struct stat sb;
  1198. X    char   buf[NBSIZE];
  1199. X
  1200. X    if(stat(pp->fullp,&sb)) return("getpro: directory not accessible");
  1201. X    if(!(S_IFDIR & sb.st_mode)) return("getpro: not an ordinary directory");
  1202. X
  1203. X    sprintf(buf,"%s/.OWN.%08X",pp->fullp,inet_num);
  1204. X    if(!fexist(buf)) return("no permission for changing the protection-mode");
  1205. X
  1206. X    switch(key[1])
  1207. X    {
  1208. X    case 'c': sprintf(buf,"%s/.FSP_OK_ADD",pp->fullp); break;
  1209. X    case 'd': sprintf(buf,"%s/.FSP_OK_DEL",pp->fullp); break;
  1210. X    default : return("bad flag");
  1211. X    }
  1212. X
  1213. X    switch(key[0])
  1214. X    {
  1215. X    case '+':  touch(buf); break;
  1216. X    case '-': unlink(buf); break;
  1217. X    default : return("bad flag");
  1218. X    }
  1219. X
  1220. X    return(NULLP);
  1221. X}
  1222. X
  1223. X/**********************************************************************
  1224. X*  These two are used for file uploading.
  1225. X**********************************************************************/
  1226. X
  1227. Xchar *server_up_load(data,len,pos,inet_num,port_num)
  1228. X    char *data;
  1229. X    int    len;
  1230. X    unsigned long pos, inet_num;
  1231. X    unsigned short port_num;
  1232. X{
  1233. X    FILE *fp;
  1234. X    char  tname[NBSIZE];
  1235. X
  1236. X    sprintf(tname,"%s/.T%08X%04X",dir_cache_dir,inet_num,port_num);
  1237. X
  1238. X    if(pos) {             fp = fopen(tname,"a"); }
  1239. X       else { unlink(tname); fp = fopen(tname,"w"); }
  1240. X
  1241. X    if(!fp) return("Cannot open temporary file");
  1242. X
  1243. X    fwrite(data, 1, len, fp);
  1244. X    fclose(fp);
  1245. X
  1246. X    return(NULLP);
  1247. X}
  1248. X
  1249. Xchar *server_install(pp,inet_num,port_num)
  1250. X    PPATH *pp;
  1251. X    unsigned long inet_num;
  1252. X    unsigned short port_num;
  1253. X{
  1254. X    FILE *ft, *fp;
  1255. X    char      tname[NBSIZE],  owner_p[NBSIZE], save_p[NBSIZE], buf[512];
  1256. X    char   ok_del_p[NBSIZE], ok_add_p[NBSIZE];
  1257. X    int bytes, is_long;
  1258. X
  1259. X    if(is_long = (pp->f_len > max_nlen))
  1260. X            { strcpy(save_p,pp->f_ptr); fold_path(pp); }
  1261. X
  1262. X    sprintf(copy_dir(owner_p,pp),"/.OWN.%08X",inet_num);
  1263. X    sprintf(tname,"%s/.T%08X%04X",dir_cache_dir,inet_num,port_num);
  1264. X
  1265. X    if(!fexist(owner_p))
  1266. X    {
  1267. X    strcpy(copy_dir(ok_add_p,pp),"/.FSP_OK_ADD");
  1268. X    strcpy(copy_dir(ok_del_p,pp),"/.FSP_OK_DEL");
  1269. X
  1270. X    if(!fexist(ok_add_p))
  1271. X    {
  1272. X        unlink(tname);
  1273. X        return("no permission for creating that file");
  1274. X    }
  1275. X
  1276. X    if(!fexist(ok_del_p) && fexist(pp->fullp))
  1277. X    {
  1278. X        unlink(tname);
  1279. X        return("no permission for replacing that file");
  1280. X    }
  1281. X    }
  1282. X
  1283. X    unlink(pp->fullp);
  1284. X    if(link(tname,pp->fullp) == 0) { unlink(tname); goto done; }
  1285. X
  1286. X    if(!(ft = fopen(tname,"r"))) { unlink(tname);
  1287. X                   return("Can't open temporary file"); }
  1288. X
  1289. X    if(!(fp = fopen(pp->fullp ,"w"))) { unlink(tname); fclose(ft);
  1290. X                   return("Can't open file for output"); }
  1291. X
  1292. X    while(bytes = fread(buf,1,sizeof(buf),ft)) fwrite(buf,1,bytes,fp);
  1293. X
  1294. X    fclose(ft); fclose(fp); unlink(tname);
  1295. X
  1296. X  done:
  1297. X
  1298. X    if(is_long)
  1299. X    {
  1300. X    *pp->f_ptr = LP_PFX;
  1301. X    if(!(fp = fopen(pp->fullp,"w")))
  1302. X    {
  1303. X        *pp->f_ptr = LF_PFX; unlink(tname);
  1304. X        return("Can't create long named file for output");
  1305. X    }
  1306. X    fputs(save_p,fp); fclose(fp);
  1307. X    }
  1308. X
  1309. X    return(NULLP);
  1310. X}
  1311. X
  1312. X/**********************************************************************/
  1313. X
  1314. Xchar *server_secure_file(pp,inet_num,port_num)    /* assume path is validated */
  1315. X    PPATH *pp;
  1316. X    unsigned long  inet_num;
  1317. X    unsigned short port_num;
  1318. X{
  1319. X    int is_long;
  1320. X    struct stat sb;
  1321. X    char   ok_del_p[NBSIZE], owner_p[NBSIZE], temp_p[NBSIZE];
  1322. X
  1323. X    if(is_long = (pp->f_len > max_nlen)) fold_path(pp);
  1324. X
  1325. X    if(stat(pp->fullp,&sb)) return("grab: file not accessible");
  1326. X    if(!(S_IFREG & sb.st_mode)) return("grab: not an ordinary file");
  1327. X
  1328. X    sprintf(copy_dir( owner_p,pp),"/.OWN.%08X"  ,inet_num         );
  1329. X     strcpy(copy_dir(ok_del_p,pp),"/.FSP_OK_DEL"                  );
  1330. X    sprintf(copy_dir(  temp_p,pp),"/.G%08X%04X" ,inet_num,port_num);
  1331. X
  1332. X    if(!fexist(owner_p) && !fexist(ok_del_p))
  1333. X            return("grab: no permission for grabbing this file");
  1334. X
  1335. X    unlink(temp_p);
  1336. X    if(link(pp->fullp,temp_p) == -1) return("grab: cannot make link");
  1337. X    if(unlink(pp->fullp) == -1) { unlink(temp_p);
  1338. X                  return("grab: cannot unlink"); }
  1339. X
  1340. X    if(is_long) { *pp->f_ptr = LP_PFX; unlink(pp->fullp); }
  1341. X
  1342. X    return(NULLP);
  1343. X}
  1344. X
  1345. Xchar *server_grab_file(pp,fp,inet_num,port_num)
  1346. X    PPATH *pp;
  1347. X    FILE **fp;
  1348. X    unsigned long  inet_num;
  1349. X    unsigned short port_num;
  1350. X{
  1351. X    struct stat sb;
  1352. X    char temp_p[NBSIZE];
  1353. X
  1354. X    sprintf(copy_dir(temp_p,pp),"/.G%08X%04X",inet_num,port_num);
  1355. X
  1356. X    if(stat(temp_p,&sb)) return("grab: can't find file");
  1357. X    if(!(S_IFREG & sb.st_mode)) return("grab: Not a file");
  1358. X    if(!(*fp = fopen(temp_p,"r"))) return("grab: can't open file");
  1359. X    return(NULLP);
  1360. X}
  1361. X
  1362. Xchar *server_grab_done(pp,inet_num,port_num)
  1363. X    PPATH *pp;
  1364. X    unsigned long  inet_num;
  1365. X    unsigned short port_num;
  1366. X{
  1367. X    struct stat sb;
  1368. X    char temp_p[NBSIZE];
  1369. X
  1370. X    sprintf(copy_dir(temp_p,pp),"/.G%08X%04X",inet_num,port_num);
  1371. X
  1372. X    if(stat(temp_p,&sb)) return("grab: can't find temporary file");
  1373. X    if(unlink(temp_p) == -1) return("grab: can't delete temporary file");
  1374. X    return(NULLP);
  1375. X}
  1376. X
  1377. X/**********************************************************************/
  1378. X
  1379. Xfold_path(pp)
  1380. X    PPATH *pp;
  1381. X{
  1382. X    unsigned char *p;
  1383. X    unsigned long v1, v2;
  1384. X
  1385. X    p = (unsigned char *) pp->f_ptr;
  1386. X
  1387. X    for(v1 = 0; v2 = *p++; )
  1388. X    {
  1389. X    if(v1 & 0x80000000) { v1 = (v1 << 1) ^ v2 ^ 1; }
  1390. X               else { v1 = (v1 << 1) ^ v2    ; }
  1391. X    }
  1392. X
  1393. X    sprintf(pp->f_ptr,"%c%08X",LF_PFX,v1);
  1394. X    pp->f_len = 9;
  1395. X}
  1396. X
  1397. X/**********************************************************************/
  1398. X
  1399. Xinit_home_dir()
  1400. X{
  1401. X    if(*home_dir != '/') { fprintf(stderr,"[%s] does not start with a /\n");
  1402. X               exit(1); }
  1403. X
  1404. X    if(chdir(home_dir) == -1) { perror("chdir"); exit(1); }
  1405. X
  1406. X    if(dbug) { fprintf(stderr,"home on %s\n",home_dir); fflush(stderr); }
  1407. X}
  1408. X
  1409. X/***************************************************************************/
  1410. END_OF_FILE
  1411.   if test 17362 -ne `wc -c <'server_file.c'`; then
  1412.     echo shar: \"'server_file.c'\" unpacked with wrong size!
  1413.   fi
  1414.   # end of 'server_file.c'
  1415. fi
  1416. if test -f 'server_lib.c' -a "${1}" != "-c" ; then 
  1417.   echo shar: Will not clobber existing file \"'server_lib.c'\"
  1418. else
  1419.   echo shar: Extracting \"'server_lib.c'\" \(6386 characters\)
  1420.   sed "s/^X//" >'server_lib.c' <<'END_OF_FILE'
  1421. X    /*********************************************************************\
  1422. X    *  Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu)   *
  1423. X    *                                                                     *
  1424. X    *  You may copy or modify this file in any manner you wish, provided  *
  1425. X    *  that this notice is always included, and that you hold the author  *
  1426. X    *  harmless for any loss or damage resulting from the installation or *
  1427. X    *  use of this software.                                              *
  1428. X    \*********************************************************************/
  1429. X
  1430. X#include "server_def.h"
  1431. X
  1432. Xextern int errno;
  1433. X
  1434. Xstatic int myport = 0;
  1435. Xstatic int myfd;
  1436. Xstatic int interrupted = 0;
  1437. X
  1438. Xvoid server_interrupt()
  1439. X{
  1440. X    interrupted = 1;
  1441. X    signal(SIGALRM,server_interrupt);
  1442. X}
  1443. X
  1444. X/****************************************************************************
  1445. X*  This is the message filter.  It is called by main with a timeout value.
  1446. X*  If timeout is -1, it will never time out.  Otherwise, it waits for a
  1447. X*  message.  If timed out, it returns.  Otherwise it pass it through checks.
  1448. X*  Those message that passed get sent to the dispatch loop.
  1449. X****************************************************************************/
  1450. X
  1451. Xserver_loop(timeout)
  1452. X    unsigned long timeout;
  1453. X{
  1454. X    unsigned long cur_time;
  1455. X    HTAB *hp;
  1456. X    UBUF rbuf;
  1457. X    struct sockaddr_in from;
  1458. X    unsigned u, sum, mask;
  1459. X    int retval, bytes, old;
  1460. X    unsigned char *s, *d, *t;
  1461. X
  1462. X    while(1)
  1463. X    {
  1464. X    mask = 1 << myfd;
  1465. X    if(interrupted) { dump_htab(); interrupted = 0; }
  1466. X    retval = _x_select(&mask, timeout);
  1467. X
  1468. X    if(retval == -1) { if(errno == EINTR) continue;
  1469. X               perror("select"); exit(1); }
  1470. X
  1471. X    if(retval == 1)    /* an incoming message is waiting */
  1472. X    {
  1473. X        bytes = sizeof(from);
  1474. X        if((bytes = recvfrom(myfd,(char*)&rbuf,sizeof(rbuf),0,
  1475. X                    &from,&bytes)) < UBUF_HSIZE) continue;
  1476. X
  1477. X        rbuf.len = ntohs(rbuf.len);
  1478. X        if(rbuf.len+UBUF_HSIZE > bytes) continue;    /* truncated.  */
  1479. X
  1480. X        if(!(hp = find_host(from.sin_addr.s_addr)))
  1481. X            { fputs("find host failed\n",stderr); exit(0); }
  1482. X
  1483. X        if(hp->inhibit) continue;
  1484. X
  1485. X        old = 0;
  1486. X        cur_time = time((time_t *) 0);
  1487. X
  1488. X        if(hp->next_key != rbuf.key)
  1489. X        {
  1490. X        if(!hp->active)
  1491. X        {
  1492. X            hp->last_key = hp->next_key = rbuf.key;
  1493. X
  1494. X        } else
  1495. X        {
  1496. X            if(hp->last_key == rbuf.key)
  1497. X            {
  1498. X            if(cur_time < hp->last_acc + 3) continue;
  1499. X            old = 1;
  1500. X
  1501. X            } else
  1502. X            {
  1503. X            if(cur_time < hp->last_acc + 60) continue;
  1504. X            }
  1505. X        }
  1506. X        }
  1507. X
  1508. X        hp->active   =        1;
  1509. X        hp->last_acc = cur_time;
  1510. X
  1511. X        s = (unsigned char *) &rbuf;
  1512. X        d = s + bytes;
  1513. X        u = rbuf.sum; rbuf.sum = 0;
  1514. X        for(t = s, sum = bytes; t < d; sum += *t++);
  1515. X        sum = (sum + (sum >> 8)) & 0xff;
  1516. X        if(sum != u) continue;            /* wrong check sum */
  1517. X
  1518. X        rbuf.pos = ntohl(rbuf.pos);
  1519. X        server_get_packet(bytes,&rbuf,old,hp,&from);
  1520. X
  1521. X    } else return(0);                /* got a timeout */
  1522. X    }
  1523. X}
  1524. X
  1525. X/****************************************************************************
  1526. X* Routine to return a 16-bit key with random number in the first 8-bits and
  1527. X* zero in the second 8-bits.
  1528. X****************************************************************************/
  1529. X
  1530. Xget_next_key()
  1531. X{
  1532. X    unsigned long k;
  1533. X
  1534. X    k = random();
  1535. X    k = k ^ (k >> 8) ^ (k >> 16) ^ (k << 8);
  1536. X
  1537. X    return(k & 0xff00);
  1538. X}
  1539. X
  1540. X/****************************************************************************
  1541. X* Generic routine for sending reply back to clients.
  1542. X*        from: client address structure.
  1543. X*          ub: pointer to the message buffer.
  1544. X*  len1, len2: lengths of the two data regions in the message buffer.
  1545. X****************************************************************************/
  1546. X
  1547. Xserver_reply(from,ub,len1,len2)
  1548. X    struct sockaddr_in *from;
  1549. X    UBUF *ub;
  1550. X    int   len1, len2;
  1551. X{
  1552. X    unsigned char *s, *t, *d;
  1553. X    unsigned sum;
  1554. X
  1555. X    if(dbug) fprintf(stderr,"snd (%c,%d,%d,%lu) ---> %d.%d.%d.%d\n",
  1556. X                ub->cmd, len1, len2, ub->pos,
  1557. X                ((unsigned char *)(&(from->sin_addr.s_addr)))[0],
  1558. X                ((unsigned char *)(&(from->sin_addr.s_addr)))[1],
  1559. X                ((unsigned char *)(&(from->sin_addr.s_addr)))[2],
  1560. X                ((unsigned char *)(&(from->sin_addr.s_addr)))[3]);
  1561. X
  1562. X    ub->len = htons(len1);
  1563. X    ub->pos = htonl(ub->pos);
  1564. X
  1565. X    ub->sum = 0;
  1566. X    s = (unsigned char *) ub;
  1567. X    d = s + (len1 + len2 + UBUF_HSIZE);
  1568. X    for(t = s, sum = 0; t < d; sum += *t++);
  1569. X    ub->sum = sum + (sum >> 8);
  1570. X
  1571. X    if(sendto(myfd,(char *)ub,(len1 + len2 + UBUF_HSIZE),0,
  1572. X            from,sizeof(struct sockaddr_in)) == -1)
  1573. X                        { perror("sendto"); exit(1); }
  1574. X}
  1575. X
  1576. X/****************************************************************************
  1577. X* Send an error string.
  1578. X****************************************************************************/
  1579. X
  1580. Xsend_error(from,ub,msg)
  1581. X    struct sockaddr_in *from;
  1582. X    UBUF *ub;
  1583. X    char *msg;
  1584. X{
  1585. X    char *d;
  1586. X
  1587. X    for(d = ub->buf; *d++ = *msg++; );
  1588. X    ub->cmd = CC_ERR;
  1589. X
  1590. X    server_reply(from,ub,d-ub->buf,0);
  1591. X}
  1592. X
  1593. X/****************************************************************************
  1594. X* Send a block of data read from the file 'fp'.  Offset information is
  1595. X* contained in the input ub message buffer, which also doubles as the output
  1596. X* message buffer.
  1597. X****************************************************************************/
  1598. X
  1599. Xsend_file(from,ub,fp,has_len,lp)
  1600. X    struct sockaddr_in *from;
  1601. X    UBUF *ub;
  1602. X    FILE *fp;
  1603. X    int has_len;
  1604. X    char *lp;
  1605. X{
  1606. X    int bytes, len;
  1607. X
  1608. X    if(has_len == 2)    /* recover length field if it exists */
  1609. X    {
  1610. X    len  = ((unsigned char *) lp)[0]; len <<= 8;
  1611. X    len += ((unsigned char *) lp)[1];
  1612. X    if(len > UBUF_SPACE || len < 0) len = UBUF_SPACE;
  1613. X
  1614. X    } else { len  = UBUF_SPACE; }    /* use default if it doesn't exist */
  1615. X
  1616. X    fseek(fp,ub->pos,0);
  1617. X    bytes = fread(ub->buf, 1, len, fp);
  1618. X    server_reply(from,ub,bytes,0);
  1619. X}
  1620. X
  1621. X/****************************************************************************
  1622. X* The two UDP socket initialization routines.  One for running alone.
  1623. X* The other for running under inetd.
  1624. X****************************************************************************/
  1625. X
  1626. Xinit_network(port)
  1627. X    int port;
  1628. X{
  1629. X    myport = port;
  1630. X
  1631. X    if((myfd = _x_udp(&myport)) == -1) { perror("socket open"); exit(1); }
  1632. X
  1633. X    if(dbug)
  1634. X    {
  1635. X    fprintf(stderr,"listening on port %d\n",myport);
  1636. X    fflush(stderr);
  1637. X    }
  1638. X
  1639. X    signal(SIGALRM,server_interrupt);
  1640. X}
  1641. X
  1642. Xinit_inetd()
  1643. X{
  1644. X    myfd = dup(0);
  1645. X
  1646. X    signal(SIGALRM,server_interrupt);
  1647. X}
  1648. END_OF_FILE
  1649.   if test 6386 -ne `wc -c <'server_lib.c'`; then
  1650.     echo shar: \"'server_lib.c'\" unpacked with wrong size!
  1651.   fi
  1652.   # end of 'server_lib.c'
  1653. fi
  1654. echo shar: End of archive 1 \(of 4\).
  1655. cp /dev/null ark1isdone
  1656. MISSING=""
  1657. for I in 1 2 3 4 ; do
  1658.     if test ! -f ark${I}isdone ; then
  1659.     MISSING="${MISSING} ${I}"
  1660.     fi
  1661. done
  1662. if test "${MISSING}" = "" ; then
  1663.     echo You have unpacked all 4 archives.
  1664.     rm -f ark[1-9]isdone
  1665. else
  1666.     echo You still must unpack the following archives:
  1667.     echo "        " ${MISSING}
  1668. fi
  1669. exit 0
  1670. exit 0 # Just in case...
  1671.