nfsLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:60k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* nfsLib.c - Network File System (NFS) library */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 03k,10may02,kbw  making man page edits
  8. 03j,06nov01,vvv  made max path length configurable (SPR #63551)
  9. 03i,15oct01,rae  merge from truestack ver 03m, base 03h (cleanup)
  10. 03h,15mar99,c_c  Doc: updated nfsAuthUnixSet manual (SPR #20867).
  11. 03g,14mar99,jdi  doc: removed refs to config.h and/or configAll.h (SPR 25663).
  12. 03f,20nov97,gnn  fix for spr#5436, need to support FIOFSTATFSGET
  13. 03e,30may97,sgv  fix for spr#8653, Check for NULL parameter in nfsExportShow
  14. 03d,06aug96,sgv  fix for spr#6468
  15. 03c,06aug96,sgv  fix for spr #4278. Eliminated the nfsLib closing
  16.  of the UDP socket(multiple close).
  17. 03b,06aug96,sgv  fix for spr#5895
  18. 03a,23feb95,caf  cleaned up pointer reference in nfsExportShow().
  19. 02g,09oct94,jag  nfsDirReadOne() was changed to handle EOF correctly.
  20. 02f,08sep94,jmm  Changed to use the new rpc genned versions of the xdr rtns
  21. 02e,11aug93,jmm  Changed ioctl.h and socket.h to sys/ioctl.h and sys/socket.h
  22. 02d,28jul93,jmm  moved AUTH_UNIX_FIELD_LEN and MAX_GRPS definitions to nfsLib.h
  23. 02c,03feb93,jdi  documentation cleanup for 5.1.
  24. 02b,16sep92,jcf  change typedef path to nfsPath.
  25. 02a,07sep92,smb  added blksize and blocks to the stat structure initialisation.
  26. 01z,19aug92,smb  Changed systime.h to sys/times.h.
  27. 01y,18jul92,smb  Changed errno.h to errnoLib.h.
  28. 01x,26may92,rrr  the tree shuffle
  29.   -changed includes to have absolute path from h/
  30. 01w,20jan92,jmm  changed nfsDirReadOne to also set errno to OK
  31. 01w,20jan92,jmm  changed nfsThingCreate to recognize symlinks (spr 1059)
  32. 02n,19dec91,rrr  put dirent.h before nfsLib.h so it would compile
  33. 02m,13dec91,gae  ANSI fixes.
  34. 02l,19nov91,rrr  shut up some ansi warnings.
  35. 02k,04oct91,rrr  passed through the ansification filter
  36.                   -changed functions to ansi style
  37.   -changed includes to have absolute path from h/
  38.   -changed VOID to void
  39.   -changed copyright notice
  40. 02j,26apr91,shl  removed NULL entry in help_msg of nfsHelp() (spr 987).
  41. 02i,05apr91,jdi  documentation -- removed header parens and x-ref numbers;
  42.  switched nfsHelp() to first position; doc review by dnw.
  43. 02h,08mar91,elh  added nfsReXmit{Sec,USec} so re-xmit time not hardcoded.
  44. 02g,22feb91,lpf  made 'ls' command work on files mounted from HP. (SPR #0935)
  45. 02f,21feb91,jaa  documentation.
  46. 02e,02oct90,hjb  added a call to htons() where needed.
  47. 02d,19jul90,dnw  mangen fix
  48. 02c,26jun90,jcf  changed semaphores to be mutex.
  49. 02b,29may90,dnw  fixed bug in nfsInit, introduced in 01x, of testing
  50.     taskRpcStatics->nfsClientCache before rpcTaskInit is called
  51.  made nfsInit be NOMANUAL
  52. 02a,10may90,dnw  fixed nfsDeleteHook to delete the owner task's nfs stuff rather
  53.    than the exception task's (del hooks are called by exception
  54.    task).
  55.  fixed nfsDeleteHook to free nfsClientCache
  56.  fixed nfsInit to add nfsDeleteHook only once
  57.  fixed bug in authorization usage: added authCount field to
  58.    verify that cached client authorization matches current
  59.    global setting
  60.  changed name of nfsAllUnmount() to nfsMntUnmountAll()
  61.  optimized by removing some unnecessary "freeres" calls
  62.  optimized by supplying buffers in xdr calls instead of having
  63.    them malloc'd, in readres (nfsFileRead) result msgs.
  64.  optimized by adding xdr_readdirresOne hack to nfsDirReadOne
  65.    which just decodes first entry and discards the rest.
  66.  changed references to taskModuleList to taskRpcStatics
  67.  added nfsExportRead and nfsExportFree for use by nfsMountAll
  68.    in nfsDrv
  69.  extracted client cache stuff from nfsClientCall() to new
  70.    function nfsClientCacheSetUp()
  71.  added forward declarations to fix lint about void
  72.  changed MAX_FILENAME_LENGTH to POSIX definitions PATH_MAX
  73.    and NAME_MAX where appropriate
  74.  cosmetic changes to print out of nfsExportShow and
  75.    nfsMountListPrint
  76.  removed nfsDirListPrint() (no longer used)
  77.  removed some unnecessary error printing
  78.  changed documentation about nfs's large stack requirements
  79.    (no longer a pig!)
  80. 01w,01may90,llk  deleted nfsLs().
  81.  added nfsDirReadOne() and nfsFileAttrGet().
  82.  changed to check return value of taskDeleteHookAdd().
  83.  changed calls to pathBuild() and pathCat() to examine return
  84.    values.
  85. 01v,14apr90,jcf  removed tcb extension dependencies.
  86. 01u,01apr90,llk  turned the `oldhost' field of moduleStatics into an array.
  87.  substituted smaller constants MAX_FILENAME_LENGTH for the
  88.    SUN specified NFS_MAXNAMLEN and NFS_MAXPATHLEN.
  89.  added safety checks for filename lengths.
  90.  deleted calls to pathArrayFree().
  91.  changed call to pathParse().
  92.  changed to clean out the CLIENT cache if authorization
  93.    parameters are changed by calling nfsClientCacheCleanUp().
  94.  changed rpcAuthUnix to nfsAuthUnix.  Made it LOCAL.
  95. 01t,07mar90,jdi  documentation cleanup.
  96. 01s,03dec89,llk  changed nfsClientClose() to check for non-null taskModuleList
  97.    before cleaning up the nfs cache.
  98. 01r,20oct89,hjb  changed "struct timeval" to nfsTimeval to avoid conflicts
  99.  with the definition of "struct timeval" in "utime.h".
  100. 01q,28aug89,dab  modified nfsFileRemove() to delete symbolic links.
  101. 01p,23jul89,gae  added taskDeleteHook for nfsCleanup.
  102. 01o,06jul89,llk  deleted nfsNameArrayFree().  Added call to pathArrayFree().
  103.  reworked calls to pathLib.  added panic() calls.  delinted.
  104. 01n,09jun89,llk  fixed bug in nfsLookUpByName() which showed up via rmdir().
  105. 01m,23may89,dnw  lint.
  106. 01l,26mar89,llk  added nfsClientCacheCleanUp and nfsNameArrayFree to get rid
  107.    of memory eaters.
  108. 01k,09nov88,llk  rearranged error checking of nfs structures returned by server.
  109. 01j,28sep88,llk  added nfsSockBufSize, nfsTimeoutSec, nfsTimeoutUSec.
  110.  added nfsIdSet().
  111. 01i,25aug88,gae  documentation.
  112. 01h,07jul88,jcf  lint.
  113. 01g,30jun88,llk  changed to handle links.
  114.  added nfsHelp().
  115.  more name changes.
  116. 01f,16jun88,llk  changed to more v4 names.
  117.  added LOCAL and NOMANUAL where appropriate.
  118.  moved pathSplit() to pathLib.c.
  119. 01e,04jun88,llk  rewrote nfsLs and nfsDirRead so they clean up after themselves.
  120.  incorporated pathLib.
  121.  added nfsAuthUnix{Set Get Prompt Show} for unix authentication.
  122. 01d,30may88,dnw  changed to v4 names.
  123. 01c,28may88,dnw  copied promptParam...() stuff here from bootLib so that
  124.    this lib doesn't depend on bootLib.
  125. 01b,26apr88,llk  bug fix.  Internet address returned from remGetHostByName
  126.    was compared to <= NULL.  Some large addresses can be
  127.    mistaken for negative numbers.
  128. 01a,19apr88,llk  written.
  129. */
  130. /*
  131. DESCRIPTION
  132. This library provides the client side of services for NFS (Network File
  133. System) devices.  Most routines in this library should not be called by
  134. users, but rather by device drivers.  The driver is responsible for
  135. keeping track of file pointers, mounted disks, and cached buffers.  This
  136. library uses Remote Procedure Calls (RPC) to make the NFS calls.
  137. VxWorks is delivered with NFS disabled.
  138. To use this feature, include the following component:
  139. INCLUDE_NFS
  140. In the same file, NFS_USER_ID and NFS_GROUP_ID should be
  141. defined to set the default user ID and group ID at system start-up.
  142. For information about creating NFS devices, see the 
  143. * .I "WindNet TCP/IP Network Programmer's Guide"
  144. Normal use of NFS requires no more than 2000 bytes of stack. This 
  145. requirement may change depending on how the maximum file name path length 
  146. parameter, NFS_MAXPATH, is configured. As many as 4 character arrays of
  147. length NFS_MAXPATH may be allocated off the stack during client operation.
  148. Therefore any increase in the parameter can increase stack usage by a
  149. factor of four times the deviation from default NFS_MAXPATH. For example,
  150. a change from 255 to 1024 will increase peak stack usage by (1024 -255) * 4
  151. which is 3076 bytes.
  152. NFS USER IDENTIFICATION
  153. NFS is built on top of RPC and uses a type of RPC authentication known as
  154. AUTH_UNIX, which is passed on to the NFS server with every NFS request.
  155. AUTH_UNIX is a structure that contains necessary information for NFS,
  156. including the user ID number and a list of group IDs to which the user 
  157. belongs.  On UNIX systems, a user ID is specified in the file 
  158. f3/etc/passwdfP.  The list of groups to which a user belongs is 
  159. specified in the file f3/etc/groupfP.
  160. To change the default authentication parameters, use nfsAuthUnixPrompt().
  161. To change just the AUTH_UNIX ID, use nfsIdSet().  Usually, only the user
  162. ID needs to be changed to indicate a new NFS user.
  163. INCLUDE FILES: nfsLib.h
  164. SEE ALSO
  165. rpcLib, ioLib, nfsDrv
  166. INTERNAL
  167. Every routine starts with a call to nfsInit.  nfsInit initializes RPC
  168. and sets up the appropriate RPC task variables used for NFS.  It
  169. may be called more than once with the only ill effect being wasted time.
  170. The constant nfsMaxPath is used instead of NFS_MAXPATHLEN (1024) or
  171. PATH_MAX (255). nfsMaxPath is derived from the configuration parameter
  172. NFS_MAXPATH. A short length like 255 helps conserve memory but restricts 
  173. use of longer paths. The introduction of NFS_MAXPATH allows the user to
  174. decide which is more important. The constant (NAME_MAX + 1) is used instead
  175. of NFS_MAXNAMELEN (255) in order to conserve memory. All file/path names 
  176. which have come to nfsLib via the I/O system, such as filenames being passed 
  177. to nfsLookUpByName(), have already been screened for their path and name 
  178. lengths being less than PATH_MAX and NAME_MAX.
  179. xdr_nfs has been changed to use the shorter lengths as well.
  180. */
  181. /* LINTLIBRARY */
  182. #include "vxWorks.h"
  183. #include "limits.h"
  184. #include "ctype.h"
  185. #include "string.h"
  186. #include "ioLib.h"
  187. #include "taskLib.h"
  188. #include "taskHookLib.h"
  189. #include "rpc/rpc.h"
  190. #include "stdlib.h"
  191. #include "sys/socket.h"
  192. #include "netinet/in.h"
  193. #include "rpc/auth.h"
  194. #include "rpc/rpcGbl.h"
  195. #include "xdr_nfs.h"
  196. #include "sys/stat.h"
  197. #include "dirent.h"
  198. #include "nfsLib.h"
  199. #include "hostLib.h"
  200. #include "sys/times.h"
  201. #include "sockLib.h"
  202. #include "pathLib.h"
  203. #include "stdio.h"
  204. #include "unistd.h"
  205. #include "errnoLib.h"
  206. #include "rpcLib.h"
  207. #include "netLib.h"
  208. #include "fioLib.h"
  209. #include "memPartLib.h"
  210. #define READDIR_MAXLEN 512 /* increased for NFSPROC_READDIR on */
  211. /* HP server */
  212. #ifdef __GNUC__
  213. # ifndef alloca
  214. #  define alloca __builtin_alloca
  215. # endif
  216. #endif
  217. /* IMPORTS */
  218. IMPORT int   nfsMaxPath;               /* max. length of file path */
  219. /* GLOBALS */
  220. unsigned nfsMaxMsgLen = NFS_MAXDATA; /* largest read or write buffer that
  221.  * can be transfered to/from the nfs
  222.  * server
  223.  */
  224. u_int nfsTimeoutSec   = NFS_TIMEOUT_SEC;
  225. u_int nfsTimeoutUSec  = NFS_TIMEOUT_USEC;
  226. u_int nfsReXmitSec    = NFS_REXMIT_SEC;
  227. u_int nfsReXmitUSec   = NFS_REXMIT_USEC;
  228. int   nfsSockBufSize  = NFS_SOCKOPTVAL;
  229. /* LOCALS */
  230. /*
  231. Static RPC information.
  232. Set on initial NFS invocation and re-used during
  233. subsequent calls on a per task basis.
  234. */
  235. typedef struct moduleStatics
  236.     {
  237.     CLIENT *client;     /* pointer to client structure */
  238.     int socket;         /* socket associated with this client */
  239.     int oldprognum;     /* last program number used with this client */
  240.     int oldversnum;     /* last version number used with this client */
  241.     int authCount; /* auth count this client was built with */
  242.     int valid;          /* if TRUE, then this client information is valid */
  243.     char oldhost [MAXHOSTNAMELEN];
  244.      /* last host name that was used with this client */
  245.     } NFS_MODULE_STATICS;
  246. typedef struct /* NFS_AUTH_UNIX_TYPE - UNIX authentication structure */
  247.     {
  248.     char machname [AUTH_UNIX_FIELD_LEN];  /* host name where client is */
  249.     int uid; /* client's UNIX effective uid */
  250.     int gid; /* client's current group ID */
  251.     int len; /* element length of aup_gids */
  252.     int aup_gids [MAX_GRPS]; /* array of groups user is in */
  253.     } NFS_AUTH_UNIX_TYPE;
  254. /* There is a single global nfs authorization, nfsAuthUnix.
  255.  * Any time it is changed, nfsAuthCount is bumped.  This count is kept
  256.  * in the nfsClientCache to make sure that the client was built with the
  257.  * current authorization parameters.  In the future, it might be desirable
  258.  * to let different tasks have different authorizations.
  259.  */
  260. LOCAL NFS_AUTH_UNIX_TYPE nfsAuthUnix;
  261. LOCAL int  nfsAuthCount;
  262. LOCAL BOOL nfsInstalled;
  263. /* forward declarations */
  264. LOCAL STATUS nfsClientCall (char *host, u_int prognum, u_int versnum, u_int procnum, xdrproc_t inproc, char *in, xdrproc_t outproc, char *out);
  265. LOCAL STATUS nfsLinkGet (char * hostName, nfs_fh * pHandle, nfspath realPath);
  266. LOCAL STATUS nfsInit (void);
  267. LOCAL void nfsDeleteHook ();
  268. LOCAL void nfsClientCacheCleanUp ();
  269. LOCAL void nfsMountListPrint ();
  270. LOCAL void nfsGroupsPrint ();
  271. LOCAL void nfsExportPrint ();
  272. LOCAL void nfsErrnoSet ();
  273. LOCAL void printClear ();
  274. LOCAL void promptParamString ();
  275. LOCAL void promptParamNum ();
  276. /*******************************************************************************
  277. *
  278. * nfsDirMount - mount an NFS directory
  279. *
  280. * RETURNS: OK or ERROR
  281. *
  282. * NOMANUAL
  283. */
  284. STATUS nfsDirMount
  285.     (
  286.     char *hostName,
  287.     dirpath dirname,
  288.     nfs_fh *pFileHandle         /* the directory's file handle */
  289.     )
  290.     {
  291.     fhstatus fileHandleStatus;
  292.     bzero ((char *) &fileHandleStatus, sizeof (fileHandleStatus));
  293.     if (nfsClientCall (hostName, MOUNTPROG, MOUNTVERS, MOUNTPROC_MNT,
  294. xdr_dirpath, (char *) &dirname,
  295. xdr_fhstatus, (char *) &fileHandleStatus) == ERROR)
  296. {
  297. return (ERROR);
  298. }
  299.     if (fileHandleStatus.fhs_status != 0)
  300. {
  301. netErrnoSet ((int) fileHandleStatus.fhs_status); /* UNIX error */
  302. return (ERROR);
  303. }
  304.     bcopy ((char *) &fileHandleStatus.fhstatus_u.fhs_fhandle,
  305.    (char *) pFileHandle, sizeof (nfs_fh));
  306.     return (OK);
  307.     }
  308. /*******************************************************************************
  309. *
  310. * nfsDirUnmount - unmount an NFS directory
  311. *
  312. * RETURNS: OK or ERROR
  313. *
  314. * NOMANUAL
  315. */
  316. STATUS nfsDirUnmount
  317.     (
  318.     char *hostName,
  319.     dirpath dirname
  320.     )
  321.     {
  322.     return (nfsClientCall (hostName, MOUNTPROG, MOUNTVERS, MOUNTPROC_UMNT,
  323. xdr_dirpath, (char *) &dirname,
  324. xdr_void, (char *) NULL));
  325.     }
  326. /*******************************************************************************
  327. *
  328. * nfsMntUnmountAll - unmount all file systems on a particular host
  329. *
  330. * This routine removes all NFS file systems mounted on <hostName> from that
  331. * host's client list.  It does NOT actually "unmount" the file systems.
  332. *
  333. * RETURNS: OK or ERROR.
  334. *
  335. * SEE ALSO: nfsMntDump()
  336. *
  337. * NOMANUAL
  338. */
  339. STATUS nfsMntUnmountAll
  340.     (
  341.     char *hostName              /* host machine to unmount from */
  342.     )
  343.     {
  344.     return (nfsClientCall (hostName, MOUNTPROG, MOUNTVERS, MOUNTPROC_UMNTALL,
  345. xdr_void, (char *) NULL,
  346. xdr_void, (char *) NULL));
  347.     }
  348. /*******************************************************************************
  349. *
  350. * nfsMntDump - display all NFS file systems mounted on a particular host
  351. *
  352. * This routine displays all the NFS file systems mounted on a specified host
  353. * machine.
  354. *
  355. * RETURNS: OK or ERROR.
  356. *
  357. * NOMANUAL
  358. */
  359. STATUS nfsMntDump
  360.     (
  361.     char *hostName              /* host machine */
  362.     )
  363.     {
  364.     mountlist mEntries;
  365.     bzero ((char *) &mEntries, sizeof (mEntries));
  366.     if (nfsClientCall (hostName, MOUNTPROG, MOUNTVERS, MOUNTPROC_DUMP,
  367. xdr_void, (char *) NULL,
  368. xdr_mountlist, (char *) &mEntries) == ERROR)
  369. {
  370. return (ERROR);
  371. }
  372.     if (mEntries)
  373. nfsMountListPrint (mEntries);
  374.     clntudp_freeres (taskRpcStatics->nfsClientCache->client, xdr_mountlist,
  375.      (caddr_t) &mEntries);
  376.     return (OK);
  377.     }
  378. /*******************************************************************************
  379. *
  380. * nfsExportRead - get list of a host's exported file systems
  381. *
  382. * This routine gets the exported file systems of a specified host and the groups
  383. * that are allowed to mount them.
  384. *
  385. * After calling this routine, the export list must be free'd by calling
  386. * nfsExportFree.
  387. *
  388. * RETURNS: OK or ERROR.
  389. *
  390. * NOMANUAL
  391. */
  392. STATUS nfsExportRead
  393.     (
  394.     char *hostName,     /* host machine for which to show exports */
  395.     exports *pExports
  396.     )
  397.     {
  398.     bzero ((char *) pExports, sizeof (*pExports));
  399.     return (nfsClientCall (hostName, MOUNTPROG, MOUNTVERS, MOUNTPROC_EXPORT,
  400.    xdr_void, (char *) NULL,
  401.    xdr_exports, (char *) pExports));
  402.     }
  403. /*******************************************************************************
  404. *
  405. * nfsExportFree - get list of a host's exported file systems
  406. *
  407. * This routine frees the list of exported file systems returned by
  408. * nfsExportRead.  It must be called after calling nfsExportRead, if
  409. * nfsExportRead returns OK.
  410. *
  411. * RETURNS: OK
  412. *
  413. * NOMANUAL
  414. */
  415. STATUS nfsExportFree
  416.     (
  417.     exports *pExports
  418.     )
  419.     {
  420.     clntudp_freeres (taskRpcStatics->nfsClientCache->client, xdr_exports,
  421.      (caddr_t) pExports);
  422.     return (OK);
  423.     }
  424. /*******************************************************************************
  425. *
  426. * nfsHelp - display the NFS help menu
  427. *
  428. * This routine displays a summary of NFS facilities typically called from
  429. * the shell:
  430. * .CS
  431. *     nfsHelp                       Print this list
  432. *     netHelp                       Print general network help list
  433. *     nfsMount "host","filesystem"[,"devname"]  Create device with
  434. *                                     file system/directory from host
  435. *     nfsUnmount "devname"          Remove an NFS device
  436. *     nfsAuthUnixShow               Print current UNIX authentication
  437. *     nfsAuthUnixPrompt             Prompt for UNIX authentication
  438. *     nfsIdSet id     Set user ID for UNIX authentication
  439. *     nfsDevShow                    Print list of NFS devices
  440. *     nfsExportShow "host"          Print a list of NFS file systems which
  441. *                                     are exported on the specified host
  442. *     mkdir "dirname"               Create directory
  443. *     rm "file"                     Remove file
  444. *
  445. *     EXAMPLE:  -> hostAdd "wrs", "90.0.0.2"
  446. *               -> nfsMount "wrs","/disk0/path/mydir","/mydir/"
  447. *               -> cd "/mydir/"
  448. *               -> nfsAuthUnixPrompt     /@ fill in user ID, etc.     @/
  449. *               -> ls                    /@ list /disk0/path/mydir    @/
  450. *               -> copy < foo            /@ copy foo to standard out  @/
  451. *               -> ld < foo.o            /@ load object module foo.o  @/
  452. *               -> nfsUnmount "/mydir/"  /@ remove NFS device /mydir/ @/
  453. * .CE
  454. *
  455. * RETURNS: N/A
  456. */
  457. void nfsHelp (void)
  458.     {
  459.     static char *help_msg [] =
  460. {
  461. "nfsHelp                       Print this list",
  462. "netHelp                       Print general network help list",
  463. "nfsMount "host","filesystem"[,"devname"]  Create device with",
  464. "                                file system/directory from host",
  465. "nfsUnmount "devname"          Remove an NFS device",
  466. "nfsAuthUnixShow               Print current UNIX authentication",
  467. "nfsAuthUnixPrompt             Prompt for UNIX authentication",
  468. "nfsIdSet id                   Set user ID for UNIX authentication",
  469. "nfsDevShow                    Print list of NFS devices",
  470. "nfsExportShow "host"          Print a list of NFS file systems which",
  471. "                                are exported on the specified host",
  472. "mkdir "dirname"               Create directory",
  473. "rm "file"                     Remove file",
  474. "",
  475. "EXAMPLE:  -> hostAdd "wrs", "90.0.0.2"",
  476. "          -> nfsMount "wrs","/disk0/path/mydir","/mydir/"",
  477. "          -> cd "/mydir/"",
  478. "          -> nfsAuthUnixPrompt     /* fill in user ID, etc. *",
  479. "          -> ls                    /* list /disk0/path/mydir *",
  480. "          -> copy < foo            /* copy foo to standard out *",
  481. "          -> ld < foo.o            /* load object module foo.o *",
  482. "          -> nfsUnmount "/mydir/"  /* remove NFS device /mydir/ *",
  483. };
  484.     FAST int ix;
  485.     for (ix = 0; ix < NELEMENTS(help_msg); ix++)
  486. printf ("%sn", help_msg [ix]);
  487.     printf ("n");
  488.     }
  489. /*******************************************************************************
  490. *
  491. * nfsExportShow - display the exported file systems of a remote host
  492. *
  493. * This routine displays the file systems of a specified host and the groups
  494. * that are allowed to mount them.
  495. *
  496. * EXAMPLE
  497. * .CS
  498. *    -> nfsExportShow "wrs"
  499. *    /d0               staff
  500. *    /d1               staff eng
  501. *    /d2               eng
  502. *    /d3
  503. *    value = 0 = 0x0
  504. * .CE
  505. *
  506. * RETURNS: OK or ERROR.
  507. */
  508. STATUS nfsExportShow
  509.     (
  510.     char *hostName      /* host machine to show exports for */
  511.     )
  512.     {
  513.     exports nfsExports;
  514.     if (hostName == NULL)
  515.         {
  516.         errnoSet (S_hostLib_INVALID_PARAMETER);
  517.         return (ERROR);
  518.         }
  519.     if (nfsExportRead (hostName, &nfsExports) != OK)
  520. return (ERROR);
  521.     if (nfsExports)
  522. nfsExportPrint (nfsExports);
  523.     return (nfsExportFree (&nfsExports));
  524.     }
  525. /*******************************************************************************
  526. *
  527. * nfsLookUpByName - looks up a remote file
  528. *
  529. * This routine returns information on a given file.
  530. * It takes the host name, mount handle, and file name, and returns the
  531. * file handle of the file and the file's attributes in pDirOpRes, and
  532. * the file handle of the directory that the file resides in in pDirHandle.
  533. *
  534. * If the file name (directory path or filename itself) contains a symbolic
  535. * link, this routine changes the file name to incorporate the name of the link.
  536. *
  537. * RETURNS:  OK | ERROR | FOLLOW_LINK,
  538. *     if FOLLOW_LINK, then fileName contains the name of the link
  539. *
  540. * NOMANUAL
  541. */
  542. int nfsLookUpByName
  543.     (
  544.     char        *hostName,
  545.     char        *fileName,      /* name is changed if symbolic link */
  546.     nfs_fh      *pMountHandle,
  547.                                 /* these args are returned to calling routine */
  548.     FAST diropres *pDirOpRes,   /*    pointer to directory operation results */
  549.     nfs_fh      *pDirHandle     /*    pointer to file's directory file handle */
  550.     )
  551.     {
  552.     diropargs file;
  553.     int nameCount = 0;
  554.     char *nameArray  [MAX_DIRNAMES]; /* ptrs to individual dir/file names
  555.       * in path name */
  556.     char *nameBuf;                   /* buffer for individual dir/file names */
  557.     char *newLinkName;               /* new file name if file is symb link */
  558.     char *linkName;                  /* name of link file */
  559.     char *currentDir;                /* current dir for the look up's
  560.       * that have been done */
  561.     if (nfsInit () != OK)
  562. return (ERROR);
  563.     if ((nameBuf = (char *) alloca (nfsMaxPath)) == NULL)
  564. return (ERROR);
  565.     if ((newLinkName = (char *) alloca (nfsMaxPath)) == NULL)
  566. return (ERROR);
  567.     if ((linkName = (char *) alloca (nfsMaxPath)) == NULL)
  568. return (ERROR);
  569.     if ((currentDir = (char *) alloca (nfsMaxPath)) == NULL)
  570. return (ERROR);
  571.     bzero ((char *) &file, sizeof (file));
  572.     /* parse file name, enter each directory name in the path into the array */
  573.     pathParse (fileName, nameArray, nameBuf);
  574.     bcopy ((char *) pMountHandle, (char *) &file.dir, sizeof (nfs_fh));
  575.     bcopy ((char *) pMountHandle, (char *) pDirHandle, sizeof (nfs_fh));
  576.     /* start traversing file name */
  577.     while ((nameCount < MAX_DIRNAMES) && (nameArray [nameCount] != NULL))
  578. {
  579. file.name = nameArray [nameCount];
  580. if (nfsClientCall (hostName, NFS_PROGRAM, NFS_VERSION, NFSPROC_LOOKUP,
  581.     xdr_diropargs, (char *) &file,
  582.     xdr_diropres, (char *) pDirOpRes) == ERROR)
  583.     {
  584.     return (ERROR);
  585.     }
  586. if (pDirOpRes->status != NFS_OK)
  587.     {
  588.     nfsErrnoSet (pDirOpRes->status);
  589.     return (ERROR);
  590.     }
  591. if (pDirOpRes->diropres_u.diropres.attributes.type == NFDIR)
  592.     {
  593.     /* save directory information */
  594.     /* Store the directory handle of the second to last entry
  595.      * in the path name array.  This is the directory where the
  596.      * file in question (or directory in question) lives.
  597.      */
  598.     if ((nameCount < MAX_DIRNAMES - 1)
  599.         && (nameArray [nameCount + 1] != NULL))
  600.         {
  601. bcopy ((char *) &pDirOpRes->diropres_u.diropres.file,
  602.        (char *) pDirHandle, sizeof (nfs_fh));
  603.         }
  604.     /* copy directory handle for the next nfsClientCall */
  605.     bcopy ((char *) &pDirOpRes->diropres_u.diropres.file,
  606.    (char *) &file.dir, sizeof (nfs_fh));
  607.     }
  608. else if (pDirOpRes->diropres_u.diropres.attributes.type == NFLNK)
  609.     {
  610.     /* symbolic link, get real path name */
  611.     if (nfsLinkGet (hostName, &pDirOpRes->diropres_u.diropres.file,
  612.     linkName) == ERROR)
  613. {
  614. return (ERROR);
  615. }
  616.     /* Change fileName to include name of link.
  617.      * Concatenate the directory name, link name,
  618.      * and rest of the path name following the link.
  619.      */
  620.     *currentDir = EOS;
  621.     if ((pathBuild (nameArray, &(nameArray [nameCount]),
  622.     currentDir) == ERROR)
  623. || (pathCat (currentDir, linkName, newLinkName) == ERROR)
  624. || (pathBuild (&(nameArray [++nameCount]), (char **) NULL,
  625.        newLinkName) == ERROR))
  626. {
  627. return (ERROR);
  628. }
  629.     pathCondense (newLinkName);
  630.     (void) strcpy (fileName, newLinkName);
  631.     return (FOLLOW_LINK);
  632.     }
  633. nameCount++; /* look up next directory */
  634. } /* while */
  635.     return (OK);
  636.     }
  637. /*******************************************************************************
  638. *
  639. * nfsFileRemove - remove a file
  640. *
  641. * RETURNS: OK or ERROR
  642. *
  643. * NOMANUAL
  644. */
  645. STATUS nfsFileRemove
  646.     (
  647.     char *      hostName,
  648.     nfs_fh *    pMountHandle,   /* file handle of mount device */
  649.     char *      fullFileName
  650.     )
  651.     {
  652.     u_int nfsProc;
  653.     diropres dirResults;
  654.     diropargs where;
  655.     nfsstat status;
  656.     int         retVal;
  657.     char fileName [NAME_MAX + 1];
  658.     char * dirName;
  659.     nfs_fh dirHandle;
  660.     if (nfsInit () != OK)
  661. return (ERROR);
  662.     if (strlen (fullFileName) >= nfsMaxPath)
  663. return (ERROR);
  664.     if ((dirName = (char *) alloca (nfsMaxPath)) == NULL)
  665. return (ERROR);
  666.     bzero ((char *) &dirResults, sizeof (dirResults));
  667.     bzero ((char *) &status, sizeof (status));
  668.     pathSplit (fullFileName, dirName, fileName);
  669.     /*
  670.      * get info on the file to be removed, such as the handle of its directory
  671.      * and its file type (so we know whether to delete a file or directory)
  672.      *
  673.      * note:  some file servers will indeed delete a file with the
  674.      *        NFSPROC_RMDIR command
  675.      */
  676.     retVal = nfsLookUpByName (hostName, fullFileName, pMountHandle,
  677.  &dirResults, &dirHandle);
  678.     if (retVal == FOLLOW_LINK)
  679.         {
  680.         return (FOLLOW_LINK);
  681.         }
  682.     else
  683.         if (retVal == ERROR)
  684.             return (ERROR);
  685.     bcopy ((char *) &dirHandle, (char *) &where.dir, sizeof (nfs_fh));
  686.     where.name = fileName;
  687.     switch (dirResults.diropres_u.diropres.attributes.type)
  688. {
  689. case NFREG: /* remove regular file */
  690. case NFLNK: /* remove symbolic link */
  691.     nfsProc = NFSPROC_REMOVE;
  692.     break;
  693. case NFDIR: /* remove directory */
  694.     nfsProc = NFSPROC_RMDIR;
  695.     break;
  696. default:
  697.     errnoSet (S_nfsLib_NFS_INAPPLICABLE_FILE_TYPE);
  698.     return (ERROR);
  699. }
  700.     if (nfsClientCall (hostName, NFS_PROGRAM, NFS_VERSION, nfsProc,
  701.     xdr_diropargs, (char *) &where,
  702.     xdr_nfsstat, (char *) &status) == ERROR)
  703. {
  704. return (ERROR);
  705. }
  706.     if (status != NFS_OK)
  707. {
  708. nfsErrnoSet (status);
  709. return (ERROR);
  710. }
  711.     return (OK);
  712.     }
  713. /*******************************************************************************
  714. *
  715. * nfsRename - rename a file
  716. *
  717. * RETURNS: OK or ERROR
  718. *
  719. * NOMANUAL
  720. */
  721. STATUS nfsRename
  722.     (
  723.     char *      hostName,
  724.     nfs_fh *    pMountHandle,
  725.     char *      oldName,
  726.     nfs_fh *    pOldDirHandle,
  727.     char *      newName
  728.     )
  729.     {
  730.     diropres dirResults;
  731.     renameargs renameArgs;
  732.     nfsstat status;
  733.     char newFileName [NAME_MAX + 1];
  734.     char oldFileName [NAME_MAX + 1];
  735.     char * newDirName;
  736.     char * oldDirName;
  737.     nfs_fh dummyDirHandle;
  738.     if (nfsInit () != OK)
  739. return (ERROR);
  740.     if ((strlen (oldName) >= nfsMaxPath) || (strlen (newName) >= nfsMaxPath))
  741. {
  742. errnoSet (S_ioLib_NAME_TOO_LONG);
  743. return (ERROR);
  744. }
  745.     if ((newDirName = (char *) alloca (nfsMaxPath)) == NULL)
  746. return (ERROR);
  747.     if ((oldDirName = (char *) alloca (nfsMaxPath)) == NULL)
  748. return (ERROR);
  749.     bzero ((char *) &dirResults, sizeof (dirResults));
  750.     bzero ((char *) &status, sizeof (status));
  751.     pathSplit (oldName, oldDirName, oldFileName);
  752.     pathSplit (newName, newDirName, newFileName);
  753.     bcopy ((char *) pOldDirHandle, (char *) &renameArgs.from.dir,
  754.    sizeof (nfs_fh));
  755.     renameArgs.from.name = oldFileName;
  756.     if (newDirName [0] == EOS)
  757. {
  758. /* NULL directory name */
  759. bcopy ((char *) pMountHandle, (char *) &renameArgs.to.dir,
  760.        sizeof (nfs_fh));
  761. }
  762.     else
  763. {
  764. if (nfsLookUpByName (hostName, newDirName, pMountHandle,
  765.      &dirResults, &dummyDirHandle) != OK)
  766.     return (ERROR);
  767. bcopy ((char *) &dirResults.diropres_u.diropres.file,
  768.        (char *) &renameArgs.to.dir, sizeof (nfs_fh));
  769. }
  770.     renameArgs.to.name = newFileName;
  771.     if (nfsClientCall (hostName, NFS_PROGRAM, NFS_VERSION, NFSPROC_RENAME,
  772.     xdr_renameargs, (char *) &renameArgs,
  773.     xdr_nfsstat, (char *) &status) == ERROR)
  774. {
  775. return (ERROR);
  776. }
  777.     if (status != NFS_OK)
  778. {
  779. nfsErrnoSet (status);
  780. return (ERROR);
  781. }
  782.     return (OK);
  783.     }
  784. /*******************************************************************************
  785. *
  786. * nfsThingCreate - creates file or directory
  787. *
  788. * RETURNS:  OK | ERROR | FOLLOW_LINK,
  789. *     if FOLLOW_LINK, then fullFileName contains the name of the link
  790. *
  791. * NOMANUAL
  792. */
  793. int nfsThingCreate
  794.     (
  795.     char *      hostName,
  796.     char *      fullFileName,   /* name of thing being created */
  797.     nfs_fh *    pMountHandle,   /* mount device's file handle */
  798.     diropres *  pDirOpRes,      /* ptr to returned direc. operation results */
  799.     nfs_fh *    pDirHandle,     /* ptr to returned file's directory file hndl */
  800.     u_int       mode            /* mode that file or dir is created with
  801.                                  *   UNIX chmod style */
  802.     )
  803.     {
  804.     FAST int status;
  805.     char * newName;              /* new name if name contained a link */
  806.     char * dirName;              /* dir where file will be created */
  807.     char fileName[NAME_MAX + 1];    /* name of file without path */
  808.     char * tmpName;       /* temporary file name */
  809.     FAST sattr *pSattr; /* ptr to attributes */
  810.     diropres lookUpResult;
  811.     createargs createArgs;
  812.     nfs_fh dummyDirHandle;
  813.     u_int nfsProc; /* which nfs procedure to call,
  814.  * depending on whether a file or
  815.  * directory is made */
  816.     if (nfsInit () != OK)
  817. return (ERROR);
  818.     if ((newName = (char *) alloca (nfsMaxPath)) == NULL)
  819. return (ERROR);
  820.     if ((dirName = (char *) alloca (nfsMaxPath)) == NULL)
  821. return (ERROR);
  822.     /* Extra 4 characters allocated for '/../' */
  823.     if ((tmpName = (char *) alloca (nfsMaxPath + 1 + 3)) == NULL)
  824. return (ERROR);
  825.     bzero ((char *) &createArgs, sizeof (createArgs));
  826.     bzero ((char *) &lookUpResult, sizeof (lookUpResult));
  827.     bzero ((char *) pDirOpRes, sizeof (diropres));
  828.     pathSplit (fullFileName, dirName, fileName);
  829.     status = nfsLookUpByName (hostName, dirName, pMountHandle, &lookUpResult,
  830.       &dummyDirHandle);
  831.     if (status == FOLLOW_LINK)
  832. {
  833. if ((strlen (dirName) + strlen (fileName) + 1) >= nfsMaxPath)
  834.     {
  835.     errnoSet (S_ioLib_NAME_TOO_LONG);
  836.     status = ERROR;
  837.     }
  838. else
  839.     {
  840.     pathCat (dirName, fileName, newName);
  841.     (void) strcpy (fullFileName, newName);
  842.     }
  843. }
  844.     if (status != OK)
  845. return (status);
  846.     bcopy ((char *) &lookUpResult.diropres_u.diropres.file,
  847.    (char *) &createArgs.where.dir, sizeof (nfs_fh));
  848.     bcopy ((char *) &lookUpResult.diropres_u.diropres.file,
  849.    (char *) pDirHandle, sizeof (nfs_fh));
  850.     createArgs.where.name = fileName;
  851.     pSattr = &createArgs.attributes;
  852.     if (mode == 0)
  853.      /* create a file with default permissions */
  854. pSattr->mode = NFS_FSTAT_REG | DEFAULT_FILE_PERM;
  855.     else
  856. pSattr->mode = mode;
  857.     /* don't set these attributes */
  858.     pSattr->uid = pSattr->gid = pSattr->size = -1; /* user ID */
  859.     pSattr->atime.seconds = pSattr->atime.useconds = -1;
  860.     pSattr->mtime.seconds = pSattr->mtime.useconds = -1;
  861.     if (mode & NFS_FSTAT_DIR)
  862. nfsProc = NFSPROC_MKDIR;
  863.     else
  864.         nfsProc = NFSPROC_CREATE;
  865.     if (nfsClientCall (hostName, NFS_PROGRAM, NFS_VERSION, nfsProc,
  866.     xdr_createargs, (char *) &createArgs,
  867.     xdr_diropres, (char *) pDirOpRes) == ERROR)
  868. {
  869. return (ERROR);
  870. }
  871.     /*
  872.      * If the file created is really a symlink, then change the name and
  873.      * return FOLLOW_LINK
  874.      */
  875.     if (pDirOpRes->diropres_u.diropres.attributes.type == NFLNK)
  876.         {
  877. strcpy (tmpName, fullFileName); /* Make a copy of fullFileName to
  878.  * use with nfsLinkGet */
  879. nfsLinkGet (hostName, &pDirOpRes->diropres_u.diropres.file, tmpName);
  880.         /*
  881.  * Need to replace last element of fullFileName with return value from
  882.          * nfsLinkGet.  Add /../newFileName to fullFileName, call
  883.          * pathCondense().
  884.  */
  885. strcpy (fullFileName, tmpName);
  886. return (FOLLOW_LINK);
  887. }
  888.     if (pDirOpRes->status != NFS_OK)
  889. {
  890. nfsErrnoSet (pDirOpRes->status);
  891. return (ERROR);
  892. }
  893.     return (OK);
  894.     }
  895. /*******************************************************************************
  896. *
  897. * nfsFileWrite - write to a file
  898. *
  899. * Either all characters will be written, or there is an ERROR.
  900. *
  901. * RETURNS:  number of characters written | ERROR
  902. *
  903. * NOMANUAL
  904. */
  905. int nfsFileWrite
  906.     (
  907.     char *      hostName,
  908.     nfs_fh *    pHandle,        /* file handle of file being written to */
  909.     unsigned    offset,         /* current byte offset in file */
  910.     unsigned    count,          /* number of bytes to write */
  911.     char *      data,           /* data to be written (up to NFS_MAXDATA) */
  912.     fattr *     pNewAttr
  913.     )
  914.     {
  915.     FAST unsigned nWrite = 0;       /* bytes written in one nfs write */
  916.     FAST unsigned nTotalWrite = 0;    /* bytes written in all writes together */
  917.     writeargs writeArgs;       /* arguments to pass to nfs server */
  918.     attrstat writeResult;       /* info returned from nfs server */
  919.     if (nfsInit () != OK)
  920. return (ERROR);
  921.     bzero ((char *) &writeArgs, sizeof (writeArgs));
  922.     bcopy ((char *) pHandle, (char *) &writeArgs.file, sizeof (nfs_fh));
  923.     /* set offset into file where write starts */
  924.     writeArgs.offset = offset;
  925.     while (nTotalWrite < count)
  926. {
  927. /* can only write up to NFS_MAXDATA bytes in one nfs write */
  928. if (count - nTotalWrite > nfsMaxMsgLen)
  929.     nWrite = nfsMaxMsgLen;
  930. else
  931.     nWrite = count - nTotalWrite;
  932. writeArgs.totalcount = nWrite;
  933. writeArgs.data.data_len = nWrite;
  934. writeArgs.data.data_val = data + nTotalWrite;
  935. writeArgs.offset = offset + nTotalWrite;
  936. bzero ((char *) &writeResult, sizeof (attrstat));
  937. if (nfsClientCall (hostName, NFS_PROGRAM, NFS_VERSION, NFSPROC_WRITE,
  938. xdr_writeargs, (char *) &writeArgs,
  939. xdr_attrstat, (char *) &writeResult) == ERROR)
  940.     {
  941.     return (ERROR);
  942.     /* XXX if some writes have been done and there was an error,
  943.      * nTotalWrite should be returned */
  944.     }
  945. if (writeResult.status != NFS_OK)
  946.     {
  947.     nfsErrnoSet (writeResult.status);
  948.     return (ERROR);
  949.     }
  950. nTotalWrite += nWrite;
  951. }
  952.     bcopy ((char *) &writeResult.attrstat_u.attributes, (char *) pNewAttr,
  953.    sizeof (fattr));
  954.     /* if nfs write returned ok, then all bytes were written */
  955.     return (count);
  956.     }
  957. /*******************************************************************************
  958. *
  959. * nfsFileRead - read from a file
  960. *
  961. * Reads as many bytes as are requested if that many bytes are left before
  962. * the end of file.
  963. *
  964. * RETURNS: number of characters read or ERROR
  965. *
  966. * NOMANUAL
  967. */
  968. int nfsFileRead
  969.     (
  970.     char *      hostName,
  971.     nfs_fh *    pHandle,        /* file handle of file being read */
  972.     unsigned    offset,         /* start at offset bytes from beg. of file */
  973.     unsigned    count,          /* number bytes to read up to */
  974.     char *      buf,            /* buffer that data is read into */
  975.     fattr *     pNewAttr        /* arguments returned from server */
  976.     )
  977.     {
  978.     FAST unsigned nRead = 0; /* number of bytes read in one read */
  979.     FAST unsigned nTotalRead = 0; /* bytes read in all reads together */
  980.     readargs readArgs; /* arguments to pass to nfs server */
  981.     readres readReply;
  982.     if (nfsInit () != OK)
  983. return (ERROR);
  984.     bzero ((char *) &readArgs, sizeof (readArgs));
  985.     bcopy ((char *) pHandle, (char *) &readArgs.file, sizeof (nfs_fh));
  986.     while (nTotalRead < count)
  987. {
  988. if (count - nTotalRead > nfsMaxMsgLen)
  989.     readArgs.count = nfsMaxMsgLen;
  990. else
  991.     readArgs.count = count - nTotalRead;
  992. readArgs.offset = offset + nTotalRead;
  993. bzero ((char *) &readReply, sizeof (readReply));
  994. /* make xdr buffer point to caller's buffer */
  995. readReply.readres_u.reply.data.data_val = buf + nTotalRead;
  996. if (nfsClientCall (hostName, NFS_PROGRAM, NFS_VERSION, NFSPROC_READ,
  997. xdr_readargs, (char *) &readArgs,
  998. xdr_readres, (char *) &readReply) == ERROR)
  999.     {
  1000.     return (ERROR);
  1001.     }
  1002. if (readReply.status != NFS_OK)
  1003.     {
  1004.     nfsErrnoSet (readReply.status);
  1005.     return (ERROR);
  1006.     }
  1007. /* check for end of file (data_len == 0) */
  1008. if ((nRead = readReply.readres_u.reply.data.data_len) == 0)
  1009.     break;
  1010. /* update attributes */
  1011. bcopy ((char *) &(readReply.readres_u.reply.attributes),
  1012.        (char *) pNewAttr, sizeof (fattr));
  1013. nTotalRead += nRead;
  1014. } /* while not all bytes requested have been read */
  1015.     return (nTotalRead);
  1016.     }
  1017. /*******************************************************************************
  1018. *
  1019. * nfsLinkGet - gets name of real file from a symbolic link
  1020. *
  1021. * RETURNS: OK or ERROR
  1022. */
  1023. LOCAL STATUS nfsLinkGet
  1024.     (
  1025.     char *      hostName,
  1026.     nfs_fh *    pHandle,        /* file handle of file being read */
  1027.     nfspath     realPath        /* the actual pathname gets returned here */
  1028.     )
  1029.     {
  1030.     readlinkres pathStatus;
  1031.     if (nfsInit () != OK)
  1032. return (ERROR);
  1033.     bzero ((char *) &pathStatus, sizeof (readlinkres));
  1034.     /* make xdr buffer point to caller's buffer */
  1035.     pathStatus.readlinkres_u.data = realPath;
  1036.     if (nfsClientCall (hostName, NFS_PROGRAM, NFS_VERSION, NFSPROC_READLINK,
  1037.     xdr_nfs_fh, (char *) pHandle,
  1038.     xdr_readlinkres, (char *) &pathStatus) == ERROR)
  1039. {
  1040. return (ERROR);
  1041. }
  1042.     if (pathStatus.status != NFS_OK)
  1043. {
  1044. nfsErrnoSet (pathStatus.status);
  1045. return (ERROR);
  1046. }
  1047.     return (OK);
  1048.     }
  1049. #if 0
  1050. /*******************************************************************************
  1051. *
  1052. * nfsDirRead - read entries from a directory
  1053. *
  1054. * RETURNS: OK or ERROR
  1055. */
  1056. LOCAL STATUS nfsDirRead
  1057.     (
  1058.     char *      hostName,
  1059.     nfs_fh *    pDirHandle,
  1060.     nfscookie   cookie,         /* hand this cookie to the server.  The cookie
  1061.                                  * marks a place in the directory where entries
  1062.                                  * are to be read from */
  1063.     unsigned    count,          /* number of bytes that nfs may return */
  1064.     readdirres *pReadDirRes     /* return the results of directory read here */
  1065.     )
  1066.     {
  1067.     readdirargs readDirArgs;
  1068.     if (nfsInit () != OK)
  1069. return (ERROR);
  1070.     bzero ((char *) &readDirArgs, sizeof (readdirargs));
  1071.     bcopy ((char *) pDirHandle, (char *) &readDirArgs.dir, sizeof (nfs_fh));
  1072.     bcopy (cookie, readDirArgs.cookie, sizeof (nfscookie));
  1073.     readDirArgs.count = count;
  1074.     bzero ((char *) pReadDirRes, sizeof (*pReadDirRes));
  1075.     if (nfsClientCall (hostName, NFS_PROGRAM, NFS_VERSION, NFSPROC_READDIR,
  1076.     xdr_readdirargs, (char *) &readDirArgs,
  1077.     xdr_readdirres, (char *) pReadDirRes) == ERROR)
  1078. {
  1079. return (ERROR);
  1080. }
  1081.     if (pReadDirRes->status != NFS_OK)
  1082. {
  1083. nfsErrnoSet (pReadDirRes->status);
  1084. return (ERROR);
  1085. }
  1086.     /* normally, the readdirres structure would be freed up here, but
  1087.      * the calling routine needs its information, so the calling routine
  1088.      * must call clntudp_freeres after calling nfsDirRead
  1089.      */
  1090.     return (OK);
  1091.     }
  1092. /*******************************************************************************
  1093. *
  1094. * nfsDirResFree - free the rcp readdirres result structure
  1095. *
  1096. * RETURNS: TRUE if successful, FALSE if error
  1097. */
  1098. LOCAL BOOL nfsDirResFree
  1099.     (
  1100.     readdirres *pReadDirRes
  1101.     )
  1102.     {
  1103.     return (clntudp_freeres (taskRpcStatics->nfsClientCache->client,
  1104.      xdr_readdirres, (caddr_t) pReadDirRes));
  1105.     }
  1106. #endif
  1107. /*******************************************************************************
  1108. *
  1109. * nfsDirReadOne - read one directory entry
  1110. *
  1111. * Read one directory entry on the host from the directory represented by
  1112. * the file handle *pDirHandle.  Update the DIR structure that is passed
  1113. * in and pointed to by pDir.
  1114. *
  1115. * NOTE:
  1116. * There is actually no way to tell the server we want only one entry.
  1117. * We only want one entry, but we have to provide a buffer for the maximum
  1118. * length filename, where the buffer size is specified in the "count" param
  1119. * to nfsDirRead.  The server will return as many entries as will fit in
  1120. * this buffer.  We will return the first entry to the caller and throw
  1121. * away the rest.  A subsequent call with the cookie of the previous
  1122. * entry will acquire the next entry, even though it may have been
  1123. * sent in previous call.
  1124. *
  1125. * In the future, we could cache several entries at a time and just return
  1126. * them to the caller, one at a time.
  1127. *
  1128. * RETURNS: OK, or ERROR if dir read fails,
  1129. *   returns ERROR but errno unchanged if EOF
  1130. *
  1131. * NOMANUAL
  1132. */
  1133. STATUS nfsDirReadOne
  1134.     (
  1135.     char *      hostName,       /* host name */
  1136.     nfs_fh *    pDirHandle,     /* file handle of directory */
  1137.     DIR *       pDir            /* ptr to DIR structure, return values here */
  1138.     )
  1139.     {
  1140.     readdirres   readRes;
  1141.     readdirargs  readDirArgs;
  1142.     bzero ((char *) &readRes, sizeof (readRes));
  1143.     
  1144.     if (nfsInit () != OK)
  1145. return (ERROR);
  1146.     bzero ((char *) &readDirArgs, sizeof (readdirargs));
  1147.     bcopy ((char *) pDirHandle, (char *) &readDirArgs.dir, sizeof (nfs_fh));
  1148.     bcopy ((char *) &pDir->dd_cookie, readDirArgs.cookie, sizeof (nfscookie));
  1149.     /*
  1150.     readDirArgs.count = sizeof (struct readdirres) + sizeof (struct entry) +
  1151. NAME_MAX;
  1152.     */
  1153.     /*
  1154.      For reasons yet unknown to me, the HP server expects the value of
  1155.      count to be AT LEAST 512 in order to successfully read directory files
  1156.      mounted from HP. Sun server does not have this limitation.
  1157.     */
  1158.     readDirArgs.count = READDIR_MAXLEN;
  1159.     if (nfsClientCall (hostName, NFS_PROGRAM, NFS_VERSION, NFSPROC_READDIR,
  1160. xdr_readdirargs, (char *) &readDirArgs,
  1161. xdr_readdirres, (char *) &readRes) == ERROR)
  1162. {
  1163. return (ERROR);
  1164. }
  1165.     if (readRes.status != NFS_OK)
  1166. {
  1167. nfsErrnoSet (readRes.status);
  1168. return (ERROR);
  1169. }
  1170.     if (readRes.readdirres_u.reply.entries == NULL && 
  1171. readRes.readdirres_u.reply.eof)
  1172.         {
  1173. /* No entries were returned - must be end of file.
  1174.  * (Note that xdr_readdirresOne hack discarded EOF flag.)
  1175.          * Return ERROR, but don't alter errno because there is no real error.
  1176.  * (Thank you POSIX for this lovely, clear construct.)
  1177.  */
  1178. /*
  1179.  * Need to set errno to OK, otherwise ls will print out an error
  1180.  * message at the end of every directory listing.
  1181.  */
  1182. errnoSet (OK);
  1183. return (ERROR);
  1184. }
  1185.     strcpy (pDir->dd_dirent.d_name,
  1186.     readRes.readdirres_u.reply.entries[0].name);
  1187.     
  1188.     /* update caller's cookie */
  1189.     bcopy (readRes.readdirres_u.reply.entries[0].cookie,
  1190.    (char *) &pDir->dd_cookie, sizeof (nfscookie));
  1191.     /* free the memory used by RPC */
  1192.     clnt_freeres (taskRpcStatics->nfsClientCache->client, xdr_readdirres,
  1193.   (caddr_t) &readRes);
  1194.     return (OK);
  1195.     }
  1196. /*******************************************************************************
  1197. *
  1198. * nfsFileAttrGet - get file attributes and put them in a stat structure
  1199. *
  1200. * NOMANUAL
  1201. */
  1202. void nfsFileAttrGet
  1203.     (
  1204.     FAST fattr *        pFattr, /* ptr to nfs file attributes */
  1205.     FAST struct stat *  pStat   /* ptr to stat struct, return attrs here */
  1206.     )
  1207.     {
  1208.     /*
  1209.      * INTERNAL:  block information is kept in the fattr
  1210.      * structure, but we decided not to hold it in the
  1211.      * stat structure.  It could be added later.
  1212.      */
  1213.     pStat->st_ino         = (ULONG) pFattr->fileid;
  1214.     pStat->st_mode        = pFattr->mode;
  1215.     pStat->st_nlink       = pFattr->nlink;
  1216.     pStat->st_uid         = pFattr->uid;
  1217.     pStat->st_gid         = pFattr->gid;
  1218.     pStat->st_rdev        = 0;                          /* unused */
  1219.     pStat->st_size        = pFattr->size;
  1220.     pStat->st_atime       = pFattr->atime.seconds;
  1221.     pStat->st_mtime       = pFattr->mtime.seconds;
  1222.     pStat->st_ctime       = pFattr->ctime.seconds;
  1223.     pStat->st_blksize     = 0;
  1224.     pStat->st_blocks      = 0;
  1225.     }
  1226. /******************************************************************************
  1227. *
  1228. * nfsFsAttrGet - get file system attributes across NFS
  1229. *
  1230. * This routine does an FSTATFS across NFS.
  1231. *
  1232. * NOMANUAL
  1233. */
  1234. STATUS nfsFsAttrGet
  1235.     (
  1236.     char* pHostName,                         /* host name */
  1237.     nfs_fh* pDirHandle,                      /* file handle of directory */
  1238.     struct statfs* pArg                      /* return value here */
  1239.     )
  1240.     {
  1241.     int status;
  1242.     statfsres retStat;
  1243.     status = nfsClientCall (pHostName,
  1244.                             NFS_PROGRAM, NFS_VERSION, NFSPROC_STATFS,
  1245.                             xdr_fhandle, (char *)pDirHandle,
  1246.                             xdr_statfsres, (char *)&retStat);
  1247.     
  1248.     if (retStat.status != NFS_OK)
  1249.         {
  1250.         nfsErrnoSet (retStat.status);
  1251.         return (ERROR);
  1252.         }
  1253.     pArg->f_type = 0;
  1254.     pArg->f_bsize = retStat.statfsres_u.reply.bsize;
  1255.     pArg->f_blocks = retStat.statfsres_u.reply.blocks;
  1256.     pArg->f_bfree = retStat.statfsres_u.reply.bfree;
  1257.     pArg->f_bavail = retStat.statfsres_u.reply.bavail;
  1258.     
  1259.     /* The following are undefined for NFS under vxWorks and
  1260.      * so are set to 0.
  1261.      */
  1262.     pArg->f_files = 0;    /* total file nodes in file system */
  1263.     pArg->f_ffree = 0;    /* free file nodes in fs */
  1264.     clnt_freeres (taskRpcStatics->nfsClientCache->client, xdr_statfsres,
  1265.                   (caddr_t)&retStat);
  1266.     return (OK);
  1267.     }
  1268. /*******************************************************************************
  1269. *
  1270. * nfsDeleteHook - cleanup NFS data structures
  1271. */
  1272. LOCAL void nfsDeleteHook
  1273.     (
  1274.     WIND_TCB *pTcb
  1275.     )
  1276.     {
  1277. #ifdef  _WRS_VXWORKS_5_X
  1278.     FAST RPC_STATICS *pRPCModList = pTcb->pRPCModList;
  1279. #else
  1280.     FAST RPC_STATICS *pRPCModList = pTcb->pLcb->pRPCModList;
  1281. #endif /*  _WRS_VXWORKS_5_X */
  1282.     
  1283.     if (pRPCModList != NULL)
  1284. {
  1285. nfsClientCacheCleanUp (pRPCModList->nfsClientCache);
  1286. if (pRPCModList->nfsClientCache != NULL)
  1287.     {
  1288.     KHEAP_FREE((char *) pRPCModList->nfsClientCache);
  1289.     pRPCModList->nfsClientCache = NULL;
  1290.     }
  1291. }
  1292.     }
  1293. /*******************************************************************************
  1294. *
  1295. * nfsInit - initialize NFS
  1296. *
  1297. * nfsInit must be called by a task before it uses NFS.
  1298. * It is okay to call this routine more than once.
  1299. *
  1300. * RETURNS: OK or ERROR
  1301. *
  1302. * NOMANUAL
  1303. */
  1304. LOCAL STATUS nfsInit (void)
  1305.     {
  1306.     /* make sure rpc is initialized for this task */
  1307.     if (rpcTaskInit () == ERROR)
  1308. return (ERROR);
  1309.     /* if first nfs use by this task, initialize nfs stuff for this task */
  1310.     if (taskRpcStatics->nfsClientCache == NULL)
  1311. {
  1312. /* if this the very first use of NFS in the system, add nfsDeleteHook */
  1313. if (!nfsInstalled)
  1314.     {
  1315.     if (taskDeleteHookAdd ((FUNCPTR)nfsDeleteHook) == ERROR)
  1316. return (ERROR);
  1317.     nfsInstalled = TRUE;
  1318.     }
  1319. /* allocate nfs specific stuff for this task */
  1320. taskRpcStatics->nfsClientCache =
  1321.     (NFS_MODULE_STATICS *) KHEAP_ALLOC(sizeof (NFS_MODULE_STATICS));
  1322. if (taskRpcStatics->nfsClientCache == NULL)
  1323.     return (ERROR);
  1324.         bzero ((char *)taskRpcStatics->nfsClientCache,
  1325.             sizeof (NFS_MODULE_STATICS));
  1326. }
  1327.     return (OK);
  1328.     }
  1329. /*******************************************************************************
  1330. *
  1331. * nfsClientCacheCleanUp - clean up the NFS client cache
  1332. *
  1333. * This routine is used to free up structures that are part of a valid
  1334. * NFS client cache.  The client cache is marked as invalid.
  1335. */
  1336. LOCAL void nfsClientCacheCleanUp
  1337.     (
  1338.     FAST NFS_MODULE_STATICS *pClientCache       /* pointer to client cache */
  1339.     )
  1340.     {
  1341.     if ((pClientCache != NULL) && (pClientCache->valid))
  1342. {
  1343. pClientCache->valid = FALSE;
  1344. /* close client socket */
  1345. if (pClientCache->socket > 0)
  1346.     {
  1347. #if 0
  1348.     close (pClientCache->socket);
  1349. #endif
  1350.     pClientCache->socket = NONE;
  1351.     }
  1352. pClientCache->oldhost[0] = EOS;
  1353. /* destroy authorization and client */
  1354. if (pClientCache->client != NULL)
  1355.     {
  1356.     if (pClientCache->client->cl_auth != NULL)
  1357. {
  1358. auth_destroy (pClientCache->client->cl_auth);
  1359. pClientCache->client->cl_auth = NULL;
  1360. }
  1361.     clnt_destroy (pClientCache->client);
  1362.     pClientCache->client = NULL;
  1363.     }
  1364. }
  1365.     }
  1366. /*******************************************************************************
  1367. *
  1368. * nfsClientCacheSetUp - set up the NFS client cache
  1369. *
  1370. * This routine is used to set up structures that are part of a valid
  1371. * NFS client cache.  If successful, the client cache is marked as valid.
  1372. */
  1373. LOCAL STATUS nfsClientCacheSetUp
  1374.     (
  1375.     FAST NFS_MODULE_STATICS *ms,        /* pointer to client cache */
  1376.     char *      host,                   /* server's host name */
  1377.     u_int       prognum,                /* RPC program number */
  1378.     u_int       versnum                 /* RPC version number */
  1379.     )
  1380.     {
  1381.     int hp; /* host's inet address */
  1382.     struct sockaddr_in server_addr;
  1383.     struct timeval timeout;
  1384.     int optval;
  1385.     /* check if cached client is appropriate */
  1386.     if (ms->valid && ms->oldprognum == prognum && ms->oldversnum == versnum
  1387. && strcmp (ms->oldhost, host) == 0 && ms->authCount == nfsAuthCount)
  1388. {
  1389. return (OK); /* reuse old client */
  1390.      }
  1391.     /* get rid of any old client and create new one */
  1392.     nfsClientCacheCleanUp (ms);
  1393.     if ((hp = hostGetByName (host)) == ERROR)
  1394. return (ERROR);
  1395.     timeout.tv_sec  = nfsReXmitSec;
  1396.     timeout.tv_usec = nfsReXmitUSec;
  1397.     server_addr.sin_addr.s_addr = hp;
  1398.     server_addr.sin_family = AF_INET;
  1399.     server_addr.sin_port = htons (0);
  1400.     ms->socket = RPC_ANYSOCK;
  1401.     if ((ms->client = clntudp_create(&server_addr, prognum, versnum,
  1402.      timeout, &ms->socket)) == NULL)
  1403. {
  1404. server_addr.sin_port = htons (NFS_PORT);
  1405. ms->client = clntudp_create (&server_addr, prognum, versnum,
  1406.      timeout, &ms->socket);
  1407. if (ms->client == NULL)
  1408.     return (ERROR);
  1409. }
  1410.     optval = nfsSockBufSize;
  1411.     if ((setsockopt (ms->socket, SOL_SOCKET, SO_SNDBUF, (char *)&optval,
  1412.      sizeof (optval)) == ERROR)
  1413. || (setsockopt (ms->socket, SOL_SOCKET, SO_RCVBUF, (char *)&optval,
  1414. sizeof (optval)) == ERROR))
  1415. {
  1416. nfsClientCacheCleanUp (ms);
  1417. return (ERROR);
  1418. }
  1419.     ms->client->cl_auth = authunix_create (nfsAuthUnix.machname,
  1420.    nfsAuthUnix.uid, nfsAuthUnix.gid,
  1421.    nfsAuthUnix.len,
  1422.    nfsAuthUnix.aup_gids);
  1423.     if (ms->client->cl_auth == NULL)
  1424. {
  1425. nfsClientCacheCleanUp (ms);
  1426. errnoSet (S_nfsLib_NFS_AUTH_UNIX_FAILED);
  1427. return (ERROR);
  1428. }
  1429.     ms->oldprognum = prognum;
  1430.     ms->oldversnum = versnum;
  1431.     ms->authCount  = nfsAuthCount;
  1432.     (void) strcpy (ms->oldhost, host);
  1433.     ms->valid = TRUE;
  1434.     return (OK);
  1435.     }
  1436. /*******************************************************************************
  1437. *
  1438. * nfsClientCall - make an NFS request to the server using RPC
  1439. *
  1440. * This is the routine which does the actual RPC call to the server.
  1441. * All NFS routines which communicate with the file server use this routine.
  1442. *
  1443. * RETURNS:  OK | ERROR
  1444. */
  1445. LOCAL STATUS nfsClientCall
  1446.     (
  1447.     char *      host,           /* server's host name */
  1448.     u_int       prognum,        /* RPC program number */
  1449.     u_int       versnum,        /* RPC version number */
  1450.     u_int       procnum,        /* RPC procedure number */
  1451.     xdrproc_t   inproc,         /* xdr routine for args */
  1452.     char *      in,
  1453.     xdrproc_t   outproc,        /* xdr routine for results */
  1454.     char *      out
  1455.     )
  1456.     {
  1457.     nfstime tottimeout;
  1458.     enum clnt_stat clientStat;
  1459.     FAST NFS_MODULE_STATICS *ms;
  1460.     if (nfsInit () != OK)
  1461. return (ERROR);
  1462.  
  1463.     ms = taskRpcStatics->nfsClientCache;
  1464.     /* get an appropriate client in the cache */
  1465.     if (nfsClientCacheSetUp (ms, host, prognum, versnum) != OK)
  1466. return (ERROR);
  1467.     /* set time to allow results to come back */
  1468.     tottimeout.seconds  = nfsTimeoutSec;
  1469.     tottimeout.useconds = nfsTimeoutUSec;
  1470.     clientStat = clnt_call (ms->client, procnum, inproc, in, outproc, out,
  1471.     tottimeout);
  1472.     if (clientStat != RPC_SUCCESS)
  1473. {
  1474. /* XXX this should be more gracefull */
  1475. nfsClientCacheCleanUp (ms);
  1476. rpcClntErrnoSet (clientStat);
  1477. return (ERROR);
  1478. }
  1479.     return (OK);
  1480.     }
  1481. /*******************************************************************************
  1482. *
  1483. * nfsClientClose - close the NFS client socket and associated structures
  1484. *
  1485. * NOMANUAL
  1486. */
  1487. void nfsClientClose (void)
  1488.     {
  1489.     if (taskRpcStatics != NULL)
  1490. nfsClientCacheCleanUp (taskRpcStatics->nfsClientCache);
  1491.     }
  1492. /*******************************************************************************
  1493. *
  1494. * nfsMountListPrint - prints a list of mount entries
  1495. */
  1496. LOCAL void nfsMountListPrint
  1497.     (
  1498.     FAST mountlist pMountList
  1499.     )
  1500.     {
  1501.     while (pMountList)
  1502. {
  1503. printf ("%s:%sn", pMountList->ml_hostname, pMountList->ml_directory);
  1504. pMountList = pMountList->ml_next;
  1505. }
  1506.     }
  1507. /*******************************************************************************
  1508. *
  1509. * nfsGroupsPrint - print a list of groups
  1510. */
  1511. LOCAL void nfsGroupsPrint
  1512.     (
  1513.     FAST groups pGroup
  1514.     )
  1515.     {
  1516.     while (pGroup != NULL)
  1517. {
  1518. printf ("%s ", pGroup->gr_name);
  1519. pGroup = pGroup->gr_next;
  1520. }
  1521.     }
  1522. /*******************************************************************************
  1523. *
  1524. * nfsExportPrint - prints a list of exported file systems on a host
  1525. */
  1526. LOCAL void nfsExportPrint
  1527.     (
  1528.     FAST exports pExport
  1529.     )
  1530.     {
  1531.     while (pExport != NULL)
  1532. {
  1533. printf ("%-25s ", pExport->ex_dir);
  1534. nfsGroupsPrint (pExport->ex_groups);
  1535. printf ("n");
  1536. pExport = pExport->ex_next;
  1537. }
  1538.     }
  1539. /*******************************************************************************
  1540. *
  1541. * nfsErrnoSet - set NFS status
  1542. *
  1543. * nfsErrnoSet calls errnoSet with the given "nfs stat" or'd with the
  1544. * NFS status prefix.
  1545. */
  1546. LOCAL void nfsErrnoSet
  1547.     (
  1548.     enum nfsstat status
  1549.     )
  1550.     {
  1551.     errnoSet (M_nfsStat | (int) status);
  1552.     }
  1553. /*******************************************************************************
  1554. *
  1555. * nfsAuthUnixPrompt - modify the NFS UNIX authentication parameters
  1556. *
  1557. * This routine allows
  1558. * UNIX authentication parameters to be changed from the shell.
  1559. * The user is prompted for each parameter, which can be changed
  1560. * by entering the new value next to the current one.
  1561. *
  1562. * EXAMPLE
  1563. * .CS
  1564. *    -> nfsAuthUnixPrompt
  1565. *    machine name:   yuba
  1566. *    user ID:        2001 128
  1567. *    group ID:       100
  1568. *    num of groups:  1 3
  1569. *    group #1:        100 100
  1570. *    group #2:        0 120
  1571. *    group #3:        0 200
  1572. *    value = 3 = 0x3
  1573. * .CE
  1574. *
  1575. * SEE ALSO: nfsAuthUnixShow(), nfsAuthUnixSet(), nfsAuthUnixGet(), nfsIdSet()
  1576. */
  1577. void nfsAuthUnixPrompt (void)
  1578.     {
  1579.     char machname [AUTH_UNIX_FIELD_LEN];/* host name where client is */
  1580.     int uid; /* client's UNIX effective uid */
  1581.     int gid; /* client's current group ID */
  1582.     int len; /* element length of aup_gids */
  1583.     int aup_gids [MAX_GRPS]; /* array of groups user is in */
  1584.     int ix;
  1585.     nfsAuthUnixGet (machname, &uid, &gid, &len, aup_gids);
  1586.     promptParamString ("machine name:  ", machname, sizeof (machname));
  1587.     promptParamNum ("user ID:       ", &uid, 8, "%d ");
  1588.     promptParamNum ("group ID:      ", &gid, 8, "%d ");
  1589.     promptParamNum ("num of groups: ", &len, 8, "%d ");
  1590.     for (ix = 0; ix < len; ix++)
  1591. {
  1592. printf ("group #%d:       ", ix + 1);
  1593. promptParamNum ("", &aup_gids [ix], 8, "%d ");
  1594. }
  1595.     nfsAuthUnixSet (machname, uid, gid, len, aup_gids);
  1596.     }
  1597. /*******************************************************************************
  1598. *
  1599. * nfsAuthUnixShow - display the NFS UNIX authentication parameters
  1600. *
  1601. * This routine displays the parameters set by nfsAuthUnixSet() or
  1602. * nfsAuthUnixPrompt().
  1603. *
  1604. * EXAMPLE:
  1605. * .CS
  1606. *    -> nfsAuthUnixShow
  1607. *    machine name = yuba
  1608. *    user ID      = 2001
  1609. *    group ID     = 100
  1610. *    group [0]    = 100
  1611. *    value = 1 = 0x1
  1612. * .CE
  1613. *
  1614. * RETURNS: N/A
  1615. *
  1616. * SEE ALSO: nfsAuthUnixPrompt(), nfsAuthUnixSet(), nfsAuthUnixGet(), nfsIdSet()
  1617. */
  1618. void nfsAuthUnixShow (void)
  1619.     {
  1620.     char machname [AUTH_UNIX_FIELD_LEN]; /* host name where client is */
  1621.     int uid; /* client's UNIX effective uid */
  1622.     int gid; /* client's current group ID */
  1623.     int len; /* element length of aup_gids */
  1624.     int aup_gids [MAX_GRPS]; /* array of groups user is in */
  1625.     int ix;
  1626.     nfsAuthUnixGet (machname, &uid, &gid, &len, aup_gids);
  1627.     printf ("machine name = %sn", machname);
  1628.     printf ("user ID      = %dn", uid);
  1629.     printf ("group ID     = %dn", gid);
  1630.     for (ix = 0; ix < len; ix++)
  1631. printf ("group [%d]    = %dn", ix, aup_gids [ix]);
  1632.     }
  1633. /*******************************************************************************
  1634. *
  1635. * nfsAuthUnixSet - set the NFS UNIX authentication parameters
  1636. *
  1637. * This routine sets UNIX authentication parameters.
  1638. * It is initially called by usrNetInit().
  1639. * `machname' should be set with the name of the mounted system (i.e. the target
  1640. * name itself) to distinguish hosts from hosts on a NFS network.
  1641. *
  1642. * RETURNS: N/A
  1643. *
  1644. * SEE ALSO: nfsAuthUnixPrompt(), nfsAuthUnixShow(), nfsAuthUnixGet(), 
  1645. * nfsIdSet()
  1646. *
  1647. */
  1648. void nfsAuthUnixSet
  1649.     (
  1650.     char *machname,     /* host machine        */
  1651.     int uid,            /* user ID             */
  1652.     int gid,            /* group ID            */
  1653.     int ngids,          /* number of group IDs */
  1654.     int *aup_gids       /* array of group IDs  */
  1655.     )
  1656.     {
  1657.     int ix;
  1658.     taskLock ();
  1659.     (void) strcpy (nfsAuthUnix.machname, machname);
  1660.     nfsAuthUnix.uid = uid;
  1661.     nfsAuthUnix.gid = gid;
  1662.     nfsAuthUnix.len = (ngids < MAX_GRPS ? ngids : MAX_GRPS);
  1663.     for (ix = 0; ix < ngids; ix++)
  1664. nfsAuthUnix.aup_gids [ix] = aup_gids [ix];
  1665.     /* Cached client authentications are out of date now.
  1666.      * Bump auth count so clients will be rebuilt with new auth,
  1667.      * next time the client transport is used.
  1668.      */
  1669.     nfsAuthCount++;
  1670.     taskUnlock ();
  1671.     }
  1672. /*******************************************************************************
  1673. *
  1674. * nfsAuthUnixGet - get the NFS UNIX authentication parameters
  1675. *
  1676. * This routine gets the previously set UNIX authentication values.
  1677. *
  1678. * RETURNS: N/A
  1679. *
  1680. * SEE ALSO: nfsAuthUnixPrompt(), nfsAuthUnixShow(), nfsAuthUnixSet(), 
  1681. * nfsIdSet()
  1682. */
  1683. void nfsAuthUnixGet
  1684.     (
  1685.     char *machname,     /* where to store host machine        */
  1686.     int *pUid,          /* where to store user ID             */
  1687.     int *pGid,          /* where to store group ID            */
  1688.     int *pNgids,        /* where to store number of group IDs */
  1689.     int *gids           /* where to store array of group IDs  */
  1690.     )
  1691.     {
  1692.     int ix;
  1693.     (void) strcpy (machname, nfsAuthUnix.machname);
  1694.     *pUid   = nfsAuthUnix.uid;
  1695.     *pGid   = nfsAuthUnix.gid;
  1696.     *pNgids = nfsAuthUnix.len;
  1697.     for (ix = 0; ix < nfsAuthUnix.len; ix++)
  1698. gids [ix] = nfsAuthUnix.aup_gids [ix];
  1699.     }
  1700. /*******************************************************************************
  1701. *
  1702. * nfsIdSet - set the ID number of the NFS UNIX authentication parameters
  1703. *
  1704. * This routine sets only the UNIX authentication user ID number.
  1705. * For most NFS permission needs, only the user ID needs to be changed.
  1706. * Set <uid> to the user ID on the NFS server.
  1707. *
  1708. * RETURNS: N/A
  1709. *
  1710. * SEE ALSO: nfsAuthUnixPrompt(), nfsAuthUnixShow(), nfsAuthUnixSet(),
  1711. * nfsAuthUnixGet()
  1712. */
  1713. void nfsIdSet
  1714.     (
  1715.     int uid             /* user ID on host machine */
  1716.     )
  1717.     {
  1718.     taskLock ();
  1719.     nfsAuthUnix.uid = uid;
  1720.     /* Cached client authentications are out of date now.
  1721.      * Bump auth count so clients will be rebuilt with new auth,
  1722.      * next time the client transport is used.
  1723.      */
  1724.     nfsAuthCount++;
  1725.     taskUnlock ();
  1726.     }
  1727. /*******************************************************************************
  1728. *
  1729. * printClear - print string with '?' for unprintable characters
  1730. */
  1731. LOCAL void printClear
  1732.     (
  1733.     FAST char *param
  1734.     )
  1735.     {
  1736.     FAST char ch;
  1737.     while ((ch = *(param++)) != EOS)
  1738. printf ("%c", (isascii ((UINT)ch) && isprint ((UINT)ch)) ? ch : '?');
  1739.     }
  1740. /*******************************************************************************
  1741. *
  1742. * promptParamString - prompt the user for a string parameter
  1743. *
  1744. * - carriage return leaves the parameter unmodified;
  1745. * - "." clears the parameter (null string).
  1746. */
  1747. LOCAL void promptParamString
  1748.     (
  1749.     char *msg,
  1750.     char *param,
  1751.     int fieldWidth
  1752.     )
  1753.     {
  1754.     int ix;
  1755.     char buf [100];
  1756.     FOREVER
  1757. {
  1758. printf ("%s ", msg);
  1759. printClear (param);
  1760. printf (" ");
  1761. ix = fioRdString (STD_IN, buf, sizeof (buf));
  1762. if (ix < fieldWidth)
  1763.     break;
  1764. printf ("too big - maximum field width = %d.n", fieldWidth);
  1765. }
  1766.     if (ix == 1)
  1767. return; /* just CR; leave field unchanged */
  1768.     if (buf[0] == '.')
  1769. {
  1770. param [0] = EOS; /* just '.'; make empty field */
  1771. return;
  1772. }
  1773.     (void) strcpy (param, buf); /* update parameter */
  1774.     }
  1775. /*******************************************************************************
  1776. *
  1777. * promptParamNum - prompt the user for a parameter
  1778. *
  1779. * - carriage return leaves the parameter unmodified;
  1780. * - "." clears the parameter (0).
  1781. */
  1782. LOCAL void promptParamNum
  1783.     (
  1784.     char *msg,
  1785.     int *pParam,
  1786.     int fieldWidth,
  1787.     char *format
  1788.     )
  1789.     {
  1790.     int ix;
  1791.     char buf [100];
  1792.     FOREVER
  1793. {
  1794. (void) strcpy (buf, "%s ");
  1795. (void) strcat (buf, format);
  1796. printf (buf, msg, *pParam);
  1797. ix = fioRdString (STD_IN, buf, sizeof (buf));
  1798. if (ix < fieldWidth)
  1799.     break;
  1800. printf ("too big - maximum field width = %d.n", fieldWidth);
  1801. }
  1802.     if (ix == 1)
  1803. return; /* just CR; leave field unchanged */
  1804.     if (buf[0] == '.')
  1805. {
  1806. pParam = 0; /* just '.'; make empty field */
  1807. return;
  1808. }
  1809.     (void) sscanf (buf, format, pParam); /* scan field */
  1810.     }