home *** CD-ROM | disk | FTP | other *** search
/ IBM Presents OS/2 Software Hits 1995 / OS-2_SW_HITS_2ND_EDITION_1995.ISO / i17 / lwp42n.exe / BWNFSD.C < prev    next >
C/C++ Source or Header  |  1994-10-05  |  67KB  |  2,704 lines

  1. #define VERSION  "3.1c"
  2. /*
  3.     BWNFSD is an RPC daemon used in conjunction with BWNFS (a client NFS
  4. for DOS based PCs. BWNFSD provides Authentication, Print Spooling,
  5. DOS 3.1 Locking, DOS 3.1 Sharing, GID name mapping, UID name mapping services
  6. for BWNFS and associated applications on the PC. BWNFSD is being used also
  7. by Macintosh NFS clients.
  8.  
  9.     The BWNFSD code is originally copyright Beame & Whiteside Software Ltd.
  10. and now is released to the Public Domain. The intent is that all server vendors
  11. included a version of BWNFSD with their operating system. BWNFSD can run
  12. simultanteously with PCNFSD, but provides more features.
  13.  
  14.     Please send modifications to:
  15.  
  16.         Beame & Whiteside Software, Inc.
  17.         706 Hillsborough St.
  18.         Raleigh, North Carolina
  19.         USA 27603-1655
  20.         +1 (919) 831-8989
  21.         support@bws.com
  22.  
  23.     Please modify by including "ifdefs" for your particular operating
  24. system, with appropriate modifications to the "makefile".
  25.  
  26. MODIFICATION HISTORY
  27. --------------------
  28. 11/11/91 gsw  Added some debug statements
  29. 24/03/92 gsw  Changed SHADOW to SHADW since it conflicted on some SYS-V's
  30. 31/07/92 fjw  Changed printers code to check for abnormal conditions
  31. 31/07/92 fjw  Cleaned up the code and repaired the printer parsing
  32. 01/08/92 fjw  Merged in SVR4 code from Frank Glass (gatech!holos0!fsg)
  33. 31/08/92 cfb  Major changes to support pcnfsdv2-style queues, etc.
  34. 31/08/92 fjw  Changed all the ifdefs around for cleaner code
  35. 31/08/92 fjw  Added user cacheing in authorize code
  36. 08/10/92 fjw  Fixed code relating to printing and debugmode
  37. 05/11/92 fjw  Added some pretty print in debug mode
  38. 14/05/93 fjw  Changed the daemon-detach code to be more like Stevens book
  39. 14/05/93 fjw  Consolidated #defines and added support for Univel and Solaris
  40. 09/02/94 fjw  Changed most of the manifest constant names to assist customisation
  41. 09/02/94 fjw  Added code to allow locks/file/process to be removed
  42. 08/05/94 fjw  Fixed set_auth_parameters() *again* (code got lost somehow)
  43. 08/23/94 cpz  Fixed possible undefined SIGCLD; added conditional for netinet
  44. 08/23/94 cpz  Fix debug write in get_gr_gid; Carl Zwanzig
  45.  
  46. */
  47.  
  48. /*
  49.  *  Uncomment the #define line below only if your system uses a Shadow Password
  50.  *  Database and you have received an "Authorization Error" message after
  51.  *  attempting to Link using a valid username & password combination!
  52.  */
  53.  
  54. #ifndef SHADW
  55. /* #define SHADW */
  56. #endif
  57.  
  58. #define MAX_NUM_PRINTERS 500
  59. #define POLL_INTERVAL 60
  60. #define MAX_NUM_CANCEL_CACHE 10
  61. #define NUM_USER_CACHE 3
  62.  
  63. #include <stdio.h>
  64. #include <sys/types.h>
  65. #include <fcntl.h>
  66. #ifdef FIND_QUEUES_AIX
  67. #include <sys/select.h>
  68. #endif
  69. #include <sys/stat.h>
  70. #include <rpc/rpc.h>
  71. #ifndef INCLUDE_BOGOSITY
  72. #include <rpc/clnt.h>    /* added for svr4 , usually included by <rpc/rpc.h> */
  73. #include <rpc/svc.h>
  74. #endif
  75. #include <errno.h>
  76. #include <sys/socket.h>
  77. #include <sys/param.h>
  78. #include <sys/time.h>
  79. #include <sys/ioctl.h>
  80. #include <ctype.h>
  81. #include <arpa/inet.h>
  82. #include <netdb.h>
  83. #include <pwd.h>
  84. #include <signal.h>
  85. #include <grp.h>
  86. #include <string.h>
  87.  
  88. #ifndef DONT_USE_NETINET_IN
  89. #include <netinet/in.h>   /* This is problematic on some systems, required on others */
  90. #endif
  91.  
  92. #ifdef USE_BCOPY
  93. #define memcmp(a,b,c) bcmp((b),(a),(c))
  94. #define memcpy(a,b,c) bcopy((b),(a),(c))
  95. #else
  96. #include <memory.h>
  97. #endif
  98.  
  99. #ifdef SHADW
  100. #include <shadow.h>
  101. #endif
  102.  
  103. #ifdef SGI
  104. extern struct group *getgrent();
  105. #endif
  106.  
  107. char *crypt();
  108. char *my_strdup();
  109. void free_printer();
  110. void get_printers();
  111.  
  112. #ifdef INT_SIG
  113. #define Void int
  114. #define Return return(0)
  115. #else
  116. #define Void void
  117. #define Return return
  118. #endif
  119.  
  120. #ifdef WINNFS
  121. #include <tiuser.h>
  122. #endif
  123.  
  124. #ifdef FIND_QUEUES_SVR4
  125. #define ALLOW 0
  126. #define DENY  1
  127. #define CLASS 2
  128.  
  129. struct {
  130.     int access;
  131.     int count;
  132.     union {
  133.         char **users;
  134.         int  *printers;
  135.     } n;
  136. } printer_access[MAX_NUM_PRINTERS];
  137. #endif
  138.  
  139. #define BW_NFS_PROGRAM 0x2f00dbadL
  140. #define BW_NFS_VERSION 1L
  141.  
  142. #define SPOOL_INQUIRE  1L    /* Return fhandle of spool directory */
  143. #define SPOOL_FILE     2L    /* Spool file */
  144. #define AUTHORIZE      3L    /* Authorize and return UID and GIDs (max 16) */
  145. #define GRP_NAME_TO_NUMB 4L    /* Convert group name to number */
  146. #define GRP_TO_NUMBER  5L    /* Convert group number(s) to name(s) */
  147. #define RETURN_HOST    6L    /* Convert IP to hostname */
  148. #define UID_TO_NAME    7L    /* Convert UID(s) to name(s) */
  149. #define NAME_TO_UID    8L    /* Convert name(s) to UID(s)  L. Yen */
  150. #define SHARE          20L    /* DOS 3.1 Share function */
  151. #define UNSHARE       21L    /* DOS 3.1 UnShare function */
  152. #define LOCK          22L    /* DOS 3.1 Lock request */
  153. #define REMOVE          23L    /* Remove all locks/shares for PC */
  154. #define UNLOCK          24L    /* DOS 3.1 Unlock request */
  155. #define GET_PRINTERS  30L    /* Get a list of printers */
  156. #define GET_PRINTQ    31L    /* Get print queue entries and status */
  157. #define CANCEL_PRJOB  32L    /* Cancel a print job */
  158. #define ZAP_LOCKS    105L    /* Remove locks on file by process */
  159.  
  160. #define NUSRS  10        /* Maximum names to convert */
  161.  
  162. #define WNPRQ_ACTIVE    0
  163. #define WNPRQ_PAUSE    1
  164. #define WNPRQ_ERROR    2
  165. #define WNPRQ_PENDING    3
  166. #define WNPRQ_PROBLEM    4
  167. #define WN_SUCCESS    0
  168. #define WN_BAD_QUEUE    0x43
  169.  
  170. static    char    dir[32],g_string[32];
  171. static    char    spool_dir[132], file[256], file1[256];
  172. static    char    remote_host[16];
  173. static    int    num_printers;
  174. static    char    printer[12];
  175. static    char    *jobname;
  176. static    char    file_name[9];
  177. static    char    *hostname,*p;
  178. static    int    extension, lgids[NGRPS+1];
  179. static    int    luids[NUSRS+1];
  180. static    int    A_flag=0, s_flag=0, do_print;
  181. int debugmode;
  182. static    unsigned long my_ip;
  183. static    unsigned long incomming_ip;
  184.  
  185. struct queueentry {
  186.     int jobid;
  187.     char *username;
  188.     char *params;
  189.     int queueposition;
  190.     int jobstatus;
  191.     unsigned long timesubmitted;
  192.     unsigned long size;
  193.     int copies;
  194.     char *jobcomment;
  195.     struct queueentry *next;
  196. };
  197.  
  198. struct printertype {
  199.     char *queuename;
  200.     char *queuecomment;
  201.     int queuestatus;
  202.     int numphysicalprinters;
  203.     unsigned long lasttime;
  204.     struct queueentry *head;
  205. } printers[MAX_NUM_PRINTERS];
  206.  
  207. static struct mm_ips {        /* Valid hosts to authenticate for */
  208.     char          type;
  209.     unsigned long ip;
  210.     unsigned long mask;
  211.     unsigned long redirect_ip;
  212. } **ips;
  213.  
  214. static struct mm_uids {     /* Cache of uid to name translation */
  215.     int    mm_uid;
  216.     char    *mm_username;
  217. } **uds;
  218.  
  219. static struct mm_gidss {    /* Cache of uid and associated gids */
  220.     int mm_uid;
  221.     int mm_gid;
  222.     int mm_gid_count;
  223.     int mm_gids[NGRPS];
  224. } **gds;
  225.  
  226. static int gids_count=0, uids_count=0;
  227. static int ips_count=0;
  228.  
  229. static struct locking {
  230.     unsigned long    lockowner;    /* 4 bytes */
  231.     unsigned long    cookie;     /* 4 bytes */
  232.     char        name[17];    /* 16 character name */
  233.     char        fh[32];     /* 32 bytes */
  234.     int        mode;
  235.     int        access;
  236.     unsigned long    offset;
  237.     unsigned long    length;
  238.     int        stat;
  239.     int        sequence;
  240. } lock = { 0 };
  241.  
  242. static struct printqs {
  243.     char queuename[32];
  244.     char username[32];
  245.     int printer_number;
  246. } printq;
  247.  
  248. static struct cancaches {
  249.     char queuename[32];
  250.     char username[32];
  251.     int jobid;
  252.     int response;
  253. } cancache[MAX_NUM_CANCEL_CACHE] = { 0 };
  254.  
  255. int current_cache=0;
  256.  
  257. int
  258. my_strnicmp(p1, p2, num)
  259.     char *p1, *p2;
  260.     int num;
  261. {
  262. char c, d;
  263.  
  264.     for ( ; num>0; num--) {
  265.         c = *p1++;
  266.         d = *p2++;
  267.         c = islower(c)?toupper(c):c;
  268.         d = islower(d)?toupper(d):d;
  269.         if (c != d)
  270.             return(1);
  271.     }
  272.     return(0);
  273. }
  274.  
  275. #ifdef CHECK_PRINTER_ACCESS
  276. int
  277. check_access_printer(pn,name)
  278.     int pn;
  279.     char *name;
  280. {
  281. int i;
  282. char **p;
  283.  
  284.     if (debugmode)
  285.         fprintf(stdout, "bwnfsd: [check_access_printer] pn = %d, name = %s\n", pn, name);
  286.  
  287.     if (printer_access[pn].count == -1) {
  288.         if (debugmode)
  289.             fprintf(stdout, "bwnfsd: [check_access_printer] deny all requests\n");
  290.         return(0);                     /* Deny all */
  291.     }
  292.     p = printer_access[pn].n.users;
  293.     for (i=0; i<printer_access[pn].count; i++) {
  294.         if (strcmp(*p++,name) == 0) {
  295.             if (debugmode)
  296.                 fprintf(stdout, "bwnfsd: [check_access_printer] request %s\n", printer_access[pn].access==ALLOW?"allowed":"denied");
  297.             return(printer_access[pn].access == ALLOW);
  298.         }
  299.     }
  300.     if (debugmode)
  301.         fprintf(stdout, "bwnfsd: [check_access_printer] request %s\n", printer_access[pn].access==DENY?"allowed":"denied");
  302.     return(printer_access[pn].access == DENY);
  303. }
  304.  
  305. int
  306. check_access(pn, name)
  307.     int pn;
  308.     char *name;
  309. {
  310. int i;
  311. int *pi;
  312.  
  313.     if (debugmode)
  314.         fprintf(stdout, "bwnfsd: [check_access] pn = %d, name = %s\n", pn, name);
  315.  
  316.     if (printer_access[pn].access != CLASS)
  317.         return(check_access_printer(pn,name));
  318.     pi = printer_access[pn].n.printers;
  319.     for (i=0; i<printer_access[pn].count; i++)
  320.         if (check_access_printer(*pi++,name)) {
  321.             if (debugmode)
  322.                 fprintf(stdout, "bwnfsd: [check_access] returns 1\n");
  323.             return(1);
  324.         }
  325.     if (debugmode)
  326.         fprintf(stdout, "bwnfsd: [check_access] returns 0\n");
  327.     return(0);
  328. }
  329. #endif
  330.  
  331. Void
  332. clear(unused)
  333.     int unused;
  334. {
  335. int i;
  336.  
  337.     if (debugmode)
  338.         fprintf(stdout, "bwnfsd: [clear]\n");
  339.     for (i=0; i<uids_count; i++) {
  340.         free((*(uds+i))->mm_username);
  341.         free(*(uds+i));
  342.     }
  343.     if (uids_count > 0) {
  344.         free(uds);
  345.         uids_count = 0;
  346.     }
  347.     endpwent();
  348.     for (i=0; i<gids_count; i++)
  349.         free(*(gds+i));
  350.     if (gids_count > 0) {
  351.         free(gds);
  352.         gids_count = 0;
  353.     }
  354.     endgrent();
  355.     for (i=0; i<num_printers; i++) {
  356.         free_printer(i);
  357.         free(printers[i].queuename);
  358.         if (printers[i].queuecomment != NULL)
  359.             free(printers[i].queuecomment);
  360.     }
  361.     get_printers();
  362.     (void) signal(SIGHUP, clear);
  363.     Return;
  364. }
  365.  
  366. Void
  367. free_child(unused)
  368.     int unused;
  369. {
  370.     if (debugmode)
  371.         fprintf(stdout, "bwnfsd: [free_child] called\n");
  372.  
  373.     (void) wait(NULL);
  374. #ifdef SIGCHLD
  375.     (void) signal(SIGCHLD,free_child);
  376. #endif
  377. #ifdef SIGCLD
  378.     (void) signal(SIGCLD,free_child);
  379. #endif
  380.     Return;
  381. }
  382.  
  383. void
  384. strlwr(p)
  385.     char *p;
  386. {
  387.     do {
  388.         if ((*p >= 'A') && (*p <= 'Z'))
  389.             *p += 'a'-'A';
  390.     } while (*(++p) != '\0');
  391. }
  392.  
  393. void
  394. getmask(ip,mask)
  395.     unsigned long *ip, *mask;
  396. {
  397.     if (*ip == 0L)
  398.         *mask = 0L;
  399.     else if (*ip <= 0xffL) {
  400.         *ip <<= 24;
  401.         *mask = 0xff000000L;
  402.     } else if (*ip <= 0xffffL) {
  403.         *ip <<= 16;
  404.         *mask = 0xffff0000L;
  405.     } else if (*ip <= 0xffffffL) {
  406.         *ip <<= 8;
  407.         *mask = 0xffffff00L;
  408.     } else
  409.         *mask = 0xffffffffL;
  410. }
  411.  
  412. unsigned long
  413. my_inet_addr(cp)
  414.     char *cp;
  415. {
  416. static union {
  417.      unsigned long inn;
  418.      struct {
  419.          unsigned char b1, b2, b3, b4;
  420.      } i;
  421. } in;
  422. int b1, b2, b3, b4;
  423.  
  424.     b1 = b2 = b3 = b4 = -1;
  425.     if (sscanf(cp,"%d.%d.%d.%d", &b1, &b2, &b3, &b4) == -1)
  426.         return(~0L);
  427.     if (b4 == -1) {
  428.         b4 = b3;
  429.         b3 = b2;
  430.         b2 = 0;
  431.     }
  432.     if (b4 == -1) {
  433.         b4 = b3;
  434.         b3 = 0;
  435.     }
  436.     if (((unsigned) b1 > 255) || ((unsigned) b2 > 255)
  437.       ||((unsigned) b3 > 255) || ((unsigned) b4 > 255))
  438.         return(~0L);
  439.     in.i.b1 = (unsigned char) b1;
  440.     in.i.b2 = (unsigned char) b2;
  441.     in.i.b3 = (unsigned char) b3;
  442.     in.i.b4 = (unsigned char) b4;
  443.     return(ntohl(in.inn));
  444. }
  445.  
  446. /*
  447.  *  For -s parameter, returns IP addresses and the associated mask to determine
  448.  *  if the IP address of the destination machine/network is matches an entry
  449.  *  in the -s file.
  450.  */
  451. int
  452. convert_ip(s,ip,mask)
  453.     char *s;
  454.     unsigned long *ip, *mask;
  455. {
  456. unsigned long ia, lip, lmask;
  457. struct hostent *he;
  458. struct netent *ne;
  459.  
  460.     if (debugmode)
  461.         fprintf(stdout, "bwnfsd: [convert_ip] s = %s\n", s);
  462.  
  463.     if ((ia=inet_network(s)) != (~0L)) {
  464.         lip = ia;
  465.         getmask(&lip,&lmask);
  466.     } else {
  467.         if ((ia=my_inet_addr(s)) != (~0L)) {
  468.             lip = ia;
  469.             lmask = 0xffffffffL;
  470.         } else {
  471.             if ((ne=getnetbyname(s)) != NULL) {
  472.                 lip = ne->n_net;
  473.                 getmask(&lip,&lmask);
  474.             } else {
  475.                 if ((he=gethostbyname(s)) != NULL) {
  476.                     lip = * (unsigned long *) he->h_addr;
  477.                     lmask = 0xffffffffL;
  478.                 } else {
  479.                     if (debugmode)
  480.                         fprintf(stdout, "bwnfsd: [convert_ip] returns 0\n");
  481.                     return(0);
  482.                 }
  483.             }
  484.         }
  485.     }
  486.     *ip = lip;
  487.     if (mask != NULL)
  488.         *mask = lmask;
  489.     if (debugmode)
  490.         fprintf(stdout, "bwnfsd: [convert_ip] (1) ip = %lu, mask = %lu\n", ip, mask);
  491.     return(1);
  492. }
  493.  
  494. /*
  495.  *     Read the -s file which lists rules for which hosts can be
  496.  *     authenticated. Each line is converted to a IP address and mask. Any
  497.  *     incoming address is ANDed with the mask and compared to IP address,
  498.  *     if it matches, the action associated with the line is taken.
  499.  *
  500.  *     Valid actions:
  501.  *         "+" - Perform Validatation check
  502.  *         "-" - Return Authorization error
  503.  *         "=" - Tell client to attempt Authorization at new address
  504.  */
  505. void
  506. read_ips(file)
  507.     char *file;
  508. {
  509. FILE *f;
  510. char s1[255], s2[255], line[255], type;
  511. int i;
  512. unsigned long ip, mask, redirect_ip;
  513.  
  514.     if (debugmode)
  515.         fprintf(stdout, "bwnfsd: [read_ips] file = %s\n", file);
  516.  
  517.     if ((f=fopen(file,"r")) == NULL) {
  518.         fprintf(stdout, "bwnfsd: [read_ips] \"%s\" file not found.\n",file);
  519.         fflush(stdout);
  520.         exit(1);
  521.     }
  522.  
  523.     ips = (struct mm_ips **) malloc(1);
  524.     while (fgets(line,sizeof(line)-1,f) != NULL) {
  525.         if ((type=line[0]) != '#') {
  526.             i = sscanf(&line[1],"%s %s",s1,s2);
  527.             if (debugmode)
  528.                 fprintf(stdout, "bwnfsd: [read_ips] parsing <%s>\n", &line[1]);
  529.  
  530.             if ((i == EOF) || (i == 0) || (i > 2) || ((type != '+') &&
  531.                 (type != '-') && (type != '=')) || ((type == '=') &&
  532.                 (i != 2)) || ((type != '=') && (i != 1))) {
  533.                 fprintf(stdout, "bwnfsd: [read_ips] syntax error, line ignored : %s",line);
  534.             } else {
  535.                 if (!convert_ip(s1,&ip,&mask)) {
  536.                     fprintf(stdout, "bwnfsd: [read_ips] \"%s\" invalid address.\n",s1);
  537.                     continue;
  538.                 }
  539.                 if (i == 2)
  540.                     if (!convert_ip(s2, &redirect_ip, NULL)) {
  541.                            fprintf(stdout, "bwnfsd: [read_ips] \42%s\42 invalid address.\n",s1);
  542.                            continue;
  543.                     }
  544.                 ips = (struct mm_ips **) realloc(ips,sizeof(ips)*(ips_count+1));
  545.                 *(ips+ips_count) = (struct mm_ips *) malloc(sizeof(struct mm_ips));
  546.                 (*(ips+ips_count))->type    = type;
  547.                 (*(ips+ips_count))->ip        = ip;
  548.                 (*(ips+ips_count))->mask    = mask;
  549.                 (*(ips+ips_count))->redirect_ip = redirect_ip;
  550.                 ips_count++;
  551.                }
  552.         }
  553.     }
  554.     fclose(f);
  555.     if (debugmode)
  556.         fprintf(stdout, "bwnfsd: [read_ips] exiting with %u values\n", ips_count);
  557. }
  558.  
  559. /*
  560.  *     Add UID to USERNAME translation to cache
  561.  */
  562. void
  563. add_uid(uid,username)
  564.     int    uid;
  565.     char    *username;
  566. {
  567.     if (debugmode)
  568.         fprintf(stdout, "bwnfsd: [add_uid] uid <%d>, name <%s>\n", uid, username);
  569.     if (uids_count++ == 0)
  570.         uds = (struct mm_uids **) malloc(1);
  571.  
  572.     uds                   = (struct mm_uids **) realloc(uds,sizeof(uds)*uids_count);
  573.     (*(uds+uids_count-1))           = (struct mm_uids *) malloc(sizeof(struct mm_uids));
  574.     (*(uds+uids_count-1))->mm_uid       = uid;
  575.     (*(uds+uids_count-1))->mm_username = (char *) malloc(strlen(username)+1);
  576.     (void) strcpy((*(uds+uids_count-1))->mm_username,username);
  577. }
  578.  
  579. /*
  580.  *     Lookup USERNAME given a UID, also add translation to cache
  581.  */
  582. char *
  583. get_ui_name(uid)
  584.     int    uid;
  585. {
  586. struct passwd *pww;
  587. int i;
  588.  
  589.     if (debugmode)
  590.         fprintf(stdout, "bwnfsd: [get_ui_name] uid <%u>\n", uid);
  591.  
  592.     for (i=0; i<uids_count; i++)
  593.         if ((*(uds+i))->mm_uid == uid)
  594.             return((*(uds+i))->mm_username);
  595.     if ((pww=getpwuid(uid)) == NULL) {
  596.         if (debugmode)
  597.             fprintf(stdout, "bwnfsd: [get_ui_name] getpwuid returned NULL\n");
  598.         return(NULL);
  599.     }
  600.     add_uid(uid,pww->pw_name);
  601.     if (debugmode)
  602.         fprintf(stdout, "bwnfsd: [get_ui_name] returns %s\n", pww->pw_name);
  603.     return(pww->pw_name);
  604. }
  605.  
  606. /*
  607.  *     Given a UID, GID and USERNAME, create a list of GIDs associated
  608.  *     with the UID, a maximum of NGRPS GIDS are used.
  609.  */
  610. void
  611. fill_gid(gd,uid,gid,username)
  612.     struct mm_gidss *gd;
  613.     int    uid,gid;
  614.     char    *username;
  615. {
  616. struct group *gr;
  617. struct group *getgrent();
  618. char   **p;
  619. int    flag;
  620.  
  621.     add_uid(uid,username);
  622.     if (debugmode)
  623.         fprintf(stdout, "bwnfsd: [fill_gid] uid = %u, gid = %u, user = %s\n", uid, gid, username);
  624.     flag         = 0;
  625.     gd->mm_uid     = uid;
  626.     gd->mm_gid     = gid;
  627.     gd->mm_gid_count = 0;
  628.     (void) setgrent();
  629.     while ((gr=getgrent()) != NULL) {
  630.         p = gr->gr_mem;
  631.         while (((*p) != NULL) && (gd->mm_gid_count < NGRPS)) {
  632.             if (strcmp((*p),username) == 0) {
  633.                 gd->mm_gids[gd->mm_gid_count++] = gr->gr_gid;
  634.                 if (gr->gr_gid == gid)
  635.                     flag = 1;
  636.                 break;
  637.             }
  638.             p++;
  639.         }
  640.     }
  641.     if ((flag == 0) && (gd->mm_gid_count < NGRPS))
  642.         gd->mm_gids[gd->mm_gid_count++] = gid;
  643.     (void) endgrent();
  644. }
  645.  
  646. /*
  647.  *     Return a list of GIDs for a given UID. The cache of GIDS/UID is
  648.  *     updated and used.
  649.  */
  650. struct mm_gidss *
  651. get_gids(uid,gid,username)
  652.     int uid,gid;
  653.     char *username;
  654. {
  655. int i;
  656.  
  657.     if (debugmode)
  658.         fprintf(stdout, "bwnfsd: [mm_gidss] uid = %u, gid = %u, name = %s\n", uid, gid, username);
  659.  
  660.     for (i=0; i<gids_count; i++)
  661.         if ((*(gds+i))->mm_uid == uid) {
  662.             if (debugmode)
  663.                 fprintf(stdout, "bwnfsd: [mm_gidss] gids_count = %u\n", gids_count);
  664.             return(*(gds+i));
  665.         }
  666.  
  667.     if (gids_count++ == 0)
  668.         gds = (struct mm_gidss **) malloc(1);
  669.  
  670.     gds = (struct mm_gidss **) realloc(gds,sizeof(gds)*gids_count);
  671.     (*(gds+gids_count-1)) = (struct mm_gidss *) malloc(sizeof(struct mm_gidss));
  672.     (void) fill_gid((*(gds+gids_count-1)), uid, gid, username);
  673.     if (debugmode)
  674.         fprintf(stdout, "bwnfsd: [mm_gidss] gids_count = %u\n", gids_count);
  675.     return(*(gds+gids_count-1));
  676. }
  677.  
  678. static struct my_groups {
  679.     int my_gid;
  680.     char    *my_name;
  681. } **g;
  682.  
  683. static int group_count=0;
  684.  
  685. /*
  686.  *     Return the text name of a GID, if none is found, then the GID
  687.  *     is convert to a text number.
  688.  */
  689. char *
  690. get_gr_name(gid)
  691.     int    gid;
  692. {
  693. static char gd[32];
  694. int i;
  695.  
  696.     if (debugmode)
  697.         fprintf(stdout, "bwnfsd: [get_gr_name] for gid %u\n", gid);
  698.  
  699.     for (i=0; i<group_count; i++)
  700.         if ((*(g+i))->my_gid == gid) {
  701.             if (debugmode)
  702.                 fprintf(stdout, "bwnfsd: [get_gr_name] returns %s\n", ((*(g+i))->my_name));
  703.             return ((*(g+i))->my_name);
  704.         }
  705.     sprintf(gd,"%u",gid);
  706.     if (debugmode)
  707.         fprintf(stdout, "bwnfsd: [get_gr_name] returns %s\n", gd);
  708.     return(gd);
  709. }
  710.  
  711. /*
  712.  *     Given a group name, return the GID associated with it.
  713.  */
  714. int *
  715. get_gr_gid(name)
  716.     char *name;
  717. {
  718. int i;
  719.  
  720.     if (debugmode)
  721.         fprintf(stdout, "bwnfsd: [get_gr_gid] for %s\n", name);
  722.     for (i=0; i<group_count; i++)
  723.         if (strcmp((*(g+i))->my_name,name) == 0) {
  724.             if (debugmode)
  725.                 fprintf(stdout, "bwnfsd: [get_gr_gid] returns %d\n", (*(g+i))->my_gid);
  726.             return(&(*(g+i))->my_gid);
  727.         }
  728.     if (debugmode)
  729.         fprintf(stdout, "bwnfsd: [get_gr_gid] returns NULL\n");
  730.     return (NULL);
  731. }
  732.  
  733. /*
  734.  *     Cache a list of all group names and their associated GIDS.
  735.  */
  736. void
  737. get_groups()
  738. {
  739. struct group *gr;
  740. struct group *getgrent();
  741.  
  742.     if (debugmode)
  743.         fprintf(stdout, "bwnfsd: [get_groups] called\n");
  744.  
  745.     g = (struct my_groups **) malloc(1);
  746.     (void) setgrent();
  747.     while ((gr=getgrent()) != NULL) {
  748.         group_count++;
  749.         g = (struct my_groups **) realloc(g,sizeof(g)*group_count);
  750.         (*(g+group_count-1)) = (struct my_groups *) malloc(sizeof(struct my_groups));
  751.         (*(g+group_count-1))->my_name = (char *) malloc(strlen(gr->gr_name)+1);
  752.  
  753.         (void) strcpy((*(g+group_count-1))->my_name,gr->gr_name);
  754.         (*(g+group_count-1))->my_gid = gr->gr_gid;
  755.     }
  756.     (void) endgrent();
  757. }
  758.  
  759. #ifdef FIND_QUEUES_SVR4
  760. void
  761. get_class_list(char *name, int pn)
  762. {
  763. FILE *f;
  764. char line[128];
  765. char file_name[64];
  766. int i;
  767.  
  768.     if (debugmode)
  769.         fprintf(stdout, "bwnfsd: [get_class_list] name = %s, pn = %u\n", name, pn);
  770.     printer_access[pn].access     = CLASS;
  771.     printer_access[pn].n.printers = NULL;
  772.     printer_access[pn].count      = 0;
  773.     sprintf(file_name,"/usr/spool/lp/admins/lp/classes/%s",name);
  774.  
  775.     if ((f=fopen(file_name,"r")) == NULL) {
  776.         if (debugmode)
  777.             fprintf(stdout, "bwnfsd: [get_class_list] open file %s returned NULL\n", file_name);
  778.         return;
  779.     }
  780.     while (fgets(line,128,f) != NULL) {
  781.         *(line+strlen(line)-1) = '\0';
  782.         for (i=0; i<pn; i++)
  783.             if (strcmp(line,printers[i].queuename) == 0) {
  784.                 if (printer_access[pn].count++ == 0)
  785.                     printer_access[pn].n.printers = (int *) malloc(sizeof(int));
  786.                 else
  787.                     printer_access[pn].n.printers = (int *) realloc(printer_access[pn].n.printers,printer_access[pn].count * sizeof(int));
  788.                 *(printer_access[pn].n.printers+printer_access[pn].count-1) = i;
  789.                 break;
  790.             }
  791.     }
  792.     fclose(f);
  793. }
  794.  
  795.  
  796. void
  797. get_access(char *name, int pn)
  798. {
  799. FILE *f;
  800. char line[128];
  801. char file_name[64];
  802. char **p;
  803. int i;
  804.  
  805.     if (debugmode)
  806.         fprintf(stdout, "bwnfsd: [get_access] name = %s, pn = %u\n", name, pn);
  807.     printer_access[pn].access  = ALLOW;
  808.     printer_access[pn].n.users = NULL;
  809.     printer_access[pn].count   = 0;
  810.     sprintf(file_name,"/usr/spool/lp/admins/lp/printers/%s/users.allow",name);
  811.     if ((f=fopen(file_name,"r")) != NULL) {
  812.         if (debugmode)
  813.             fprintf(stdout, "bwnfsd: [get_access] reading %s\n", file_name);
  814.         while (fgets(line,128,f) != NULL) {
  815.             *(line+strlen(line)-1) = '\0';
  816.             if ((strcmp(line,"any") == 0) ||
  817.                 (strcmp(line,"all") == 0) ||
  818.                 (strcmp(line,"all!all") == 0)) {
  819.                 printer_access[pn].n.users = NULL;
  820.                 printer_access[pn].count = 0;
  821.                 break;
  822.             }
  823.             if (printer_access[pn].count++ == 0)
  824.                 printer_access[pn].n.users = (char **) malloc(sizeof(char**));
  825.             else
  826.                 printer_access[pn].n.users = (char **) realloc(printer_access[pn].n.users,printer_access[pn].count * sizeof(char**));
  827.             *(printer_access[pn].n.users+printer_access[pn].count-1) = strdup(line);
  828.         }
  829.         fclose(f);
  830.         if (printer_access[pn].count != 0) {
  831.             if (debugmode) {
  832.                 fprintf(stdout, "bwnfsd: [get_access] access count = %u\nbwnfsd: [get_access] Allowed users:\n", printer_access[pn].count);
  833.                 p = printer_access[pn].n.users;
  834.                 for (i=0; i<printer_access[pn].count; i++)
  835.                     fprintf(stdout, "bwnfsd: [get_access]               %s\n", *p++);
  836.             }
  837.             return;
  838.         }
  839.     } else {
  840.         if (debugmode)
  841.             fprintf(stdout, "bwnfsd: [get_access] unable to open %s\n", file_name);
  842.     }
  843.     printer_access[pn].access = DENY;
  844.     sprintf(file_name,"/usr/spool/lp/admins/lp/printers/%s/users.deny",name);
  845.     if ((f=fopen(file_name,"r")) != NULL) {
  846.         while (fgets(line,128,f) != NULL) {
  847.             *(line+strlen(line)-1) = '\0';
  848.             if ((strcmp(line,"any") == 0) || (strcmp(line,"all") == 0)) {
  849.                 printer_access[pn].n.users = NULL;
  850.                 printer_access[pn].count   = -1;
  851.                 break;
  852.             }
  853.             if (printer_access[pn].count++ == 0)
  854.                 printer_access[pn].n.users = (char **) malloc(sizeof(char**));
  855.             else
  856.                 printer_access[pn].n.users = (char **) realloc(printer_access[pn].n.users,printer_access[pn].count * sizeof(char**));
  857.             *(printer_access[pn].n.users+printer_access[pn].count-1) = strdup(line);
  858.         }
  859.         fclose(f);
  860.         if (printer_access[pn].count != 0)
  861.             if (debugmode) {
  862.                 fprintf(stdout, "bwnfsd: [get_access] access count = %u\nbwnfsd: [get_access] Denied users:\n", printer_access[pn].count);
  863.                 p = printer_access[pn].n.users;
  864.                 for (i=0; i<printer_access[pn].count; i++)
  865.                     fprintf(stdout, "bwnfsd: [get_access]               %s\n", *p++);
  866.             }
  867.     } else {
  868.         if (debugmode)
  869.             fprintf(stdout, "bwnfsd: [get_access] unable to open %s\n", file_name);
  870.     }
  871. }
  872.  
  873.  
  874. void
  875. get_printer_list(status_file, type)
  876. char *status_file;
  877. int  type;
  878. {
  879. FILE *f;
  880. char line[128],name[32];
  881. int  i;
  882.  
  883.     if (debugmode)
  884.         fprintf(stdout, "bwnfsd: [get_printer_list] file = %s, type = %u\n", status_file, type);
  885.     if ((f=fopen(status_file,"r")) == NULL) {
  886.         if (debugmode)
  887.             fprintf(stdout, "bwnfsd: [get_printer_list] unable to open %s\n", status_file);
  888.         return;
  889.     }
  890.     while (fgets(line,128,f) != NULL)
  891.         if (strncmp(line,"=====",5) == 0) {
  892.             if (fgets(name,32,f) == NULL)
  893.                 break;
  894.             *(name+strlen(name)-1) = '\0';
  895.             if (fgets(line,128,f) == NULL)
  896.                 break;
  897.             *(line+strlen(line)-1) = '\0';
  898.             if (debugmode)
  899.                 fprintf(stdout, "bwnfsd: [get_printer_list] name = %s, line = %s\n", name, line);
  900.             for (i=0; i<(int)strlen(line); i++)
  901.                 if (strncmp(&line[i],"accepting",9) == 0)
  902.                     break;
  903.             if (i == strlen(line))
  904.                 continue;
  905.             if (strlen(name) > 11) {
  906.                 fprintf(stdout, "bwnfsd: [get_printer_list] Printer name \"%s\" exceeds 11 characters; not available for linking\n", name);
  907.                 continue;
  908.             }
  909.             if (num_printers >= MAX_NUM_PRINTERS) {
  910.                 if (debugmode)
  911.                     fprintf(stdout, "bwnfsd: [get_printer_list] Max number of printers (%d) exceeded.  Recompile with larger value\n", MAX_NUM_PRINTERS);
  912.                 break;
  913.             }
  914.             printers[num_printers].queuename = strdup(name);
  915.             printers[num_printers].queuecomment = NULL;
  916.             if (type == 0)
  917.                 get_access(name,num_printers++);
  918.             else
  919.                 get_class_list(name,num_printers++);
  920.         }
  921.     fclose(f);
  922. }
  923. #endif
  924.  
  925. /*
  926.  *     Cache a list of available printers, BSD code searchs the /etc/printcap
  927.  *     file.    Creating a dummy /etc/printcap can also work.
  928.  */
  929. void
  930. get_printers()
  931. {
  932. #ifndef FIND_QUEUES_SVR4
  933. static char line[1024];
  934. #ifdef FIND_QUEUES_AIX
  935. static char stanza[255];
  936. #endif
  937. char *p, *p1, *end;
  938. FILE *f;
  939. int start;
  940. #endif
  941. int i;
  942.  
  943.     if (debugmode)
  944.         fprintf(stdout, "bwnfsd: [get_printers] called\n");
  945.  
  946.     num_printers = 0;
  947. #ifdef FIND_QUEUES_SVR4
  948.     get_printer_list("/usr/spool/lp/system/pstatus",0);
  949.     get_printer_list("/usr/spool/lp/system/cstatus",1);
  950. #else
  951. #ifdef FIND_QUEUES_AIX
  952.     if ((f=fopen("/etc/qconfig","r")) == NULL) {
  953.         fprintf(stdout, "bwnfsd: File /etc/qconfig was not found.\n");
  954.         fprintf(stdout, "        No printers are available for use.\n");
  955.         fflush(stdout);
  956.         return;
  957.     }
  958.  
  959.     stanza[0] = '\0';
  960.     while (fgets(line,sizeof(line)-1,f) != NULL) {
  961.         line[sizeof(line)-1] = '\0';
  962.         for (p=line; isspace(*p); )
  963.             p++;
  964.         if (*p == '*')
  965.             continue;
  966.         for (p1=&line[strlen(line)-1]; isspace(*p1); --p1)
  967.             *p1 = '\0';
  968.         if (strchr(p, ':') != NULL) {
  969.             strcpy(stanza, p);
  970.             if (stanza[strlen(stanza)-1] == ':')
  971.                 stanza[strlen(stanza)-1] = '\0';
  972.             continue;
  973.         }
  974.         if (my_strstr(p, "device") != NULL) {
  975.             if (stanza[0] != '\0') {
  976.                 if (num_printers >= MAX_NUM_PRINTERS) {
  977.                     fprintf(stdout, "bwnfsd: [get_printers] Max number of printers (%d) exceeded.\nRecompile with larger value\n", MAX_NUM_PRINTERS);
  978.                     fflush(stdout);
  979.                     goto outoutout;
  980.                 }
  981.                 if (strlen(stanza) <= 11) {
  982.                     printers[num_printers].queuename = my_strdup(stanza);
  983.                     printers[num_printers].queuecomment = NULL;
  984.                     printers[num_printers].queuestatus = WNPRQ_ACTIVE;
  985.                     printers[num_printers].numphysicalprinters = 0;
  986.                     printers[num_printers].lasttime = 0L;
  987.                     printers[num_printers].head = NULL;
  988.                     num_printers++;
  989.                 } else
  990.                     fprintf(stdout, "bwnfsd: [get_printer_list] Printer name \"%s\" exceeds 11 characters; not available for linking\n", stanza);
  991.                 stanza[0] = '\0';
  992.             }
  993.         }
  994.     }
  995. outoutout:
  996.     fclose(f);
  997. #else
  998. #ifdef FIND_QUEUES_PRINTCAP
  999.     if ((f=fopen("/etc/printcap","r")) == NULL) {
  1000.         fprintf(stdout, "bwnfsd: File /etc/printcap was not found.\n");
  1001.         fprintf(stdout, "        No printers are available for use.\n");
  1002.         fflush(stdout);
  1003.         return;
  1004.     }
  1005.  
  1006.     while (fgets(line,sizeof(line)-1,f) != NULL) {
  1007.         start=num_printers;
  1008. multi_line:
  1009.         if ((p=strchr(line,'#')) != NULL)
  1010.             *p = '\0';
  1011.         if ((p=strchr(line,':')) != NULL)
  1012.             *p = '\0';
  1013.         if ((end=line+strlen(line)) == line)
  1014.             continue;
  1015.         if (*(end-1) == '\n')
  1016.             *(--end) = '\0';
  1017.         if (*(end-1) == '\\') {
  1018.             *(--end) = '\0';
  1019.             if ((sizeof(line)-(end-line)) <= 0) {
  1020.                 fprintf(stdout, "bwnfsd: [get_printers] Multi-line line too long in /etc/printcap.\n");
  1021.                 fflush(stdout);
  1022.                 break;
  1023.             }
  1024.             if (fgets(end,sizeof(line)-(end-line),f) != NULL)
  1025.                 goto multi_line;
  1026.         }
  1027.         for (p=line; p<=end; ) {
  1028.             while ((*p == ' ') || (*p == '\t'))
  1029.                 p++;
  1030.             if (!*p)
  1031.                 break;
  1032.             p1 = p;
  1033.             while (strchr(" \t|",*p1) == NULL)
  1034.                 p1++;
  1035.             if ((*p1 == ' ') || (*p1 == '\t')) {
  1036.                 while (strchr("|",*p1) == NULL)
  1037.                     p1++;
  1038.                 *p1 = '\0';
  1039.                 while ((p[strlen(p)-1] == ' ') || (p[strlen(p)-1] == '\t'))
  1040.                     p[strlen(p)-1] = '\0';
  1041.                 if ((strchr(p,' ') != NULL) || (strchr(p,'\t') != NULL)) {
  1042.                     for (i=start; i<num_printers; i++)
  1043.                         printers[i].queuecomment = my_strdup(p);
  1044.                     start = num_printers;
  1045.                     p = p1 + 1;
  1046.                     continue;
  1047.                 }
  1048.             } else
  1049.                 *p1 = '\0';
  1050.             if (*p) {
  1051.                 if (num_printers >= MAX_NUM_PRINTERS) {
  1052.                     fprintf(stdout, "bwnfsd: [get_printers] Max number of printers (%d) exceeded.\nRecompile with larger value\n", MAX_NUM_PRINTERS);
  1053.                     fflush(stdout);
  1054.                     goto outoutout;
  1055.                 }
  1056.                 if (strlen(p) <= 11) {
  1057.                     printers[num_printers].queuename = my_strdup(p);
  1058.                     printers[num_printers].queuecomment = NULL;
  1059.                     printers[num_printers].queuestatus = WNPRQ_ACTIVE;
  1060.                     printers[num_printers].numphysicalprinters = 0;
  1061.                     printers[num_printers].lasttime = 0L;
  1062.                     printers[num_printers].head = NULL;
  1063.                     num_printers++;
  1064.                 } else
  1065.                     fprintf(stdout, "bwnfsd: [get_printer_list] Printer name \"%s\" exceeds 11 characters; not available for linking\n", p);
  1066.             }
  1067.             p = p1 + 1;
  1068.         }
  1069.     }
  1070. outoutout:
  1071.     fclose(f);
  1072. #else
  1073.  error FIND_QUEUES_Something must be specified
  1074. #endif
  1075. #endif
  1076. #endif
  1077.     if (debugmode) {
  1078.           fprintf(stdout, "bwnfsd: [get_printers] Following devices are available:\n");
  1079.           for (i=0; i<num_printers; i++)
  1080.               fprintf(stdout, "bwnfsd:                 %s\n", printers[i].queuename);
  1081.     }
  1082.  
  1083. }
  1084.  
  1085. static struct var_file {
  1086.     int    status;
  1087.     int    dir_size;
  1088.     char    *dir_handle;
  1089. } f;
  1090.  
  1091. /*
  1092.  *     DOS 3.1 Sharing and Unsharing code. Uses the same format for rpc.lockd
  1093.  *     as BWNFSD, so some parameters are ignored. The cookie under rpc.lockd
  1094.  *     must be 4 bytes long under BWNFSD.
  1095.  */
  1096. xdr_share(xdrsp,l)
  1097.     XDR *xdrsp;
  1098.     struct locking *l;
  1099. {
  1100. int  i;
  1101. char g[32];
  1102. char *p;
  1103.  
  1104.     if (debugmode > 1) {
  1105.         fprintf(stdout, "bwnfsd: [xdr_share] called for %s, ofs = %ld, len = %ld\n", l->name, l->offset, l->length);
  1106.         fprintf(stdout, "bwnfsd:             mode = %u, access = %u, stat = %u, sequence = %u\n", l->mode, l->access, l->stat, l->sequence);
  1107.     }
  1108.     if (!xdr_int(xdrsp, &l->cookie))
  1109.         return(0);
  1110.     if (l->cookie != 4)
  1111.         return(0);
  1112.     if (!xdr_int(xdrsp, &l->cookie))
  1113.         return(0);
  1114.  
  1115.     p = l->name;
  1116.     if (!xdr_string(xdrsp,&p,17))
  1117.         return(0);
  1118.     p = l->fh;
  1119.     if (!xdr_bytes(xdrsp,&p,&i,32))
  1120.         return(0);
  1121.     p = g;
  1122.     if (!xdr_bytes(xdrsp,&p,&i,32))
  1123.         return(0);
  1124.     if (!xdr_int(xdrsp, &l->mode))
  1125.         return(0);
  1126.     if (!xdr_int(xdrsp, &l->access))
  1127.         return(0);
  1128.  
  1129.     if (debugmode)
  1130.         fprintf(stdout, "bwnfsd: [xdr_share] returns (1)\n");
  1131.     return(1);
  1132. }
  1133.  
  1134.  
  1135. /*
  1136.  *     Get Printers response
  1137.  */
  1138. int
  1139. xdr_printers(xdrsp,l)
  1140.     XDR *xdrsp;
  1141.     char *l;
  1142. {
  1143. int i;
  1144. char *p;
  1145.  
  1146.     if (debugmode)
  1147.         fprintf(stdout, "bwnfsd: [xdr_printers] called\n");
  1148.     i = num_printers;
  1149.     if (!xdr_int(xdrsp, &i))
  1150.         return(0);
  1151.     for (i=0; i<num_printers; i++) {
  1152.         p = printers[i].queuename;
  1153.         if (!xdr_string(xdrsp, &p, 24))
  1154.             return(0);
  1155.         p = printers[i].queuecomment;
  1156.         if (p == NULL)
  1157.             p = "";
  1158.         if (!xdr_string(xdrsp, &p, 255))
  1159.             return(0);
  1160.     }
  1161.  
  1162.     if (debugmode)
  1163.         fprintf(stdout, "bwnfsd: [xdr_printers] returns (1)\n");
  1164.     return(1);
  1165. }
  1166.  
  1167. /*
  1168.  *     DOS 3.1 Share response.
  1169.  */
  1170. int
  1171. xdr_shareres(xdrsp,l)
  1172.     XDR *xdrsp;
  1173.     struct locking *l;
  1174. {
  1175. int i;
  1176. char *p;
  1177.  
  1178.     if (debugmode)
  1179.         fprintf(stdout, "bwnfsd: [xdr_shareres] called by %s\n", l->name);
  1180.     i = 4;
  1181.     if (!xdr_int(xdrsp, &i))
  1182.         return(0);
  1183.     if (!xdr_int(xdrsp, &l->cookie))
  1184.         return(0);
  1185.     if (!xdr_int(xdrsp,&l->stat))
  1186.         return(0);
  1187.     l->sequence++;
  1188.     if (!xdr_int(xdrsp,&l->sequence))
  1189.         return(0);
  1190.  
  1191.     if (debugmode)
  1192.         fprintf(stdout, "bwnfsd: [xdr_shareres] returns (1)\n");
  1193.     return(1);
  1194. }
  1195.  
  1196.  
  1197. /*
  1198.  *     DOS 3.1 locking request. Note that several parameters are ignored.
  1199.  */
  1200. int
  1201. xdr_lock(xdrsp,l)
  1202.     XDR *xdrsp;
  1203.     struct locking *l;
  1204. {
  1205. int  i;
  1206. union {
  1207.    char g[32];
  1208.    unsigned long lockowner;
  1209. } g;
  1210. char *p;
  1211.  
  1212.     if (debugmode) {
  1213.         fprintf(stdout, "bwnfsd: [xdr_lock] called by %s\n", l->name);
  1214.         if (debugmode > 1)
  1215.             fprintf(stdout, "bwnfsd:            ofs = %lu, len = %lu\n", l->offset, l->length);
  1216.     }
  1217.     if (!xdr_int(xdrsp, &l->cookie))
  1218.         return(0);
  1219.     if (!xdr_int(xdrsp, &l->cookie))
  1220.         return(0);
  1221.     if (!xdr_int(xdrsp,&i))
  1222.         return(0);
  1223.     if (!xdr_int(xdrsp,&i))
  1224.         return(0);
  1225.     p = l->name;
  1226.     if (!xdr_string(xdrsp,&p,17))
  1227.         return(0);
  1228.     p = l->fh;
  1229.     if (!xdr_bytes(xdrsp,&p,&i,32))
  1230.         return(0);
  1231.     p = (char *)&g;
  1232.     if (!xdr_bytes(xdrsp,&p,&i,32))
  1233.         return(0);
  1234.     l->lockowner = g.lockowner;
  1235.     if (!xdr_int(xdrsp,&i))
  1236.         return(0);
  1237.     if (!xdr_int(xdrsp, &l->offset))
  1238.         return(0);
  1239.     if (!xdr_int(xdrsp, &l->length))
  1240.         return(0);
  1241.     if (debugmode > 1)
  1242.         fprintf(stdout, "bwnfsd: [xdr_lock] returns (1)\n");
  1243.     return(1);
  1244. }
  1245.  
  1246.  
  1247. /*
  1248.  *     DOS 3.1 unlock request. Note that several parameters are ignored.
  1249.  */
  1250. xdr_unlock(xdrsp,l)
  1251.     XDR *xdrsp;
  1252.     struct locking *l;
  1253. {
  1254. int  i;
  1255. char g[32];
  1256. char *p;
  1257.  
  1258.     if (debugmode) {
  1259.         fprintf(stdout, "bwnfsd: [xdr_unlock] called by %s\n", l->name);
  1260.         if (debugmode > 1)
  1261.             fprintf(stdout, "bwnfsd:              ofs = %lu, len = %lu\n", l->offset, l->length);
  1262.     }
  1263.     if (!xdr_int(xdrsp, &l->cookie))
  1264.         return(0);
  1265.     if (!xdr_int(xdrsp, &l->cookie))
  1266.         return(0);
  1267.  
  1268.     p = l->name;
  1269.     if (!xdr_string(xdrsp,&p,17))
  1270.         return(0);
  1271.     p = l->fh;
  1272.     if (!xdr_bytes(xdrsp,&p,&i,32))
  1273.         return(0);
  1274.     p = g;
  1275.     if (!xdr_bytes(xdrsp,&p,&i,32))
  1276.         return(0);
  1277.     if (!xdr_int(xdrsp,&i))
  1278.         return(0);
  1279.     if (!xdr_int(xdrsp, &l->offset))
  1280.         return(0);
  1281.     if (!xdr_int(xdrsp, &l->length))
  1282.         return(0);
  1283.     if (debugmode > 1)
  1284.         fprintf(stdout, "bwnfsd: [xdr_unlock] returns (1)\n");
  1285.     return(1);
  1286. }
  1287.  
  1288. /*
  1289.  *     Send Locking response.
  1290.  */
  1291. int
  1292. xdr_res(xdrsp,l)
  1293.     XDR *xdrsp;
  1294.     struct locking *l;
  1295. {
  1296. int i;
  1297. char *p;
  1298.  
  1299.     if (debugmode > 1)
  1300.         fprintf(stdout, "bwnfsd: [xdr_res] called\n");
  1301.     i = 4;
  1302.     if (!xdr_int(xdrsp, &i))
  1303.         return(0);
  1304.     if (!xdr_int(xdrsp, &l->cookie))
  1305.         return(0);
  1306.     if (!xdr_int(xdrsp,&l->stat))
  1307.         return(0);
  1308.     if (debugmode)
  1309.         fprintf(stdout, "bwnfsd: [xdr_res] returns (1)\n");
  1310.     return(1);
  1311. }
  1312.  
  1313.  
  1314. /*
  1315.  *     Remove all DOS 3.1 locks and shares, note that the PC's name is
  1316.  *     a maximum of 16 chaarcters.
  1317.  */
  1318. int
  1319. xdr_get_lock_name(xdrsp,l)
  1320.     XDR *xdrsp;
  1321.     char *l;
  1322. {
  1323.     if (debugmode)
  1324.         fprintf(stdout, "bwnfsd: [xdr_get_lock_name] called\n");
  1325.     return(xdr_string(xdrsp,&l,17));
  1326. }
  1327.  
  1328. /*
  1329.  *     Send a redirect to a new IP during an authorization request.
  1330.  */
  1331. int
  1332. xdr_new_ip(xdrsp, ip)
  1333.     XDR *xdrsp;
  1334.     unsigned long *ip;
  1335. {
  1336. int i;
  1337.  
  1338.     if (debugmode)
  1339.         fprintf(stdout, "bwnfsd: [xdr_new_ip] called\n");
  1340.     i = 3;
  1341.     if (!xdr_int(xdrsp, &i))
  1342.         return(0);
  1343.     if (!xdr_int(xdrsp, ip))
  1344.         return(0);
  1345.     if (debugmode)
  1346.         fprintf(stdout, "bwnfsd: [xdr_new_ip] returns (1)\n");
  1347.     return(1);
  1348. }
  1349.  
  1350. /*
  1351.  *     Get GROUP name.
  1352.  */
  1353. int
  1354. xdr_g_string(xdrsp, st)
  1355.     XDR *xdrsp;
  1356.     char *st;
  1357. {
  1358. char *p;
  1359.  
  1360.     if (debugmode)
  1361.         fprintf(stdout, "bwnfsd: [xdr_g_string] called\n");
  1362.     p = st;
  1363.     if (!xdr_string(xdrsp,&p,32))
  1364.         return(0);
  1365.     if (debugmode)
  1366.         fprintf(stdout, "bwnfsd: [xdr_g_string] returns (1)\n");
  1367.     return(1);
  1368. }
  1369.  
  1370. /*
  1371.  *     Send Status and GID
  1372.  */
  1373. int
  1374. xdr_send_gid(xdrsp, st)
  1375.     XDR *xdrsp;
  1376.     char *st;
  1377. {
  1378. int   *i, j;
  1379.  
  1380.     if (debugmode)
  1381.         fprintf(stdout, "bwnfsd: [xdr_send_gid] called with st = %s\n", st);
  1382.     i = get_gr_gid(st);
  1383.     if (i == NULL) {
  1384.         j = 2;
  1385.         if (!xdr_int(xdrsp,&j))
  1386.             return(0);
  1387.     } else {
  1388.         j = 0;
  1389.         if (!xdr_int(xdrsp,&j))
  1390.             return(0);
  1391.         if (!xdr_int(xdrsp,i))
  1392.             return(0);
  1393.     }
  1394.     if (debugmode)
  1395.         fprintf(stdout, "bwnfsd: [xdr_send_gid] returns (1)\n");
  1396.     return(1);
  1397. }
  1398.  
  1399. /*
  1400.  *     Get list of UIDs to translate to text.
  1401.  */
  1402. int
  1403. xdr_nuids(xdrsp, luids)
  1404.     XDR *xdrsp;
  1405.     int luids[NUSRS+1];
  1406. {
  1407. int i;
  1408.  
  1409.     if (debugmode)
  1410.         fprintf(stdout, "bwnfsd: [xdr_nuids] called\n");
  1411.     if (!xdr_int(xdrsp,&luids[0]))
  1412.         return(0);
  1413.     if ((luids[0] < 0) || (luids[0] > 16))
  1414.         luids[0] = 0;
  1415.     for (i=1; i<=luids[0]; i++)
  1416.        if (!xdr_int(xdrsp,&luids[i]))
  1417.         return(0);
  1418.     if (debugmode)
  1419.         fprintf(stdout, "bwnfsd: [xdr_nuids] returns (1)\n");
  1420.     return(1);
  1421. }
  1422.  
  1423.  
  1424. /*
  1425.  *     Get list of GIDs to translate to text.
  1426.  */
  1427. int
  1428. xdr_ngids(xdrsp, lgids)
  1429.     XDR *xdrsp;
  1430.     int lgids[NGRPS+1];
  1431. {
  1432. int i;
  1433.  
  1434.     if (debugmode)
  1435.         fprintf(stdout, "bwnfsd: [xdr_ngids] called\n");
  1436.  
  1437.     if (!xdr_int(xdrsp,&lgids[0]))
  1438.         return(0);
  1439.     if ((lgids[0] < 0) || (lgids[0] > 16))
  1440.         lgids[0] = 0;
  1441.     for (i=1; i<=lgids[0]; i++)
  1442.         if (!xdr_int(xdrsp,&lgids[i]))
  1443.             return(0);
  1444.     if (debugmode)
  1445.         fprintf(stdout, "bwnfsd: [xdr_ngids] returns (1)\n");
  1446.     return(1);
  1447. }
  1448.  
  1449.  
  1450. /*
  1451.  *     Send Usernames translated from UIDS.
  1452.  */
  1453. xdr_send_usernames(xdrsp, luids)
  1454.     XDR *xdrsp;
  1455.     int luids[NUSRS+1];
  1456. {
  1457. int i, j;
  1458. char *p;
  1459.  
  1460.     if (debugmode)
  1461.         fprintf(stdout, "bwnfsd: [xdr_send_usernames] called\n");
  1462.     for (i=1; i<=luids[0]; i++) {
  1463.         p = get_ui_name(luids[i]);
  1464.         if (debugmode)
  1465.             fprintf(stdout, "bwnfsd: [xdr_send_usernames] p = %s\n", p);
  1466.         if (p == NULL) {
  1467.             j = 0;
  1468.             if (!xdr_int(xdrsp,&j))
  1469.                 return(0);
  1470.         } else {
  1471.             if (!xdr_string(xdrsp,&p,32))
  1472.                 return(0);
  1473.         }
  1474.     }
  1475.     if (debugmode)
  1476.         fprintf(stdout, "bwnfsd: [xdr_send_usernames] returns (1)\n");
  1477.     return(1);
  1478. }
  1479.  
  1480. /*
  1481.  *     Send Group names translated from GIDS.
  1482.  */
  1483. int
  1484. xdr_send_names(xdrsp, lgids)
  1485.     XDR *xdrsp;
  1486.     int lgids[NGRPS+1];
  1487. {
  1488. int i, j;
  1489. char *p;
  1490.  
  1491.     if (debugmode)
  1492.         fprintf(stdout, "bwnfsd: [xdr_send_names] called\n");
  1493.     for (i=1; i<=lgids[0]; i++) {
  1494.         p = get_gr_name(lgids[i]);
  1495.         if (debugmode)
  1496.             fprintf(stdout, "bwnfsd: [xdr_send_names] p = %s\n", p);
  1497.         if (p == NULL) {
  1498.             j = 0;
  1499.             if (!xdr_int(xdrsp,&j))
  1500.                 return(0);
  1501.         } else {
  1502.             if (!xdr_string(xdrsp,&p,32))
  1503.                 return(0);
  1504.         }
  1505.     }
  1506.     if (debugmode)
  1507.         fprintf(stdout, "bwnfsd: [xdr_send_names] returns (1)\n");
  1508.     return(1);
  1509. }
  1510.  
  1511.  
  1512. /*
  1513.  *     Return fhandle of spool directory. Note a loop of XDR_INTS is
  1514.  *     used to allow this to compile on all systems.
  1515.  */
  1516. xdr_file(xdrsp, file_var)
  1517.     XDR *xdrsp;
  1518.     struct var_file *file_var;
  1519. {
  1520. int i;
  1521.  
  1522.     if (debugmode)
  1523.         fprintf(stdout, "bwnfsd: [xdr_file] called\n");
  1524.     if (!xdr_int(xdrsp,&file_var->status))
  1525.         return(0);
  1526.     if (file_var->status != 0) {
  1527.         if (debugmode > 1)
  1528.             fprintf(stdout, "bwnfsd: [xdr_file] status = %u, returns (1)\n", file_var->status);
  1529.         return(1);
  1530.     }
  1531.     for (i=0; i<32; i+=4)
  1532.         if (!xdr_int(xdrsp, (&file_var->dir_handle[0]) + i))
  1533.             return(0);
  1534.     if (debugmode)
  1535.         fprintf(stdout, "bwnfsd: [xdr_file] returns (1)\n");
  1536.     return(1);
  1537. }
  1538.  
  1539.  
  1540. /*
  1541.  *    Spool a file to the printer:
  1542.  *
  1543.  *        Parameters:
  1544.  *            printer_name (fixed 11 bytes)
  1545.  *            file_name    (fixed 8 bytes) (Internet Address in Hex).
  1546.  *            extension     xdr_int (filename is form C02A0405.xxx)
  1547.  */
  1548. int
  1549. xdr_print(xdrsp)
  1550.     XDR *xdrsp;
  1551. {
  1552. struct stat buf;
  1553. struct passwd *pw1;
  1554. char *p;
  1555. int i;
  1556.  
  1557.     if (debugmode)
  1558.         fprintf(stdout, "bwnfsd: [xdr_print] called\n");
  1559.     i = 11;
  1560.     p = printer;
  1561.     if (!xdr_bytes(xdrsp,&p,&i, 11)) {
  1562.         if (debugmode > 1)
  1563.             fprintf(stdout, "bwnfsd: [xdr_print] printer = %s, file = %s, ext = %s\n", printer, file_name, extension);
  1564.         return(0);
  1565.     }
  1566.     printer[11] = ' ';
  1567.     *strchr(printer, ' ') = '\0';
  1568.     i = 8;
  1569.     p = file_name;
  1570.     if (!xdr_bytes(xdrsp,&p,&i, 8)) {
  1571.         if (debugmode > 1)
  1572.             fprintf(stdout, "bwnfsd: [xdr_print] printer = %s, file = %s, ext = %s\n", printer, file_name, extension);
  1573.         return(0);
  1574.     }
  1575.     file_name[8] = '\0';
  1576.     if (!xdr_int(xdrsp,&extension)) {
  1577.         if (debugmode > 1)
  1578.             fprintf(stdout, "bwnfsd: [xdr_print] printer = %s, file = %s, ext = %s\n", printer, file_name, extension);
  1579.         return(0);
  1580.     }
  1581.     strlwr(file_name);
  1582.     sprintf(file,"%s/%s.%03d",spool_dir,file_name,extension);
  1583. #ifdef FOURTEEN_CHAR
  1584.     sprintf(file1,"%s/%s.%03dq",spool_dir,file_name,extension);
  1585. #else
  1586.     sprintf(file1,"%s/%s.%03dqueued",spool_dir,file_name,extension);
  1587. #endif
  1588.     if (debugmode > 1)
  1589.         fprintf(stdout, "bwnfsd: [xdr_print] f = %s, f1 = %s\n", file, file1);
  1590.     jobname  = NULL;
  1591.     do_print = -1;
  1592.     if (stat(file, &buf) == 0) {
  1593.         do_print = rename(file, file1);
  1594.         if (debugmode && do_print)
  1595.             fprintf(stdout, "bwnfsd: [xdr_print] rename failed, error = %d\n", errno);
  1596.         pw1 = getpwuid((int) buf.st_uid);
  1597.         if (pw1 != NULL) {
  1598.             if (debugmode)
  1599.                 fprintf(stdout, "bwnfsd: [xdr_print] jobname = %s\n", pw1->pw_name);
  1600.             jobname = pw1->pw_name;
  1601.         }
  1602.     } else
  1603.         if (debugmode)
  1604.             if (errno == ENOENT)
  1605.                 fprintf(stdout, "bwnfsd: [xdr_print] duplicate close request\n");
  1606.             else
  1607.                 fprintf(stdout, "bwnfsd: [xdr_print] stat failed, errno = %d\n",errno);
  1608.     if (debugmode)
  1609.         fprintf(stdout, "bwnfsd: [xdr_print] returns (1)\n");
  1610.     return(1);
  1611. }
  1612.  
  1613. struct auth_struct {
  1614.     unsigned long ip;
  1615.     int type;
  1616.     char device[13];
  1617.     char login_text[64];
  1618.     char *username;
  1619.     char *password;
  1620. } auth_request;
  1621.  
  1622. /*
  1623.  *     Request Authorization:
  1624.  *         Parameters:
  1625.  *             IP_Address of server host (XDR_INT)
  1626.  *             Type of request (XDR_INT) (4 - disk, 3 - printer)
  1627.  *             Device to link  (XDR_BYTES max 12) (printer name)
  1628.  *             Username/Password (XDR_BYTES max 64)
  1629.  */
  1630. int
  1631. xdr_auth_request(xdrsp, auth)
  1632.     XDR *xdrsp;
  1633.     struct auth_struct *auth;
  1634. {
  1635. int   i, j, x, y;
  1636. char  *p;
  1637.  
  1638.     if (!xdr_int(xdrsp,&auth->ip))
  1639.         return(0);
  1640.     if (!xdr_int(xdrsp,&auth->type))
  1641.         return(0);
  1642.     i = 11;
  1643.     p = auth->device;
  1644.     if (!xdr_bytes(xdrsp,&p,&i, 12))
  1645.         return(0);
  1646.     auth->device[11] = ' ';
  1647.     p=strchr(auth->device, ' ');
  1648.     if (p == NULL)
  1649.         return(0);
  1650.     *p = '\0';
  1651.     i = 64;
  1652.     p = auth->login_text;
  1653.     if (!xdr_bytes(xdrsp,&p,&i,64))
  1654.         return(0);
  1655.     if (i < 6)
  1656.         auth->type = -1;
  1657.     p = auth->login_text;
  1658.     for (x= -1,j=0; j<i; j++) {
  1659.         y = *p;
  1660.         x ^= *p;
  1661.         *p++ = x;
  1662.         x = y;
  1663.     }
  1664.     auth->username = auth->login_text + 2;
  1665.     auth->password = auth->username + strlen(auth->username) + 1;
  1666.     if (debugmode) {
  1667.         fprintf(stdout, "bwnfsd: [xdr_auth_request] called\n");
  1668.         fprintf(stdout, "bwnfsd:   Link to %d.%d.%d.%d\n",
  1669.                (auth->ip >> 24) & 0xff, (auth->ip >> 16) & 0xff,
  1670.                (auth->ip >>  8) & 0xff, (auth->ip)         & 0xff);
  1671.         fprintf(stdout, "bwnfsd:   Request type     : %u (%s)\n", auth->type, auth->type==3?"print request":"disk request");
  1672.         fprintf(stdout, "bwnfsd:   Requested Device : %s\n", auth->device);
  1673.         fprintf(stdout, "bwnfsd:   Username         : %s\n", auth->username);
  1674. /*
  1675.  *        fprintf(stdout, "bwnfsd:   Password         : %s\n", auth->password);
  1676.  */
  1677.         fprintf(stdout, "bwnfsd: [xdr_auth_request] returns (1)\n");
  1678.     }
  1679.     return(1);
  1680. }
  1681.  
  1682. struct name_struct {
  1683.     char usr_login[64];
  1684.     char *usr_name;
  1685. } name_request;
  1686.  
  1687. int
  1688. xdr_name_request(xdrsp, name)
  1689.     XDR *xdrsp;
  1690.     struct name_struct *name;
  1691. {
  1692. char *p;
  1693.  
  1694.     p = name->usr_login;
  1695.     name->usr_name = name->usr_login;
  1696.     if (!xdr_string(xdrsp,&p,32))
  1697.         return(0);
  1698.     if (debugmode)
  1699.         fprintf(stdout, "bwnfsd: [xdr_name_request] called\n");
  1700.     return(1);
  1701. }
  1702.  
  1703. /*
  1704.  *     Send successful authorization reply.
  1705.  *         Results:
  1706.  *           UID (XDR_INT)
  1707.  *           GID (XDR_INT)
  1708.  *           GID count (XDR_INT)
  1709.  *           GIDs (XDR_INT)     (GID count entries)
  1710.  */
  1711. int
  1712. xdr_pw(xdrsp,pwd)
  1713.     XDR   *xdrsp;
  1714.     struct passwd *pwd;
  1715. {
  1716. int   i;
  1717. struct mm_gidss *gg;
  1718.  
  1719.     if (debugmode)
  1720.         fprintf(stdout, "bwnfsd: [xdr_pw] called\n");
  1721.     i  = 0;
  1722.     gg = get_gids(pwd->pw_uid,pwd->pw_gid,pwd->pw_name);
  1723.     if (debugmode > 1)
  1724.         fprintf(stdout, "bwnfsd: uid = %u, gid = %u, gids = %u\n", gg->mm_uid, gg->mm_gid, gg->mm_gids[0]);
  1725.     if (!xdr_int(xdrsp,&i))
  1726.         return(0);
  1727.     i = pwd->pw_uid;
  1728.     if (!xdr_int(xdrsp,&i))
  1729.         return(0);
  1730.     i = pwd->pw_gid;
  1731.     if (!xdr_int(xdrsp,&i))
  1732.         return(0);
  1733.     if (!xdr_int(xdrsp,&gg->mm_gid_count))
  1734.         return(0);
  1735.     for (i=0; i<gg->mm_gid_count; i++)
  1736.         if (!xdr_int(xdrsp,&gg->mm_gids[i]))
  1737.             return(0);
  1738.  
  1739.     if (debugmode > 1)
  1740.         fprintf(stdout, "bwnfsd: [xdr_pw] returns (1)\n");
  1741.     return(1);
  1742. }
  1743.  
  1744. int
  1745. xdr_get_printq(xdrsp,pq)
  1746.     XDR *xdrsp;
  1747.     struct printqs *pq;
  1748. {
  1749. char *p;
  1750.  
  1751.     if (debugmode)
  1752.         fprintf(stdout, "bwnfsd: [xdr_get_printq] called\n");
  1753.     p = pq->queuename;
  1754.     if (!xdr_string(xdrsp,&p,32))
  1755.         return(0);
  1756.     p = pq->username;
  1757.     if (!xdr_string(xdrsp,&p,32))
  1758.         return(0);
  1759.     return(1);
  1760. }
  1761.  
  1762. int
  1763. xdr_cancel_job(xdrsp,pq)
  1764.     XDR *xdrsp;
  1765.     struct printqs *pq;
  1766. {
  1767. char *p;
  1768.  
  1769.     if (debugmode)
  1770.         fprintf(stdout, "bwnfsd: [xdr_cancel_job] called\n");
  1771.     p = pq->queuename;
  1772.     if (!xdr_string(xdrsp,&p,32))
  1773.         return(0);
  1774.     p = pq->username;
  1775.     if (!xdr_string(xdrsp,&p,32))
  1776.         return(0);
  1777.     if (!xdr_int(xdrsp,&pq->printer_number))
  1778.         return(0);
  1779.     return(1);
  1780. }
  1781.  
  1782. int
  1783. xdr_send_printq(xdrsp,pq)
  1784.     XDR *xdrsp;
  1785.     struct printqs *pq;
  1786. {
  1787. int i, pn;
  1788. struct queueentry *qe;
  1789. char *pp;
  1790.  
  1791.     if (debugmode)
  1792.         fprintf(stdout, "bwnfsd: [xdr_send_printq] called\n");
  1793.     pn = pq->printer_number;
  1794.     i = pn == -1;
  1795.     if (!xdr_int(xdrsp,&i))
  1796.         return(0);
  1797.     if (i != 0)
  1798.         return(1);
  1799.     pp = printers[pn].queuecomment;
  1800.     if (pp == NULL)
  1801.         pp = "";
  1802.     if (!xdr_string(xdrsp,&pp,32))
  1803.         return(0);
  1804.     if (!xdr_int(xdrsp,&printers[pn].queuestatus))
  1805.         return(0);
  1806.     if (!xdr_int(xdrsp,&printers[pn].numphysicalprinters))
  1807.         return(0);
  1808.     qe = printers[pn].head;
  1809.     i = 1;
  1810.     while (qe) {
  1811.         if ((*pq->username != '\0') && (strcmp(pq->username,qe->username) != 0)) {
  1812.             qe=qe->next;
  1813.             continue;
  1814.         }
  1815.         if (!xdr_int(xdrsp,&i))
  1816.             return(0);
  1817.         if (!xdr_int(xdrsp,&qe->jobid))
  1818.             return(0);
  1819.         pp = qe->username;
  1820.         if (pp == NULL)
  1821.             pp = "";
  1822.         if (!xdr_string(xdrsp,&pp,32))
  1823.             return(0);
  1824.         pp = qe->params;
  1825.         if (pp == NULL)
  1826.             pp = "";
  1827.         if (!xdr_string(xdrsp,&pp,255))
  1828.             return(0);
  1829.         if (!xdr_int(xdrsp,&qe->queueposition))
  1830.             return(0);
  1831.         if (!xdr_int(xdrsp,&qe->jobstatus))
  1832.             return(0);
  1833.         if (!xdr_long(xdrsp,&qe->timesubmitted))
  1834.             return(0);
  1835.         if (!xdr_long(xdrsp,&qe->size))
  1836.             return(0);
  1837.         if (!xdr_int(xdrsp,&qe->copies))
  1838.             return(0);
  1839.         pp = qe->jobcomment;
  1840.         if (pp == NULL)
  1841.             pp = "";
  1842.         if (!xdr_string(xdrsp,&pp,255))
  1843.             return(0);
  1844.         qe=qe->next;
  1845.     }
  1846.     i = 0;
  1847.     if (!xdr_int(xdrsp,&i))
  1848.         return(0);
  1849.     return(1);
  1850. }
  1851.  
  1852. #ifdef SCO
  1853. #define SecureWare 1
  1854. #include <sys/security.h>
  1855. #include <sys/audit.h>
  1856. #include <prot.h>
  1857. #endif
  1858.  
  1859. char *
  1860. find_host(r_ip)
  1861.     unsigned long r_ip;
  1862. {
  1863. char *p;
  1864. unsigned long incomming_ip;
  1865. struct hostent *h;
  1866.  
  1867.     if (r_ip == my_ip)
  1868.         p = hostname;
  1869.     else {
  1870.         incomming_ip = ntohl(r_ip);
  1871.         h = gethostbyaddr((char *) &incomming_ip,4,AF_INET);
  1872.         if (h == NULL) {
  1873.             sprintf(remote_host,"%u.%u.%u.%u",
  1874.                        (r_ip >> 24) & 0xff);
  1875.                        (r_ip >> 16) & 0xff,
  1876.                        (r_ip >>  8) & 0xff,
  1877.                        (r_ip      ) & 0xff,
  1878.             p = remote_host;
  1879.         } else
  1880.             p = h->h_name;
  1881.     }
  1882.     return(p);
  1883. }
  1884.  
  1885. struct user_cache_struct {
  1886.     char username[32];
  1887.     int uid, gid;
  1888.     char password[32];
  1889.     unsigned long successes;
  1890. } user_cache[NUM_USER_CACHE] = { 0 };
  1891.  
  1892. int cache_cycle=0;
  1893.  
  1894. void
  1895. add_cache(pw, p)
  1896.     struct passwd *pw;
  1897.     char *p;
  1898. {
  1899. int i,pos;
  1900. unsigned long smin= ~0L;
  1901.  
  1902.     pos = 0;
  1903.     cache_cycle = (cache_cycle+1) % NUM_USER_CACHE;
  1904.     for (i=0; i<NUM_USER_CACHE; i++)
  1905.         if ( (user_cache[i].successes < smin) ||
  1906.              ((user_cache[i].successes == smin) && (i <= cache_cycle))) {
  1907.             pos=i;
  1908.             smin=user_cache[i].successes;
  1909.         }
  1910.     if (debugmode)
  1911.         fprintf(stdout, "bwnfsd: [addcache] <%s> added to position %d replacing <%s(%ld)>\n",
  1912.             pw->pw_name, pos, user_cache[pos].username, user_cache[pos].successes);
  1913.     strcpy(user_cache[pos].username,pw->pw_name);
  1914.     strcpy(user_cache[pos].password,p);
  1915.     user_cache[pos].uid = pw->pw_uid;
  1916.     user_cache[pos].gid = pw->pw_gid;
  1917.     user_cache[pos].successes=1;
  1918. }
  1919.  
  1920. struct passwd *
  1921. getcache(request)
  1922.     struct auth_struct *request;
  1923. {
  1924. static struct passwd pas;
  1925. int i;
  1926.  
  1927.     for (i=0; i<NUM_USER_CACHE; i++) {
  1928.         if (strcmp(request->username, user_cache[i].username) == 0) {
  1929.             if (strcmp(crypt(request->password,user_cache[i].password), user_cache[i].password) == 0) {
  1930.                 pas.pw_name = user_cache[i].username;
  1931.                 pas.pw_uid = user_cache[i].uid;
  1932.                 pas.pw_gid = user_cache[i].gid;
  1933.                 user_cache[i].successes++;
  1934.                 if (debugmode)
  1935.                     fprintf(stdout, "bwnfsd: [getcache] <%s(%ld)> found in cache\n", request->username, user_cache[i].successes);
  1936.                 return(&pas);
  1937.             } else {
  1938.                 user_cache[i].username[0] = '\0';
  1939.                 user_cache[i].successes = 0;
  1940.                 if (debugmode)
  1941.                     fprintf(stdout, "bwnfsd: [getcache] <%s> wrong password in cache\n", request->username);
  1942.                 return(NULL);
  1943.             }
  1944.         }
  1945.     }
  1946.     return(NULL);
  1947. }
  1948.  
  1949. char *
  1950. reqname(req)
  1951.     int req;
  1952. {
  1953. static char buff[100];
  1954.  
  1955.     switch(req) {
  1956.     case NULLPROC:
  1957.         strcpy(buff, "Null Procedure");
  1958.         break;
  1959.     case SPOOL_INQUIRE:
  1960.         strcpy(buff, "Return fhandle of spool directory");
  1961.         break;
  1962.     case SPOOL_FILE:
  1963.         strcpy(buff, "Spool a file");
  1964.         break;
  1965.     case AUTHORIZE:
  1966.         strcpy(buff, "Authorize and return UID and GIDs");
  1967.         break;
  1968.     case GRP_NAME_TO_NUMB:
  1969.         strcpy(buff, "Convert group name to number");
  1970.         break;
  1971.     case GRP_TO_NUMBER:
  1972.         strcpy(buff, "Convert group number(s) to name(s)");
  1973.         break;
  1974.     case RETURN_HOST:
  1975.         strcpy(buff, "Convert IP to hostname");
  1976.         break;
  1977.     case UID_TO_NAME:
  1978.         strcpy(buff, "Convert UID(s) to name(s)");
  1979.         break;
  1980.     case NAME_TO_UID:
  1981.         strcpy(buff, "Convert name(s) to UID(s)");
  1982.         break;
  1983.     case SHARE:
  1984.         strcpy(buff, "DOS Share function");
  1985.         break;
  1986.     case UNSHARE:
  1987.         strcpy(buff, "DOS UnShare function");
  1988.         break;
  1989.     case ZAP_LOCKS:
  1990.         strcpy(buff, "Remove all locks on file by process");
  1991.         break;
  1992.     case LOCK:
  1993.         strcpy(buff, "DOS Lock request");
  1994.         break;
  1995.     case REMOVE:
  1996.         strcpy(buff, "Remove all locks/shares for PC");
  1997.         break;
  1998.     case UNLOCK:
  1999.         strcpy(buff, "DOS Unlock request");
  2000.         break;
  2001.     case GET_PRINTERS:
  2002.         strcpy(buff, "Get a list of printers");
  2003.         break;
  2004.     case GET_PRINTQ:
  2005.         strcpy(buff, "Get print queue entries and status");
  2006.         break;
  2007.     case CANCEL_PRJOB:
  2008.         strcpy(buff, "Cancel a print job");
  2009.         break;
  2010.     default:
  2011.         sprintf(buff, "Unknown request - %d", req);
  2012.         break;
  2013.     }
  2014.     return(buff);
  2015. }
  2016.  
  2017. /*
  2018.  *     The main RPC routine.
  2019.  */
  2020. void
  2021. create_spool(rqstp, transp)
  2022.     struct svc_req *rqstp;
  2023.     SVCXPRT *transp;
  2024. {
  2025. struct passwd *pw;
  2026. int i,j;
  2027. unsigned long r_ip, i_ip;
  2028. char *p;
  2029. #ifdef SHADW
  2030. struct spwd *sp;
  2031. #endif
  2032. #ifdef SCO
  2033. struct pr_passwd *prpw;
  2034. #endif
  2035.  
  2036.     if (debugmode)
  2037.         fprintf(stdout, "bwnfsd: [create_spool] called with %s\n", reqname(rqstp->rq_proc));
  2038.     switch(rqstp->rq_proc) {
  2039.     case NULLPROC:
  2040.         if (!svc_sendreply(transp, xdr_void, 0))
  2041.             if (debugmode)
  2042.                 fprintf(stdout, "bwnfsd: [nullproc] Can't reply to RPC call\n");
  2043.         return;
  2044.     case SPOOL_INQUIRE:
  2045.         if (!svc_sendreply(transp, xdr_file, &f))
  2046.             if (debugmode)
  2047.                 fprintf(stdout, "bwnfsd: [spool_inquire] Can't reply to RPC call\n");
  2048.         return;
  2049.     case SPOOL_FILE:
  2050.         if (!svc_getargs(transp,xdr_print, NULL)) {
  2051.             if (debugmode)
  2052.                 fprintf(stdout, "bwnfsd: [spool_file] svc_getargs request failed\n");
  2053.             svcerr_decode(transp);
  2054.             return;
  2055.         }
  2056.         i = 0;
  2057.         if (do_print == 0) {
  2058.             for (i=0; i<num_printers; i++)
  2059.                 if (strcmp(printers[i].queuename,printer) == 0) {
  2060.                     printers[i].lasttime = 0L;
  2061.                     break;
  2062.                 }
  2063.             if (debugmode)
  2064.                 fflush(stdout);
  2065.             if ((i=fork()) == 0) {
  2066.                 (void) signal(SIGHUP,SIG_IGN);
  2067.                 (void) signal(SIGINT,SIG_IGN);
  2068.                 (void) signal(SIGQUIT,SIG_IGN);
  2069. #ifdef SIGABRT
  2070.                 (void) signal(SIGABRT,SIG_IGN);
  2071. #endif
  2072.                 (void) signal(SIGTERM,SIG_IGN);
  2073.                 print_it(file1,printer,jobname);
  2074.                 exit(0);
  2075.             }
  2076.         }
  2077.         if (i != -1) {
  2078.             if (!svc_sendreply(transp, xdr_void, 0))
  2079.                 if (debugmode)
  2080.                     fprintf(stdout, "bwnfsd: [spool_file] Can't reply to RPC call\n");
  2081.         } else
  2082.             if (debugmode)
  2083.                 fprintf(stdout, "bwnfsd: [spool_file] Can't fork print process\n");
  2084.         return;
  2085.     case AUTHORIZE:
  2086.         if (!svc_getargs(transp,xdr_auth_request, &auth_request)) {
  2087.             if (debugmode)
  2088.                 fprintf(stdout, "bwnfsd: [authorize] svc_getargs request failed\n");
  2089.             svcerr_decode(transp);
  2090.             return;
  2091.         }
  2092.         if (auth_request.type == -1) {
  2093.             i = 1;
  2094.             if (!svc_sendreply(transp, xdr_int, &i))
  2095.                 if (debugmode)
  2096.                     fprintf(stdout, "bwnfsd: [authorize] (1) Can't reply to RPC call\n");
  2097.             return;
  2098.         }
  2099.         if (A_flag == 0) {
  2100.             if (s_flag == 0) {
  2101.                 if (ntohl(auth_request.ip) != my_ip) {
  2102.                     i = 1;
  2103.                     if (!svc_sendreply(transp, xdr_int, &i))
  2104.                         if (debugmode)
  2105.                             fprintf(stdout, "bwnfsd: [authorize] (2) Can't reply to RPC call\n");
  2106.                     return;
  2107.                 }
  2108.             } else {
  2109.                 for (i=0; i<ips_count; i++) {
  2110.                     if (((*(ips+i))->mask & ntohl(auth_request.ip)) == (*(ips+i))->ip) {
  2111.                         switch((*(ips+i))->type) {
  2112.                         case '+' :
  2113.                             i=ips_count+1;
  2114.                             break;
  2115.                         case '-' :
  2116.                             i = 1;
  2117.                             if (!svc_sendreply(transp, xdr_int, &i))
  2118.                                 if (debugmode)
  2119.                                     fprintf(stdout, "bwnfsd: [authorize] (3) Can't reply to RPC call\n");
  2120.                             return;
  2121.                         case '=' :
  2122.                             i_ip = (*(ips+i))->redirect_ip;
  2123.                             if (!svc_sendreply(transp, xdr_new_ip, &i_ip))
  2124.                                 if (debugmode)
  2125.                                     fprintf(stdout, "bwnfsd: [authorize] (4) Can't reply to RPC call\n");
  2126.                             return;
  2127.                         }
  2128.                     }
  2129.                 }
  2130.                 if (i == ips_count) {
  2131.                     i = 1;
  2132.                     if (!svc_sendreply(transp, xdr_int, &i))
  2133.                         if (debugmode)
  2134.                             fprintf(stdout, "bwnfsd: [authorize] (5) Can't reply to RPC call\n");
  2135.                     return;
  2136.                 }
  2137.             }
  2138.         }
  2139. #ifdef SCO
  2140.         if ((prpw=getprpwnam(auth_request.username)) == NULL) {
  2141.             if (debugmode)
  2142.                 fprintf(stdout, "bwnfsd: [authorize] getprpwnam failed\n");
  2143. auth_error:
  2144.             i = 1;
  2145.             if (!svc_sendreply(transp, xdr_int, &i))
  2146.                 if (debugmode)
  2147.                     fprintf(stdout, "bwnfsd: [authorize] (6) Can't reply to RPC call\n");
  2148.             return;
  2149.         }
  2150.         if (prpw->uflg.fg_lock && (prpw->ufld.fd_lock != 0))
  2151.             goto auth_error;
  2152.         i = prpw->ufld.fd_max_tries;
  2153.         if (i == 0)
  2154.             i = 5;
  2155.         if (prpw->ufld.fd_nlogins >= (short) i)
  2156.             goto auth_error;
  2157.         prpw->ufld.fd_encrypt[13] = '\0';
  2158.         if (strcmp(crypt(auth_request.password,prpw->ufld.fd_encrypt), prpw->ufld.fd_encrypt) != 0) {
  2159.             if (debugmode)
  2160.                 fprintf(stdout, "bwnfsd: [authorize] crypt(pwd)=%s doesn't match %s\n",crypt(auth_request.password,prpw->ufld.fd_encrypt), prpw->ufld.fd_encrypt);
  2161.             goto auth_error;
  2162.         }
  2163.         if ((pw=getpwnam(auth_request.username)) == NULL) {
  2164.             if (debugmode)
  2165.                 fprintf(stdout, "bwnfsd: [authorize] getpwnam failed\n");
  2166.             goto auth_error;
  2167.         }
  2168. #else
  2169.         if ((pw=getcache(&auth_request)) != NULL)
  2170.             goto got_pw;
  2171.         if ((pw=getpwnam(auth_request.username)) == NULL) {
  2172.             if (debugmode)
  2173.                 fprintf(stdout, "bwnfsd: [authorize] getpwnam failed\n");
  2174.             i = 1;
  2175.             if (!svc_sendreply(transp, xdr_int, &i))
  2176.                 if (debugmode)
  2177.                     fprintf(stdout, "bwnfsd: [authorize] (6) Can't reply to RPC call\n");
  2178.             return;
  2179.         }
  2180. #ifdef SHADW
  2181.         if ((sp=getspnam(auth_request.username)) == NULL) {
  2182.             if (debugmode)
  2183.                 fprintf(stdout, "bwnfsd: [authorize] getspnam request failed\n");
  2184.             i = 1;
  2185.             if (!svc_sendreply(transp, xdr_int, &i))
  2186.                 if (debugmode)
  2187.                     fprintf(stdout, "bwnfsd: [authorize] (7) Can't reply to RPC call\n");
  2188.             return;
  2189.         }
  2190.         p = sp->sp_pwdp;
  2191. #else
  2192.         p = pw->pw_passwd;
  2193. #endif
  2194.         if (strcmp(crypt(auth_request.password,p),p) != 0) {
  2195.             if (debugmode)
  2196.                 fprintf(stdout, "bwnfsd: [authorize] crypt(pwd)=%s doesn't match %s\n", crypt(auth_request.password,p), p);
  2197.             i = 1;
  2198.             if (!svc_sendreply(transp, xdr_int, &i))
  2199.                 if (debugmode)
  2200.                     fprintf(stdout, "bwnfsd: [authorize] (8) Can't reply to RPC call\n");
  2201.             return;
  2202.         }
  2203.         add_cache(pw, p);
  2204. #endif
  2205. got_pw:
  2206.         if (auth_request.type == 3) {
  2207.             for (i=0; i<num_printers; i++)
  2208.                 if (strcmp(printers[i].queuename,auth_request.device) == 0)
  2209.                     break;
  2210.             if (i == num_printers) {
  2211.                 if (debugmode)
  2212.                     fprintf(stdout, "bwnfsd: [authorize] Printer %s not found\n",auth_request.device);
  2213.                 i = 2;
  2214.                 if (!svc_sendreply(transp, xdr_int, &i))
  2215.                     if (debugmode)
  2216.                         fprintf(stdout, "bwnfsd: [authorize] (9) Can't reply to RPC call\n");
  2217.                 return;
  2218.             }
  2219. #ifdef CHECK_PRINTER_ACCESS
  2220.                if (!check_access(i,auth_request.username)) {
  2221.                 if (debugmode)
  2222.                     fprintf(stdout, "bwnfsd: [authorize] Not authorized for %s\n",auth_request.device);
  2223.                 i = 1;
  2224.                 if (!svc_sendreply(transp, xdr_int, &i))
  2225.                     if (debugmode)
  2226.                         fprintf(stdout, "bwnfsd: [authorize] (10) Can't reply to RPC call\n");
  2227.                 return;
  2228.             }
  2229. #endif
  2230.         }
  2231.         if (!svc_sendreply(transp, xdr_pw, pw))
  2232.             if (debugmode)
  2233.                 fprintf(stdout, "bwnfsd: [authorize] (11) Can't reply to RPC call\n");
  2234.         return;
  2235.     case GRP_NAME_TO_NUMB:
  2236.         if (!svc_getargs(transp,xdr_g_string, g_string)) {
  2237.             if (debugmode)
  2238.                 fprintf(stdout, "bwnfsd: [grp_name_to_numb] svc_getargs request failed\n");
  2239.             svcerr_decode(transp);
  2240.             return;
  2241.         }
  2242.         if (!svc_sendreply(transp, xdr_send_gid, g_string))
  2243.             if (debugmode)
  2244.                 fprintf(stdout, "bwnfsd: [grp_name_to_numb] Can't reply to RPC call\n");
  2245.         return;
  2246.     case GRP_TO_NUMBER:
  2247.         if (!svc_getargs(transp,xdr_ngids, lgids)) {
  2248.             if (debugmode)
  2249.                 fprintf(stdout, "bwnfsd: [grp_to_number] svc_getargs request failed\n");
  2250.             svcerr_decode(transp);
  2251.             return;
  2252.         }
  2253.         if (!svc_sendreply(transp, xdr_send_names, lgids))
  2254.             if (debugmode)
  2255.                 fprintf(stdout, "bwnfsd: [grp_to_number] Can't reply to RPC call\n");
  2256.         return;
  2257.     case RETURN_HOST:
  2258.         if (!svc_getargs(transp,xdr_int, &r_ip)) {
  2259.             if (debugmode)
  2260.                 fprintf(stdout, "bwnfsd: [return_host] svc_getargs request failed\n");
  2261.             svcerr_decode(transp);
  2262.             return;
  2263.         }
  2264.         p = find_host(r_ip);
  2265.         if (debugmode)
  2266.             fprintf(stdout, "bwnfsd: [return_host] remote = %s\n", p);
  2267.  
  2268.         if (!svc_sendreply(transp, xdr_g_string, p))
  2269.             if (debugmode)
  2270.                 fprintf(stdout, "bwnfsd: [return_host] Can't reply to RPC call\n");
  2271.         return;
  2272.     case UID_TO_NAME:
  2273.         if (!svc_getargs(transp,xdr_nuids, luids)) {
  2274.             if (debugmode)
  2275.                 fprintf(stdout, "bwnfsd: [uid_to_name] svc_getargs failed\n");
  2276.             svcerr_decode(transp);
  2277.             return;
  2278.         }
  2279.         if (!svc_sendreply(transp, xdr_send_usernames, luids))
  2280.             if (debugmode)
  2281.                 fprintf(stdout, "bwnfsd: [uid_to_name] Can't reply to RPC call\n");
  2282.         return;
  2283.     case NAME_TO_UID:
  2284.         if (!svc_getargs(transp, xdr_name_request, &name_request)) {
  2285.             if (debugmode)
  2286.                 fprintf(stdout, "bwnfsd: [name_to_uid] svc_getargs failed\n");
  2287.             svcerr_decode(transp);
  2288.             return;
  2289.         }
  2290.         if ((pw=getpwnam(name_request.usr_name)) == NULL) {
  2291.             i = 1;
  2292.             if (!svc_sendreply(transp, xdr_int, &i))
  2293.                 if (debugmode)
  2294.                     fprintf(stdout, "bwnfsd: [name_to_uid] (1) Can't reply to RPC call\n");
  2295.             return;
  2296.         }
  2297.         if (!svc_sendreply(transp, xdr_pw, pw))
  2298.             if (debugmode)
  2299.                 fprintf(stdout, "bwnfsd: [name_to_uid] (2) Can't reply to RPC call\n");
  2300.         return;
  2301.     case REMOVE:
  2302.         if (!svc_getargs(transp,xdr_get_lock_name,lock.name)) {
  2303.             if (debugmode)
  2304.                 fprintf(stdout, "bwnfsd: [remove] svc_getargs failed\n");
  2305.             svcerr_decode(transp);
  2306.             return;
  2307.         }
  2308.         process_lock_request((int) rqstp->rq_proc,lock.name,lock.fh,lock.access,
  2309.                      lock.mode,lock.offset,lock.length,lock.cookie,lock.lockowner);
  2310.         if (!svc_sendreply(transp,xdr_void,NULL))
  2311.             if (debugmode)
  2312.                 fprintf(stdout, "bwnfsd: [remove] Can't reply to RPC call\n");
  2313.         return;
  2314.     case SHARE:
  2315.     case UNSHARE:
  2316.         if (!svc_getargs(transp,xdr_share,&lock)) {
  2317.             if (debugmode)
  2318.                 fprintf(stdout, "bwnfsd: [%sshare] svc_getargs failed\n", rqstp->rq_proc==SHARE?"":"un");
  2319.             svcerr_decode(transp);
  2320.             return;
  2321.         }
  2322.         lock.stat = !process_lock_request((int) rqstp->rq_proc,lock.name,lock.fh,
  2323.                      lock.access,lock.mode,lock.offset,lock.length,lock.cookie,lock.lockowner);
  2324.         if (debugmode) {
  2325.             if (lock.stat)
  2326.                 fprintf(stdout, "bwnfsd: [%sshare] lock status = false\n", rqstp->rq_proc==SHARE?"":"un");
  2327.             else
  2328.                 fprintf(stdout, "bwnfsd: [%sshare] lock status = true\n", rqstp->rq_proc==SHARE?"":"un");
  2329.         }
  2330.         if (!svc_sendreply(transp,xdr_shareres,&lock))
  2331.             if (debugmode)
  2332.                 fprintf(stdout, "bwnfsd: [%sshare] Can't reply to RPC call\n", rqstp->rq_proc==SHARE?"":"un");
  2333.         return;
  2334.     case ZAP_LOCKS:
  2335.     case LOCK:
  2336.         lock.stat = svc_getargs(transp,xdr_lock,&lock);
  2337.         goto check_lock;
  2338.     case UNLOCK:
  2339.         lock.stat = svc_getargs(transp,xdr_unlock,&lock);
  2340.      check_lock:
  2341.         if (!lock.stat)
  2342.             if (!svc_getargs(transp,xdr_lock,&lock)) {
  2343.                 if (debugmode)
  2344.                     fprintf(stdout, "bwnfsd: [%slock] svc_getargs request failed\n", rqstp->rq_proc==LOCK?"":"un");
  2345.                 svcerr_decode(transp);
  2346.                 return;
  2347.             }
  2348.         lock.stat = !process_lock_request((int) rqstp->rq_proc,lock.name,lock.fh,
  2349.                      lock.access,lock.mode,lock.offset,lock.length,lock.cookie,lock.lockowner);
  2350.         if (debugmode)
  2351.             if (lock.stat)
  2352.                 fprintf(stdout, "bwnfsd: [%slock] lock status = false\n", rqstp->rq_proc==LOCK?"":rqstp->rq_proc==UNLOCK?"un":"zap");
  2353.             else
  2354.                 fprintf(stdout, "bwnfsd: [%slock] lock status = true\n", rqstp->rq_proc==LOCK?"":rqstp->rq_proc==UNLOCK?"un":"zap");
  2355.         if (!svc_sendreply(transp,xdr_res,&lock))
  2356.             if (debugmode)
  2357.                 fprintf(stdout, "bwnfsd: [%slock] Can't reply to RPC call\n", rqstp->rq_proc==LOCK?"":rqstp->rq_proc==UNLOCK?"un":"zap");
  2358.         return;
  2359.     case GET_PRINTERS:
  2360.         if (!svc_sendreply(transp, xdr_printers, NULL))
  2361.             if (debugmode)
  2362.                 fprintf(stdout, "bwnfsd: [get_printers] Can't reply to RPC call\n");
  2363.         return;
  2364.     case GET_PRINTQ:
  2365.         if (!svc_getargs(transp,xdr_get_printq,&printq)) {
  2366.             if (debugmode)
  2367.                 fprintf(stdout, "bwnfsd: [get_printq] svc_getargs failed\n");
  2368.             svcerr_decode(transp);
  2369.             return;
  2370.         }
  2371.         printq.printer_number = -1;
  2372.         for (i=0; i<num_printers; i++)
  2373.             if (strcmp(printers[i].queuename,printq.queuename) == 0) {
  2374.                 if (time(NULL) > (printers[i].lasttime+POLL_INTERVAL))
  2375.                     add_entries(i);
  2376.                 printq.printer_number = i;
  2377.                 break;
  2378.             }
  2379.         if (!svc_sendreply(transp,xdr_send_printq,&printq))
  2380.             if (debugmode)
  2381.                 fprintf(stdout, "bwnfsd: [get_printq] Can't reply to RPC call\n");
  2382.         return;
  2383.     case CANCEL_PRJOB:
  2384.         if (!svc_getargs(transp,xdr_cancel_job,&printq)) {
  2385.             if (debugmode)
  2386.                 fprintf(stdout, "bwnfsd: [cancel_prjob] svc_getargs failed\n");
  2387.             svcerr_decode(transp);
  2388.             return;
  2389.         }
  2390.         j = WN_BAD_QUEUE;
  2391.         for (i=0; i<num_printers; i++)
  2392.             if (strcmp(printers[i].queuename,printq.queuename) == 0) {
  2393.                 for (j=0; j<MAX_NUM_CANCEL_CACHE; j++)
  2394.                     if ((cancache[j].jobid == printq.printer_number) &&
  2395.                         (strcmp(cancache[j].username, printq.username) == 0) &&
  2396.                         (strcmp(cancache[j].queuename, printq.queuename) == 0)) {
  2397.                         j = cancache[j].response;
  2398.                         goto no_bloody_boolean_handy;
  2399.                     }
  2400.                 if ((j=cancel_printjob(i, printq.username, printq.printer_number)) == WN_SUCCESS)
  2401.                     printers[i].lasttime = 0L;
  2402.                 cancache[current_cache].jobid = printq.printer_number;
  2403.                 strcpy(cancache[current_cache].queuename, printq.queuename);
  2404.                 strcpy(cancache[current_cache].username, printq.username);
  2405.                 cancache[current_cache].response = j;
  2406.                 current_cache = ++current_cache%MAX_NUM_CANCEL_CACHE;
  2407.                 break;
  2408.             }
  2409. no_bloody_boolean_handy:
  2410.         if (!svc_sendreply(transp,xdr_int,&j))
  2411.             if (debugmode)
  2412.                 fprintf(stdout, "bwnfsd: [cancel_prjob] Can't reply to RPC call\n");
  2413.         return;
  2414.     default:
  2415.         svcerr_noproc(transp);
  2416.         return;
  2417.     }
  2418. }
  2419.  
  2420. static struct fhstatus {
  2421.     int status;
  2422.     char dir[32];
  2423. } mount_return;
  2424.  
  2425. /*
  2426.  *     Response from rpc.mountd for mount request of SPOOL directory.
  2427.  */
  2428. int
  2429. xdr_fhstatus(xdrsp, fhstat)
  2430.     XDR *xdrsp;
  2431.     struct fhstatus *fhstat;
  2432. {
  2433. int i;
  2434.  
  2435.     if (debugmode)
  2436.         fprintf(stdout, "bwnfsd: [xdr_fhstatus] called\n");
  2437.     if (!xdr_int(xdrsp, &fhstat->status))
  2438.         return(0);
  2439.     if (fhstat->status == 0)
  2440.         for (i=0; i<32 ; i+=4)
  2441.             if (!xdr_int(xdrsp, &(fhstat->dir[0])+i))
  2442.                 return(0);
  2443.     if (debugmode > 1)
  2444.         fprintf(stdout, "bwnfsd: [xdr_fhstatus] returns (1)\n");
  2445.     return(1);
  2446. }
  2447.  
  2448. static struct text_string {
  2449.     int length;
  2450.     char *dir;
  2451. } request_text;
  2452.  
  2453. /*
  2454.  *     Request to mount SPOOL directory.
  2455.  */
  2456. int
  2457. xdr_text(xdrsp, req)
  2458.     XDR *xdrsp;
  2459.     struct text_string *req;
  2460. {
  2461.     if (debugmode)
  2462.         fprintf(stdout, "bwnfsd: [xdr_text] mount request for %s\n", req->dir);
  2463.     if (!xdr_bytes(xdrsp, &req->dir, &req->length,255))
  2464.         return(0);
  2465.     if (debugmode > 1)
  2466.         fprintf(stdout, "bwnfsd: [xdr_text] returns (1)\n");
  2467.     return(1);
  2468. }
  2469.  
  2470.  
  2471. /*
  2472.  *     Use rpc.mountd to determine the fhandle of the spool directory,
  2473.  *     Can be replaced with extracted code from rpc.mountd.
  2474.  */
  2475. int get_mount(dir,directory)
  2476.     char *dir,*directory;
  2477. {
  2478. struct hostent *hp;
  2479. struct timeval pentry_timeout, total_timeout;
  2480. struct sockaddr_in server_addr;
  2481. int sock= RPC_ANYSOCK;
  2482. register CLIENT *client;
  2483. enum clnt_stat clnt_stat;
  2484.  
  2485.     if (debugmode)
  2486.         fprintf(stdout, "bwnfsd: [get_mount] called\n");
  2487.     if (debugmode > 1)
  2488.         fprintf(stdout, "bwnfsd: [get_mount] dir = \"%s\", directory = \"%s\"\n", dir, directory);
  2489.     request_text.length = strlen(directory);
  2490.     request_text.dir    = directory;
  2491.     if ((hp=gethostbyname(hostname)) == NULL) {
  2492.         fprintf(stdout, "bwnfsd: [get_mount] \"%s\" is not in the /etc/hosts file.\n", hostname);
  2493.         fprintf(stdout, "bwnfsd:             please enter it and re-run.\n");
  2494.         fflush(stdout);
  2495.         exit(-1);
  2496.     }
  2497.     pentry_timeout.tv_sec  = 3;
  2498.     pentry_timeout.tv_usec = 0;
  2499.     memcpy((caddr_t) &server_addr.sin_addr, hp->h_addr, hp->h_length);
  2500.     server_addr.sin_family = AF_INET;
  2501.     server_addr.sin_port   = 0;
  2502.     if ((client=(CLIENT *)clntudp_create(&server_addr, 100005L, 1L,pentry_timeout, &sock)) == NULL) {
  2503.         fprintf(stdout, "bwnfsd: [get_mount] clntupd_create failed\n");
  2504.         clnt_pcreateerror("clntudp_create");
  2505.         fflush(stdout);
  2506.         exit(-1);
  2507.     }
  2508.     if (bindresvport(sock, (struct sockaddr_in *) NULL))
  2509.         if (debugmode)
  2510.             fprintf(stdout, "bwnfsd: [get_mount] cannot allocate reserved port ... not critical.\n");
  2511.     client->cl_auth       = authunix_create_default();
  2512.     total_timeout.tv_sec  = 20;
  2513.     total_timeout.tv_usec = 0;
  2514.     clnt_stat          = clnt_call(client, 1L, xdr_text, &request_text,
  2515.                        xdr_fhstatus, &mount_return,
  2516.                        total_timeout);
  2517.     if (clnt_stat != RPC_SUCCESS) {
  2518.         fprintf(stdout, "bwnfsd: [get_mount] clnt_stat failed\n");
  2519.         clnt_perror(client,"rpc");
  2520.         fflush(stdout);
  2521.         exit(-1);
  2522.     }
  2523.     auth_destroy(client->cl_auth);
  2524.     clnt_destroy(client);
  2525.     if (mount_return.status == 0L)
  2526.         memcpy(dir, &mount_return.dir[0], 32);
  2527.     if (debugmode)
  2528.         fprintf(stdout, "bwnfsd: [get_mount] returns mount status %u\n",mount_return.status);
  2529.     return(mount_return.status);
  2530. }
  2531.  
  2532.  
  2533. /*
  2534.  *     Daemon should be killed with a simple KILL and not KILL -9 so
  2535.  *     that it may unmap itself
  2536.  */
  2537. Void
  2538. die(unused)
  2539.     int unused;
  2540. {
  2541.     fprintf(stdout, "bwnfsd: [die] Daemon is dying\n\n");
  2542.     fflush(stdout);
  2543.     (void) pmap_unset(BW_NFS_PROGRAM, BW_NFS_VERSION);
  2544.     exit(1);
  2545. }
  2546.  
  2547. void
  2548. ErrAndDie(fmt, str1, str2)
  2549.     char *fmt, *str1, *str2;
  2550. {
  2551.     fprintf(stdout, fmt, str1, str2);
  2552.     fflush(stdout);
  2553.     exit(-1);
  2554. }
  2555.  
  2556. int
  2557. main(argc,argv)
  2558.     int argc;
  2559.     char **argv;
  2560. {
  2561. SVCXPRT *transp;
  2562. char *p,*prog;
  2563. int i, child_pid;
  2564. struct hostent *hp;
  2565.  
  2566. #ifdef SCO
  2567.     set_auth_parameters(argc, argv);
  2568.     setluid(0);
  2569. #endif
  2570.  
  2571.     fprintf(stdout, "BWNFSD Authentication Daemon Vsn %s starting\n\n", VERSION);
  2572.     prog = argv[0];
  2573.     debugmode = 0;
  2574.     argc--;
  2575.     argv++;
  2576.  
  2577. another:
  2578.     if ((argc > 0) && (strcmp(*argv,"-A") == 0)) {
  2579.         argc--;
  2580.         argv++;
  2581.         A_flag=1;
  2582.         goto another;
  2583.     }
  2584.  
  2585.     if ((argc > 0) && (strcmp(*argv,"-d") == 0)) {
  2586.         argc--;
  2587.         argv++;
  2588.         debugmode++;
  2589.         goto another;
  2590.     }
  2591.  
  2592.     if ((argc > 0) && (strcmp(*argv,"-s") == 0)) {
  2593.         argc--;
  2594.         argv++;
  2595.         if (argc < 2)
  2596.             ErrAndDie("usage: %s [-A] [-d] [-s file] spool_area_mount_point\n", prog, NULL);
  2597.         read_ips(*argv);
  2598.         s_flag = 1;
  2599.         argc--;
  2600.         argv++;
  2601.         goto another;
  2602.     }
  2603.     if (argc != 1)
  2604.         ErrAndDie("usage: %s [-A] [-d] [-s file] spool_area_mount_point\n", prog, NULL);
  2605.  
  2606.     init_locks();
  2607.     hostname = (char *) malloc(255);
  2608.     (void) gethostname(hostname,255);
  2609.     if ((hp=gethostbyname(hostname)) == NULL)
  2610.         ErrAndDie("bwnfsd: host \"%s\" is not in the /etc/hosts file\nbwnfsd: Please add it to the file and restart %s\n", hostname, prog);
  2611.     memcpy((caddr_t) &my_ip, hp->h_addr, hp->h_length);
  2612.     if (get_mount(dir,*argv) != 0)
  2613.         ErrAndDie("bwnfsd: Spool area mount point %s could not be mounted.\nbwnfsd: Check that %s is in the /etc/exports file & world-writable\n", *argv, *argv);
  2614.  
  2615.     if (!debugmode) {
  2616. #ifdef SIGTTOU
  2617.         signal(SIGTTOU, SIG_IGN);
  2618. #endif
  2619. #ifdef SIGTTIN
  2620.         signal(SIGTTIN, SIG_IGN);
  2621. #endif
  2622. #ifdef SIGTSTP
  2623.         signal(SIGTSTP, SIG_IGN);
  2624. #endif
  2625.         if ((child_pid=fork()) > 0)
  2626.             exit(0);
  2627.         if (child_pid < 0)
  2628.             ErrAndDie("bwnfsd: Unable to detach process\n", NULL, NULL);
  2629.         if (setpgrp(0, 0) == -1)
  2630.             ErrAndDie("bwnfsd: [main] Can't change process group\n", NULL, NULL);
  2631. #ifdef SIGTSTP
  2632. #ifdef TIOCNOTTY
  2633.         if ((i=open("/dev/tty", O_RDWR)) >= 0) {
  2634.            ioctl(i, TIOCNOTTY, NULL);
  2635.            close(i);
  2636.         }
  2637. #endif
  2638. #else
  2639.         signal(SIGHUP, SIG_IGN);
  2640.         if ((child_pid=fork()) > 0)
  2641.             exit(0);
  2642.         if (child_pid < 0)
  2643.             ErrAndDie("bwnfsd: [main] Unable to detach second process\n", NULL, NULL);
  2644. #endif
  2645. #ifndef NOFILE
  2646. #define NOFILE 10
  2647. #endif
  2648.         for (i=0; i<NOFILE; i++)
  2649.             close(i);
  2650.         errno = 0;
  2651.         chdir("/");
  2652.         umask(0);
  2653.  
  2654.         if ((i=open("/dev/null", O_RDWR)) < 0)
  2655.             ErrAndDie("bwnfsd: [main] Unable to map handles\n", NULL, NULL);
  2656.         dup2(i, 4);
  2657.         close(i);
  2658.         dup2(4, 0);
  2659.         dup2(4, 1);
  2660.         dup2(4, 2);
  2661.         close(4);
  2662.     }
  2663.  
  2664.     if (determine_print_command() == 0)
  2665.         ErrAndDie("bwnfsd: [main] Unable to determine print command\n", NULL, NULL);
  2666.     p = strcpy(spool_dir,*argv) + strlen(*argv);
  2667.     if (*(p-1) == '/')
  2668.         *(--p) = '\0';
  2669.     get_printers();
  2670.     get_groups();
  2671.     f.status     = 0;
  2672.     f.dir_size   = 32;
  2673.     f.dir_handle = dir;
  2674.  
  2675.     transp = (SVCXPRT *)svcudp_create(RPC_ANYSOCK);
  2676.     if (transp == NULL)
  2677.         ErrAndDie("bwnfsd: [main] Unable to create an RPC server\n", NULL, NULL);
  2678.     (void) pmap_unset(BW_NFS_PROGRAM, BW_NFS_VERSION);
  2679.     if (!svc_register(transp,BW_NFS_PROGRAM, BW_NFS_VERSION,create_spool, IPPROTO_UDP))
  2680.         ErrAndDie("bwnfsd: [main] Can't register BWNFSD service\n", NULL, NULL);
  2681.     (void) signal(SIGHUP, clear);
  2682.     (void) signal(SIGINT, die);
  2683.     (void) signal(SIGQUIT, die);
  2684. #ifdef SIGABRT
  2685.     (void) signal(SIGABRT, die);
  2686. #endif
  2687.     (void) signal(SIGTERM, die);
  2688. #ifdef SIGCHLD
  2689.     (void) signal(SIGCHLD, free_child);
  2690. #endif
  2691. #ifdef SIGCLD
  2692. #ifndef SIGTSTP
  2693.     (void) signal(SIGCLD, SIG_IGN);
  2694. #else
  2695.     (void) signal(SIGCLD, free_child);
  2696. #endif
  2697. #endif
  2698.     svc_run();
  2699.     fprintf(stdout, "bwnfsd: [main] svc_run returned!\n");
  2700.     fflush(stdout);
  2701.     exit(1);
  2702.     return(1); /* for the compulsive compilers */
  2703. }
  2704.