home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / contrib / samba / samba-1.8 / samba-1 / samba-1.8.05 / server.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-27  |  82.4 KB  |  3,225 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.8.
  4.    Copyright (C) Andrew Tridgell 1992,1993,1994
  5.    
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.    
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.    
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20.  
  21. #include "includes.h"
  22. #include "loadparm.h"
  23. #include "pcap.h"
  24. #include "trans2.h"
  25. #include "reply.h"
  26.  
  27. pstring OriginalDir ="/";
  28. pstring servicesf = SERVICES;
  29. extern pstring debugf;
  30.  
  31. BOOL append_log = True;
  32.  
  33. char *InBuffer = NULL;
  34. char *OutBuffer = NULL;
  35.  
  36. int initial_uid = 0;
  37. int initial_gid = 0;
  38.  
  39. /* have I done a become_user? */
  40. int done_become_user = -1;
  41.  
  42. /* the last message the was processed */
  43. int last_message = -1;
  44.  
  45. /* does getgroups return ints or gid_t ?? */
  46. BOOL groups_use_ints = True;
  47.  
  48. /* a useful macro to debug the last message processed */
  49. #define LAST_MESSAGE() smb_fn_name(last_message)
  50.  
  51. extern BOOL NeedSwap;
  52. extern pstring scope;
  53. extern int DEBUGLEVEL;
  54. extern char magic_char;
  55.  
  56. connection_struct Connections[MAX_CONNECTIONS];
  57. files_struct Files[MAX_OPEN_FILES];
  58.  
  59. /* local prototype */
  60. static char *build_print_command(int snum, char *command, char *syscmd, char *filename);
  61.  
  62. extern int Protocol;
  63.  
  64. int maxxmit = BUFFER_SIZE;
  65.  
  66. int chain_size = 0;
  67.  
  68. /* a fnum to use when chaining */
  69. int chain_fnum = -1;
  70.  
  71. /* total number of open files */
  72. int num_files_open = 0;
  73.  
  74. /* this structure is used to hold information about the machine that 
  75.    the program is running on */
  76. extern machine_struct machine_info;
  77.  
  78. /* booleans from smb_flg2 when PROTOCOL >= LANMAN2 */
  79. BOOL long_filenames = False;
  80. extern BOOL casesignames;
  81.  
  82. fstring remote_machine="";
  83.  
  84.  
  85. /* these can be set by some functions to override the error codes */
  86. int unix_ERR_class=SUCCESS;
  87. int unix_ERR_code=0;
  88.  
  89.  
  90. extern int extra_time_offset;
  91.  
  92. pstring myhostname="";
  93. extern struct in_addr myip;
  94.  
  95.  
  96. /****************************************************************************
  97.   change a dos mode to a unix mode
  98. ****************************************************************************/
  99. mode_t unix_mode(int cnum,int dosmode)
  100. {
  101.   mode_t result = 0444;
  102.   
  103.   if ((dosmode & aRONLY) == 0)
  104.     result |= (S_IWUSR | S_IWGRP | S_IWOTH);
  105.  
  106.   if ((dosmode & aDIR) != 0)
  107.     result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH);
  108.  
  109.   if ((dosmode & aARCH) != 0)
  110.     result |= S_IXUSR;
  111.  
  112.   if (MAP_SYSTEM(cnum) && ((dosmode & aSYSTEM) != 0))
  113.     result |= S_IXGRP;
  114.  
  115.   if (MAP_HIDDEN(cnum) && ((dosmode & aHIDDEN) != 0))
  116.     result |= S_IXOTH;  
  117.  
  118.   result &= CREATE_MODE(cnum);
  119.   return(result);
  120. }
  121.  
  122.  
  123. /****************************************************************************
  124.   change a unix mode to a dos mode
  125. ****************************************************************************/
  126. int dos_mode(int cnum,char *path,struct stat *sbuf)
  127. {
  128.   int result = 0;
  129.  
  130.   if (!CAN_WRITE(cnum))
  131.     result |= aRONLY;
  132.   else
  133.   if (!((sbuf->st_mode & S_IWOTH) ||
  134.       ((sbuf->st_mode & S_IWUSR) && Connections[cnum].uid == sbuf->st_uid) ||
  135.       ((sbuf->st_mode & S_IWGRP) && 
  136.        in_group(sbuf->st_gid,Connections[cnum].gid,
  137.         Connections[cnum].ngroups,Connections[cnum].igroups))))
  138.     result |= aRONLY;
  139.  
  140.   if ((sbuf->st_mode & S_IXUSR) != 0)
  141.     result |= aARCH;
  142.  
  143.   if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
  144.     result |= aSYSTEM;
  145.  
  146.   if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
  147.     result |= aHIDDEN;   
  148.   
  149.   if (S_ISDIR(sbuf->st_mode))
  150.     result = aDIR;
  151.  
  152.   /* hide files with a name starting with a . */
  153.   if (lp_hide_dot_files(SNUM(cnum)))
  154.     {
  155.       char *p = strrchr(path,'/');
  156.       if (p)
  157.     p++;
  158.       else
  159.     p = path;
  160.       
  161.       if (p[0] == '.' && p[1] != '.' && p[1] != 0)
  162.     result |= aHIDDEN;
  163.     }
  164.  
  165.   return(result);
  166. }
  167.  
  168.  
  169. struct dptr_struct
  170. {
  171.   int key;
  172.   int pid;
  173.   void *ptr;
  174.   BOOL valid;
  175.   BOOL expect_close;
  176.   char *wcard; /* Field only used for lanman2 trans2_findfirst/next searches */
  177.   uint16 attr; /* Field only used for lanman2 trans2_findfirst/next searches */
  178.   pstring path;
  179. }
  180. dirptrs[MAXDIR];
  181.  
  182. BOOL dptrs_init=False;
  183. int next_key = 1;
  184.  
  185. /****************************************************************************
  186. convert a filename to a unix filename from dos
  187. ****************************************************************************/
  188. void unix_convert(char *name,int cnum)
  189. {
  190.   if(long_filenames)
  191.     unix_convert_lanman2(name,HOME(cnum),casesignames);
  192.   else
  193.     unix_convert_83(name,HOME(cnum),lp_manglednames(SNUM(cnum)), lp_mangled_map(SNUM(cnum)));
  194. }
  195.  
  196. /****************************************************************************
  197. check a filename - possibly caling reducename
  198. ****************************************************************************/
  199. BOOL check_name(char *name,int cnum)
  200. {
  201.   BOOL ret;
  202.  
  203.   if (Connections[cnum].printer && strstr(name,"dev/"))
  204.     {
  205.       fstring name2;
  206.       sprintf(name2,"%s.XXXXXX",remote_machine);
  207.       strcpy(name,(char *)mktemp(name2));
  208.       return(True);
  209.     }
  210.  
  211.   ret = reduce_name(name,HOME(cnum),lp_widelinks(SNUM(cnum)));
  212.   if (!ret)
  213.     DEBUG(5,("check_name on %s failed\n",name));
  214.  
  215.   return(ret);
  216. }
  217.  
  218. /****************************************************************************
  219. check a filename - possibly caling reducename
  220. ****************************************************************************/
  221. void check_for_pipe(char *fname)
  222. {
  223.   /* special case of pipe opens */
  224.   char s[10];
  225.   StrnCpy(s,fname,9);
  226.   strlower(s);
  227.   if (strstr(s,"pipe/"))
  228.     {
  229.       DEBUG(3,("Rejecting named pipe open for %s\n",fname));
  230.       unix_ERR_class = ERRSRV;
  231.       unix_ERR_code = ERRaccess;
  232.     }
  233. }
  234.  
  235.  
  236. /****************************************************************************
  237. open a file
  238. ****************************************************************************/
  239. void open_file(int fnum,int cnum,char *fname1,int flags,int mode)
  240. {
  241.   fstring fname;
  242.  
  243.   Files[fnum].open = False;
  244.   Files[fnum].fd = -1;
  245.   errno = EPERM;
  246.  
  247.   strcpy(fname,fname1);
  248.  
  249.   /* check permissions */
  250.   if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
  251.     {
  252.       DEBUG(3,("Permission denied opening %s\n",fname));
  253.       check_for_pipe(fname);
  254.       return;
  255.     }
  256.  
  257.   /* new files with no casesignames get created with the default case */
  258.   if (Protocol >= PROTOCOL_LANMAN2 && !casesignames && (flags & O_CREAT) &&
  259.       !file_exist(fname))
  260.     {
  261.       char *p = strrchr(fname,'/');
  262.       if(!p) p = fname;
  263.       if (lp_defaultcase(cnum) == CASE_UPPER)
  264.     strupper(p);
  265.       else
  266.     strlower(p);
  267.     }
  268.  
  269.   Files[fnum].fd = open(fname,flags,mode);
  270.  
  271.   /* Fix for files ending in '.' */
  272.   if((Files[fnum].fd == -1) && (errno == ENOENT) && 
  273.      (strchr(fname,'.')==NULL))
  274.     {
  275.       strcat(fname,".");
  276.       Files[fnum].fd = open(fname,flags,mode);
  277.     }
  278.  
  279.   if (Files[fnum].fd < 0)
  280.     {
  281.       DEBUG(3,("Error opening file %s (%s)\n",fname,strerror(errno)));
  282.       check_for_pipe(fname);
  283.       return;
  284.     }
  285.  
  286.   if (Files[fnum].fd >= 0)
  287.     {
  288.       num_files_open++;
  289.       Files[fnum].pos = -1;
  290.       Files[fnum].open = True;
  291.       Files[fnum].mmap_ptr = NULL;
  292.       Files[fnum].mmap_size = 0;
  293.       Files[fnum].can_lock = True;
  294.       Files[fnum].read_only = (flags == O_RDONLY);
  295.       Files[fnum].print_file = Connections[cnum].printer;
  296.       Files[fnum].cnum = cnum;
  297.       strcpy(Files[fnum].name,fname);
  298.       Files[fnum].wbmpx_ptr = NULL;      
  299.  
  300.       /*
  301.        * If the printer is marked as postscript output a leading
  302.        * file identifier to ensure the file is treated as a raw
  303.        * postscript file.
  304.        * This has a similar effect as CtrlD=0 in WIN.INI file.
  305.        * tim@fsg.com 09/06/94
  306.        */
  307.       if (Files[fnum].print_file && POSTSCRIPT(cnum) && 
  308.       !Files[fnum].read_only) 
  309.     {
  310.       DEBUG(3,("Writing postscript line\n"));
  311.       write(Files[fnum].fd,"%!\n",3);
  312.     }
  313.     }
  314.  
  315. #if USE_MMAP
  316.   /* mmap it if read-only */
  317.   if (Files[fnum].read_only)
  318.     {
  319.       Files[fnum].mmap_size = file_size(fname);
  320.       Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
  321.                       PROT_READ,MAP_SHARED,Files[fnum].fd,0);
  322.  
  323.       if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
  324.     {
  325.       DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
  326.       Files[fnum].mmap_ptr = NULL;
  327.     }
  328.     }
  329. #endif
  330. }
  331.  
  332. /****************************************************************************
  333. close a file - possibly invalidating the read prediction
  334. ****************************************************************************/
  335. void close_file(int fnum)
  336. {
  337.   invalidate_read_prediction(Files[fnum].fd);
  338.   Files[fnum].open = False;
  339.   num_files_open--;
  340.   if(Files[fnum].wbmpx_ptr) 
  341.     {
  342.       free((char *)Files[fnum].wbmpx_ptr);
  343.       Files[fnum].wbmpx_ptr = NULL;
  344.     }
  345.  
  346. #if USE_MMAP
  347.   if(Files[fnum].mmap_ptr) 
  348.     {
  349.       munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size);
  350.       Files[fnum].mmap_ptr = NULL;
  351.     }
  352. #endif
  353.  
  354.   close(Files[fnum].fd);
  355.  
  356.   /* NT uses smbclose to start a print - weird */
  357.   if (Files[fnum].print_file)
  358.     print_file(fnum);
  359.  
  360.   /* check for magic scripts */
  361.   check_magic(fnum,Files[fnum].cnum);
  362. }
  363.  
  364. /****************************************************************************
  365. seek a file. Try to avoid the seek if possible
  366. ****************************************************************************/
  367. int seek_file(int fnum,int pos)
  368. {
  369.   int offset = 0;
  370. #if 0
  371.   if (Files[fnum].pos == pos)
  372.     return(pos);
  373. #endif
  374.   if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
  375.     offset = 3;
  376.  
  377.   Files[fnum].pos = lseek(Files[fnum].fd,pos+offset,SEEK_SET) - offset;
  378.   return(Files[fnum].pos);
  379. }
  380.  
  381. /****************************************************************************
  382. read from a file
  383. ****************************************************************************/
  384. int read_file(int fnum,char *data,int pos,int mincnt,int maxcnt,int timeout,BOOL exact)
  385. {
  386.   int ret=0;
  387.  
  388.   if (Files[fnum].read_only)
  389.     {
  390.       ret = read_predict(Files[fnum].fd,
  391.              pos,
  392.              data,
  393.              maxcnt);
  394.  
  395.       data += ret;
  396.       maxcnt -= ret;
  397.       mincnt = MAX(mincnt-ret,0);
  398.       pos += ret;
  399.     }
  400.  
  401. #if USE_MMAP
  402.   if (Files[fnum].mmap_ptr)
  403.     {
  404.       int num = MIN(maxcnt,Files[fnum].mmap_size-pos);
  405.       if (num > 0)
  406.     {
  407.       memcpy(data,Files[fnum].mmap_ptr+pos,num);
  408.       data += num;
  409.       pos += num;
  410.       maxcnt -= num;
  411.       mincnt = MAX(mincnt-num,0);
  412.       ret += num;
  413.     }
  414.     }
  415. #endif
  416.  
  417.   if (maxcnt <= 0)
  418.     return(ret);
  419.  
  420.   if (seek_file(fnum,pos) != pos)
  421.     {
  422.       DEBUG(3,("Failed to seek to %d\n",pos));
  423.       return(ret);
  424.     }
  425.   
  426.   if (maxcnt > 0)
  427.     ret += read_with_timeout(Files[fnum].fd,
  428.                  data,
  429.                  mincnt,
  430.                  maxcnt,
  431.                  timeout,
  432.                  exact);
  433.  
  434.   return(ret);
  435. }
  436.  
  437.  
  438. /****************************************************************************
  439. initialise the dir array
  440. ****************************************************************************/
  441. void init_dptrs(void)
  442. {
  443.   int i;
  444.   if (dptrs_init) return;
  445.   for (i=0;i<MAXDIR;i++)    
  446.     dirptrs[i].valid = False;
  447.   dptrs_init = True;
  448. }
  449.  
  450. /****************************************************************************
  451. get the dir ptr for a dir index
  452. ****************************************************************************/
  453. void *dptr_get(int key)
  454. {
  455.   int i;
  456.   for (i=0;i<MAXDIR;i++)
  457.     if (dirptrs[i].valid && dirptrs[i].key == key)
  458.       return(dirptrs[i].ptr);
  459.   return(NULL);
  460. }
  461.  
  462. /****************************************************************************
  463. get the dir path for a dir index
  464. ****************************************************************************/
  465. char *dptr_path(int key)
  466. {
  467.   int i;
  468.   for (i=0;i<MAXDIR;i++)
  469.     if (dirptrs[i].valid && dirptrs[i].key == key)
  470.       return(dirptrs[i].path);
  471.   return(NULL);
  472. }
  473.  
  474. /****************************************************************************
  475. get the dir wcard for a dir index (lanman2 specific)
  476. ****************************************************************************/
  477. char *dptr_wcard(int key)
  478. {
  479.   int i;
  480.   for (i=0;i<MAXDIR;i++)
  481.     if (dirptrs[i].valid && dirptrs[i].key == key)
  482.       return(dirptrs[i].wcard);
  483.   return(NULL);
  484. }
  485.  
  486. /****************************************************************************
  487. set the dir wcard for a dir index (lanman2 specific)
  488. Returns 0 on ok, 1 on fail.
  489. ****************************************************************************/
  490. int dptr_set_wcard(int key, char *wcard)
  491. {
  492.   int i;
  493.   for (i=0;i<MAXDIR;i++)
  494.     if (dirptrs[i].valid && dirptrs[i].key == key)
  495.       {
  496.     dirptrs[i].wcard = wcard;
  497.     return 0;
  498.       }
  499.   return 1;
  500. }
  501.  
  502. /****************************************************************************
  503. set the dir attrib for a dir index (lanman2 specific)
  504. Returns 0 on ok, 1 on fail.
  505. ****************************************************************************/
  506. int dptr_set_attr(int key, uint16 attr)
  507. {
  508.   int i;
  509.   for (i=0;i<MAXDIR;i++)
  510.     if (dirptrs[i].valid && dirptrs[i].key == key)
  511.       {
  512.     dirptrs[i].attr = attr;
  513.     return 0;
  514.       }
  515.   return 1;
  516. }
  517.  
  518. /****************************************************************************
  519. get the dir attrib for a dir index (lanman2 specific)
  520. ****************************************************************************/
  521. uint16 dptr_attr(int key)
  522. {
  523.   int i;
  524.   for (i=0;i<MAXDIR;i++)
  525.     if (dirptrs[i].valid && dirptrs[i].key == key)
  526.       return(dirptrs[i].attr);
  527.   return(0);
  528. }
  529.  
  530.  
  531. /****************************************************************************
  532. check a key
  533. ****************************************************************************/
  534. BOOL key_ok(int key)
  535. {
  536.   int i;
  537.   for (i=0;i<MAXDIR;i++)
  538.     if (dirptrs[i].valid && dirptrs[i].key == key)
  539.       return(True);
  540.   return(False);
  541. }
  542.  
  543. /****************************************************************************
  544. prompte a dptr (to make it recently used)
  545. ****************************************************************************/
  546. void dptr_promote(int key)
  547. {
  548.   int i;
  549.   for (i=0;i<MAXDIR;i++)
  550.     if (dirptrs[i].valid && dirptrs[i].key == key)
  551.       {
  552.     struct dptr_struct d;
  553.     int j;
  554.     d = dirptrs[i];
  555.     for (j=i;j>0;j--)
  556.       dirptrs[j] = dirptrs[j-1];
  557.     dirptrs[0] = d;
  558.     return;
  559.       }
  560. }
  561.  
  562.  
  563. /****************************************************************************
  564. demote a dptr (to make it likely to get closed)
  565. ****************************************************************************/
  566. void dptr_demote(int key)
  567. {
  568.   int i;
  569.   for (i=0;i<MAXDIR;i++)
  570.     if (dirptrs[i].valid && dirptrs[i].key == key)
  571.       {
  572.     struct dptr_struct d;
  573.     int j;
  574.     d = dirptrs[i];
  575.     for (j=i;j<(MAXDIR-1) && dirptrs[j].valid;j++)
  576.       dirptrs[j] = dirptrs[j+1];
  577.     dirptrs[j] = d;
  578.     return;
  579.       }
  580. }
  581.  
  582.  
  583. /****************************************************************************
  584. find a free key
  585. ****************************************************************************/
  586. int find_key(int start)
  587. {
  588.   int key;
  589.  
  590.   for (key=start;key<256;key++)
  591.     if (!key_ok(key))
  592.       return(key);
  593.  
  594.   for (key=1;key<start;key++)
  595.     if (!key_ok(key))
  596.       return(key);
  597.  
  598.   DEBUG(0,("ERROR: Out of dirptr keys!\n"));
  599.   return 1;
  600. }       
  601.   
  602.  
  603. /****************************************************************************
  604. close a dptr
  605. ****************************************************************************/
  606. void dptr_close(int key)
  607. {
  608.   int i;
  609.   for (i=0;i<MAXDIR;i++)
  610.     if (dirptrs[i].valid && dirptrs[i].key == key)
  611.       {
  612.     if (dirptrs[i].ptr)
  613.       closedir(dirptrs[i].ptr);
  614.     /* Lanman 2 specific code */
  615.     if (dirptrs[i].wcard)
  616.       free(dirptrs[i].wcard);
  617.     dirptrs[i].valid = False;
  618.     next_key = key+1;
  619.     if (next_key > 255) next_key = 1;
  620.     return;
  621.       }
  622. }
  623.  
  624. /****************************************************************************
  625. close a dptr that matches a given path, only if it matches the pid also
  626. ****************************************************************************/
  627. void dptr_closepath(char *path,int pid)
  628. {
  629.   int i;
  630.   for (i=0;i<MAXDIR;i++)
  631.     if (dirptrs[i].valid && pid == dirptrs[i].pid)
  632.       {      
  633.     DEBUG(5,("closepath [%s] [%s]\n",path,dirptrs[i].path));
  634.     if (strequal(dirptrs[i].path,path))
  635.       {
  636.         if (dirptrs[i].ptr)
  637.           closedir(dirptrs[i].ptr);
  638.         if (dirptrs[i].wcard)
  639.           free(dirptrs[i].wcard);
  640.         dirptrs[i].valid = False;
  641.         next_key = dirptrs[i].key+1;
  642.         if (next_key > 255) next_key = 1;
  643.       }
  644.       }
  645. }
  646.  
  647. /****************************************************************************
  648. create a new dir ptr
  649. ****************************************************************************/
  650. int dptr_create(void *p,char *path, BOOL expect_close,int pid)
  651. {
  652.   int i,key;
  653.  
  654.   for (i=0;i<MAXDIR;i++)
  655.     if (!dirptrs[i].valid)
  656.       break;
  657.  
  658.   /* as a second option, grab one not marked for expect_close */
  659.   if (i == MAXDIR)
  660.     for (i=MAXDIR-1;i>=0;i--)
  661.       if (!dirptrs[i].expect_close)
  662.     {
  663.       dptr_close(dirptrs[i].key);    
  664.       break;
  665.     }
  666.  
  667.   if (i < 0)
  668.     {
  669.       /* All dirptrs are used by uncloseable SMBffirsts */
  670.       DEBUG(0,("Error - all dirptrs in use by SMBffirsts.\n"));
  671.       return(-1);
  672.     }
  673.  
  674.   dirptrs[i].ptr = p;
  675.   strcpy(dirptrs[i].path,path);
  676.   key = find_key(next_key);
  677.   dirptrs[i].key = key;
  678.   dirptrs[i].valid = True;
  679.   dirptrs[i].pid = pid;
  680.   dirptrs[i].expect_close = expect_close;
  681.   dirptrs[i].wcard = NULL; /* Only used in lanman2 searches */
  682.   dirptrs[i].attr = 0; /* Only used in lanman2 searches */
  683.  
  684.   dptr_promote(key);
  685.  
  686.   DEBUG(3,("creating new dirptr %d (0x%x) for path %s, expect_close = %d\n",key,p,path,
  687.     expect_close));  
  688.  
  689.   return(key);
  690. }
  691.  
  692. /****************************************************************************
  693. fill the 5 byte server reserved dptr field
  694. ****************************************************************************/
  695. BOOL dptr_fill(char *buf,unsigned int key)
  696. {
  697.   void *p = dptr_get(key);
  698.   int offset;
  699.   if (!p)
  700.     {
  701.       DEBUG(3,("filling null dirptr %d\n",key));
  702.       return(False);
  703.     }
  704.   offset = telldir(p);
  705.   DEBUG(3,("fill on dirptr 0x%x now at %d\n",p,offset));
  706.   buf[0] = key;
  707.   memcpy(buf+1,(char *)&offset,4);
  708.   DEBUG(3,("filled dirptr %d at offset %d\n",key,offset));
  709.   return(True);
  710. }
  711.  
  712. /****************************************************************************
  713. return True is the offset is at zero
  714. ****************************************************************************/
  715. BOOL dptr_zero(char *buf)
  716. {
  717.   int offset;
  718.   memcpy((char *)&offset,buf+1,4);
  719.   return (offset == 0);
  720. }
  721.  
  722. /****************************************************************************
  723. fetch the dir ptr and seek it given the 5 byte server field
  724. ****************************************************************************/
  725. void *dptr_fetch(char *buf,int *num)
  726. {
  727.   unsigned int key = *(unsigned char *)buf;
  728.   void *p = dptr_get(key);
  729.   int offset;
  730.   if (!p)
  731.     {
  732.       DEBUG(3,("fetched null dirptr %d\n",key));
  733.       return(NULL);
  734.     }
  735.   *num = key;
  736.   memcpy((char *)&offset,buf+1,4);
  737.   seekdir(p,offset);
  738.   dptr_promote(key);
  739.   DEBUG(3,("fetching dirptr %d for path %s\n",key,dptr_path(key)));
  740.   return(p);
  741. }
  742.  
  743. /****************************************************************************
  744. fetch the dir ptr and seek it given the lanman2 parameter block
  745. ****************************************************************************/
  746. void *dptr_fetch_lanman2(char *params,int dptr_num)
  747. {
  748.   void *p = dptr_get(dptr_num);
  749.   uint32 resume_key = SVAL(params,6);
  750.   BOOL uses_resume_key = BITSETW(params+10,2);
  751.  
  752.   if (!p)
  753.     {
  754.       DEBUG(3,("fetched null dirptr %d\n",dptr_num));
  755.       return(NULL);
  756.     }
  757.   if(uses_resume_key)
  758.     seekdir(p,resume_key);
  759.   dptr_promote(dptr_num);
  760.   DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
  761.   return(p);
  762. }
  763.  
  764. /****************************************************************************
  765.   start a directory listing
  766. ****************************************************************************/
  767. BOOL start_dir(int cnum,char *directory)
  768. {
  769.   DEBUG(5,("start_dir cnum=%d dir=%s\n",cnum,directory));
  770.  
  771.   if (!check_name(directory,cnum))
  772.     return(False);
  773.   
  774.   Connections[cnum].dirptr = (void *)opendir(directory);
  775.  
  776.   StrnCpy(Connections[cnum].dirpath,directory,sizeof(pstring)-1);
  777.   
  778.   return(Connections[cnum].dirptr != NULL);
  779. }
  780.  
  781. /****************************************************************************
  782.   get a directory entry
  783. ****************************************************************************/
  784. BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mode,time_t *date,BOOL check_descend)
  785. {
  786.   struct DIRECT *dptr;
  787.   BOOL do_mangling;
  788.   BOOL found = False;
  789.   struct stat sbuf;
  790.   pstring path="";
  791.   pstring pathreal="";
  792.   BOOL isrootdir;
  793.   pstring filename="";
  794.   BOOL matched;
  795.   BOOL has_wild = (strchr(mask,'?') || strchr(mask,'*'));
  796.   
  797.   isrootdir = (strequal(Connections[cnum].dirpath,"./") ||
  798.            strequal(Connections[cnum].dirpath,"."));
  799.   
  800.   if (!Connections[cnum].dirptr)
  801.     return(False);
  802.   
  803.   while (!found)
  804.     {
  805.       dptr = readdir(Connections[cnum].dirptr);
  806.  
  807.       DEBUG(3,("readdir on dirptr 0x%x now at offset %d\n",
  808.         Connections[cnum].dirptr,telldir(Connections[cnum].dirptr)));
  809.       
  810.       if (dptr == NULL) 
  811.     return(False);
  812.       
  813.      
  814. #ifdef NEXT2
  815.       DEBUG(3,("name is: %s\n", dptr->d_name));
  816.       if (telldir(Connections[cnum].dirptr)<0) {
  817.         DEBUG(3,("get_dir_entry encountered null - returning false.\n"));
  818.         return(False);
  819.       }
  820. #endif
  821.  
  822.       matched = False;
  823.  
  824.       do_mangling = ((has_wild || strchr(mask,magic_char)) && 
  825.              lp_manglednames(SNUM(cnum)));
  826.  
  827.       strcpy(filename,dptr->d_name);      
  828.  
  829.       if ((strcmp(filename,mask) == 0) ||
  830.       (name_convert(filename,dptr->d_name,do_mangling,lp_mangled_map(SNUM(cnum))) &&
  831.        mask_match(filename,mask,!isrootdir,False,False)))
  832.     {
  833.       strcpy(fname,filename);
  834.       strcpy(path,Connections[cnum].dirpath);
  835.       strcat(path,"/");
  836.       strcpy(pathreal,path);
  837.       strcat(path,fname);
  838.       strcat(pathreal,dptr->d_name);
  839.       if (stat(pathreal,&sbuf) != 0) 
  840.         {
  841.           DEBUG(5,("Couldn't stat 1 [%s]\n",path));
  842.           continue;
  843.         }
  844.  
  845.       if (check_descend &&
  846.           !strequal(fname,".") && !strequal(fname,".."))
  847.         continue;
  848.       
  849.       *mode = dos_mode(cnum,pathreal,&sbuf);
  850.  
  851.       if (((*mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
  852.         {          
  853.           DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype));
  854.           continue;
  855.         }
  856.       *size = sbuf.st_size;
  857.       *date = sbuf.st_mtime;
  858.  
  859.       DEBUG(5,("get_dir_entry found %s fname=%s\n",pathreal,fname));
  860.       
  861.       found = True;
  862.     }
  863.     }
  864.  
  865.   return(found);
  866. }
  867.  
  868. static int old_umask = 022;
  869.  
  870. /****************************************************************************
  871. load parameters specific to a connection/service
  872. ****************************************************************************/
  873. void become_service(int cnum)
  874. {
  875.   static int last_cnum = -1;
  876.   extern int case_sensitivity;
  877.  
  878.   if (!OPEN_CNUM(cnum))
  879.     {
  880.       last_cnum = -1;
  881.       return;
  882.     }
  883.  
  884.   if (cnum == last_cnum)
  885.     return;
  886.  
  887.   case_sensitivity = lp_defaultcase(SNUM(cnum));
  888.   magic_char = lp_magicchar(SNUM(cnum));
  889.  
  890.   if (ChDir(Connections[cnum].connectpath) != 0)
  891.     {
  892.       DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
  893.         Connections[cnum].connectpath,cnum));     
  894.       return;
  895.     }
  896.  
  897.   last_cnum = cnum;
  898. }
  899.  
  900.  
  901. /****************************************************************************
  902.   become the user of a connection number
  903. ****************************************************************************/
  904. BOOL become_user(int cnum)
  905. {
  906.   if (!OPEN_CNUM(cnum))
  907.     {
  908.       DEBUG(0,("ERROR: Connection %d not open\n",cnum));
  909.       return(False);
  910.     }
  911.  
  912.   if (done_become_user == cnum)
  913.     {
  914.       DEBUG(3,("Skipping become_user - already user\n"));
  915.       return(True);
  916.     }
  917.  
  918.   if (done_become_user != -1)
  919.     unbecome_user();
  920.   
  921.   if (initial_uid == 0)
  922.     {
  923. #ifdef USE_SETRES 
  924.       if (setresgid(-1,Connections[cnum].gid,-1) != 0)
  925. #else
  926.     if (setgid(Connections[cnum].gid) != 0)
  927. #endif
  928.       {
  929.         DEBUG(0,("Couldn't set gid %d currently set to (%d,%d)\n",
  930.           Connections[cnum].gid,getgid(),getegid()));
  931.         return(False);
  932.       }
  933.  
  934.  
  935.       /* groups stuff added by ih/wreu */
  936.       if (Connections[cnum].ngroups > 0)
  937.     if (setgroups(Connections[cnum].ngroups,(GID_TYPE *)Connections[cnum].groups))
  938.       DEBUG(0,("setgroups call failed!\n"));
  939.   
  940. #ifdef AIX
  941.     {
  942.        /* AIX 3 stuff - inspired by a code fragment in wu-ftpd */
  943.        priv_t priv;
  944.  
  945.        priv.pv_priv[0] = 0;
  946.        priv.pv_priv[1] = 0;
  947.        if (setpriv(PRIV_SET|PRIV_INHERITED|PRIV_EFFECTIVE|PRIV_BEQUEATH,
  948.                    &priv, sizeof(priv_t)) < 0 ||
  949.            setuidx(ID_REAL|ID_EFFECTIVE, (uid_t)Connections[cnum].uid) < 0 ||
  950.            seteuid((uid_t)Connections[cnum].uid) < 0) 
  951.      DEBUG(1,("Can't set uid (AIX3)"));
  952.     }
  953. #endif
  954.  
  955. #ifdef USE_SETRES
  956.       if (setresuid(-1,Connections[cnum].uid,-1) != 0)
  957. #else  
  958.       if ((seteuid(Connections[cnum].uid) != 0) && 
  959.       (setuid(Connections[cnum].uid) != 0))
  960. #endif
  961.     {
  962.       DEBUG(0,("Couldn't set uid %d currently set to (%d,%d)\n",
  963.         Connections[cnum].uid,getuid(), geteuid()));
  964.       return(False);
  965.     }
  966.     }
  967.   
  968.   old_umask = umask(0777 & ~lp_create_mode(SNUM(cnum)));
  969.  
  970.   done_become_user = cnum;
  971.  
  972.   if (ChDir(Connections[cnum].connectpath) != 0)
  973.     {
  974.       DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
  975.         Connections[cnum].connectpath,cnum));     
  976.       unbecome_user();
  977.       return(False);
  978.     }
  979.   
  980.   DEBUG(5,("become_user now uid=(%d,%d) gid=(%d,%d)\n",
  981.     getuid(),geteuid(),getgid(),getegid()));
  982.  
  983.   return(True);
  984. }
  985.  
  986. /****************************************************************************
  987.   unbecome the user of a connection number
  988. ****************************************************************************/
  989. BOOL unbecome_user(void )
  990. {
  991.   if (ChDir(OriginalDir) != 0)
  992.     DEBUG(0,("%s chdir(%s) failed\n",timestring(),OriginalDir));  
  993.  
  994.   if (done_become_user == -1)
  995.     return(False);
  996.  
  997.   umask(old_umask);
  998.  
  999.   if (initial_uid == 0)
  1000.     {
  1001. #ifdef USE_SETRES
  1002.       setresuid(-1,getuid(),-1);
  1003.       setresgid(-1,getgid(),-1);
  1004. #else
  1005.       if (seteuid(initial_uid) != 0) 
  1006.     setuid(initial_uid);
  1007.       setgid(initial_gid);
  1008. #endif
  1009.     }
  1010. #ifdef NO_EID
  1011.   DEBUG(2,("Running with no EID\n"));
  1012.   initial_uid = getuid();
  1013.   initial_gid = getgid();
  1014. #else
  1015.   if (geteuid() != initial_uid)
  1016.     {
  1017.       DEBUG(0,("Warning: You appear to have a trapdoor uid system\n"));
  1018.       initial_uid = geteuid();
  1019.     }
  1020.   if (getegid() != initial_gid)
  1021.     {
  1022.       DEBUG(0,("Warning: You appear to have a trapdoor gid system\n"));
  1023.       initial_gid = getegid();
  1024.     }
  1025. #endif
  1026.   
  1027.   if (ChDir(OriginalDir) != 0)
  1028.     DEBUG(0,("%s chdir(%s) failed\n",timestring(),OriginalDir));  
  1029.  
  1030.   DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n",
  1031.     getuid(),geteuid(),getgid(),getegid()));
  1032.  
  1033.   done_become_user = -1;
  1034.  
  1035.   return(True);
  1036. }
  1037.  
  1038. /****************************************************************************
  1039.   find a service entry
  1040. ****************************************************************************/
  1041. int find_service(char *service)
  1042. {
  1043.    int iService;
  1044.  
  1045.    iService = lp_servicenumber(service);
  1046.  
  1047.    /* now handle the special case of a home directory */
  1048.    if (iService < 0)
  1049.    {
  1050.       char *phome_dir = get_home_dir(service);
  1051.       DEBUG(3,("checking for home directory %s gave %s\n",service,
  1052.         phome_dir?phome_dir:"(NULL)"));
  1053.       if (phome_dir)
  1054.       {   
  1055.      int iHomeService;
  1056.      if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
  1057.      {
  1058.         lp_add_home(service,iHomeService,phome_dir);
  1059.         iService = lp_servicenumber(service);
  1060.      }
  1061.       }
  1062.    }
  1063.  
  1064.    /* If we still don't have a service, attempt to add it as a printer. */
  1065.    if (iService < 0)
  1066.    {
  1067.       int iPrinterService;
  1068.  
  1069.       if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
  1070.       {
  1071.          char *pszTemp;
  1072.  
  1073.          DEBUG(3,("checking whether %s is a valid printer name...\n", service));
  1074.          pszTemp = PRINTCAP;
  1075.          if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
  1076.          {
  1077.             DEBUG(3,("%s is a valid printer name\n", service));
  1078.             DEBUG(3,("adding %s as a printer service\n", service));
  1079.             lp_add_printer(service,iPrinterService);
  1080.             iService = lp_servicenumber(service);
  1081.             if (iService < 0)
  1082.                DEBUG(0,("failed to add %s as a printer service!\n", service));
  1083.          }
  1084.          else
  1085.             DEBUG(3,("%s is not a valid printer name\n", service));
  1086.       }
  1087.    }
  1088.  
  1089.    /* just possibly it's a default service? */
  1090.    if (iService < 0) 
  1091.      {
  1092.        char *defservice = lp_defaultservice();
  1093.        if (defservice && *defservice && !strequal(defservice,service))
  1094.      return(find_service(defservice));
  1095.      }
  1096.  
  1097.    if (iService >= 0)
  1098.       if (!VALID_SNUM(iService))
  1099.       {
  1100.          DEBUG(0,("Invalid snum %d for %s\n",iService,service));
  1101.      iService = -1;
  1102.       }
  1103.  
  1104.    if (iService < 0)
  1105.       DEBUG(3,("find_service() failed to find service %s\n", service));
  1106.  
  1107.    return (iService);
  1108. }
  1109.  
  1110.  
  1111. /****************************************************************************
  1112.   create an error packet from a cached error.
  1113. ****************************************************************************/
  1114. int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
  1115. {
  1116.   write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
  1117.  
  1118.   int32 eclass = wbmpx->wr_errclass;
  1119.   int32 err = wbmpx->wr_error;
  1120.  
  1121.   /* We can now delete the auxiliary struct */
  1122.   free((char *)wbmpx);
  1123.   Files[fnum].wbmpx_ptr = NULL;
  1124.   return error_packet(inbuf,outbuf,eclass,err,line);
  1125. }
  1126.  
  1127.  
  1128. struct
  1129. {
  1130.   int unixerror;
  1131.   int smbclass;
  1132.   int smbcode;
  1133. } unix_smb_errmap[] =
  1134. {
  1135.   {EPERM,ERRDOS,ERRnoaccess},
  1136.   {EACCES,ERRDOS,ERRnoaccess},
  1137.   {ENOENT,ERRDOS,ERRbadfile},
  1138.   {EIO,ERRHRD,ERRgeneral},
  1139.   {EBADF,ERRSRV,ERRsrverror},
  1140.   {EINVAL,ERRSRV,ERRsrverror},
  1141.   {EEXIST,ERRDOS,ERRfilexists},
  1142.   {ENFILE,ERRDOS,ERRnofids},
  1143.   {EMFILE,ERRDOS,ERRnofids},
  1144.   {ENOSPC,ERRHRD,ERRdiskfull},
  1145. #ifdef EDQUOT
  1146.   {EDQUOT,ERRHRD,ERRdiskfull},
  1147. #endif
  1148. #ifdef ENOTEMPTY
  1149.   {ENOTEMPTY,ERRDOS,ERRnoaccess},
  1150. #endif
  1151.   {EROFS,ERRHRD,ERRnowrite},
  1152.   {0,0,0}
  1153. };
  1154.  
  1155.  
  1156. /****************************************************************************
  1157.   create an error packet from errno
  1158. ****************************************************************************/
  1159. int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
  1160. {
  1161.   int eclass=def_class;
  1162.   int ecode=def_code;
  1163.   int i=0;
  1164.  
  1165.   if (unix_ERR_class != SUCCESS)
  1166.     {
  1167.       eclass = unix_ERR_class;
  1168.       ecode = unix_ERR_code;
  1169.       unix_ERR_class = SUCCESS;
  1170.       unix_ERR_code = 0;
  1171.     }
  1172.   else
  1173.     {
  1174.       while (unix_smb_errmap[i].smbclass != 0)
  1175.     {
  1176.       if (unix_smb_errmap[i].unixerror == errno)
  1177.         {
  1178.           eclass = unix_smb_errmap[i].smbclass;
  1179.           ecode = unix_smb_errmap[i].smbcode;
  1180.           break;
  1181.         }
  1182.       i++;
  1183.     }
  1184.     }
  1185.  
  1186.   return(error_packet(inbuf,outbuf,eclass,ecode,line));
  1187. }
  1188.  
  1189.  
  1190. /****************************************************************************
  1191.   create an error packet. Normally called using the ERROR() macro
  1192. ****************************************************************************/
  1193. int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
  1194. {
  1195.   int outsize = set_message(outbuf,0,0,True);
  1196.   int cmd;
  1197.   cmd = CVAL(inbuf,smb_com);
  1198.   
  1199.   CVAL(outbuf,smb_rcls) = error_class;
  1200.   SSVAL(outbuf,smb_err,error_code);  
  1201.   
  1202.   DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
  1203.        timestring(),
  1204.        line,
  1205.        (int)CVAL(inbuf,smb_com),
  1206.        smb_fn_name(CVAL(inbuf,smb_com)),
  1207.        error_class,
  1208.        error_code));
  1209.  
  1210.   if (errno != 0)
  1211.     DEBUG(3,("error string = %s\n",strerror(errno)));
  1212.   
  1213.   return(outsize);
  1214. }
  1215.  
  1216.  
  1217. /****************************************************************************
  1218.   utility function called to see if a file region is locked
  1219. ****************************************************************************/
  1220. BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset)
  1221. {
  1222.   if (count == 0)
  1223.     return(False);
  1224.  
  1225.   if (!lp_locking(SNUM(cnum)))
  1226.     return(False);
  1227.  
  1228.   return(fcntl_lock(Files[fnum].fd,F_GETLK,offset,count,
  1229.             (Files[fnum].read_only?F_RDLCK:F_WRLCK)));
  1230. }
  1231.  
  1232.  
  1233. /****************************************************************************
  1234.   utility function called by locking requests
  1235. ****************************************************************************/
  1236. BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
  1237. {
  1238.   BOOL ok = False;
  1239.  
  1240.   if (!lp_locking(SNUM(cnum)))
  1241.     return(True);
  1242.  
  1243.   if (count == 0) {
  1244.     *eclass = ERRDOS;
  1245.     *ecode = ERRnoaccess;
  1246.     return False;
  1247.   }
  1248.  
  1249.   if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  1250.     ok = fcntl_lock(Files[fnum].fd,F_SETLK,offset,count,
  1251.             (Files[fnum].read_only?F_RDLCK:F_WRLCK));
  1252.  
  1253.   if (!ok) {
  1254.     *eclass = ERRDOS;
  1255.     *ecode = ERRlock;
  1256.     return False;
  1257.   }
  1258.   return True; /* Got lock */
  1259. }
  1260.  
  1261.  
  1262. /****************************************************************************
  1263.   utility function called by unlocking requests
  1264. ****************************************************************************/
  1265. BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
  1266. {
  1267.   BOOL ok = False;
  1268.  
  1269.   if (!lp_locking(SNUM(cnum)))
  1270.     return(True);
  1271.  
  1272.   if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
  1273.     ok = fcntl_lock(Files[fnum].fd,F_SETLK,offset,count,F_UNLCK);
  1274.    
  1275.   if (!ok) {
  1276.     *eclass = ERRDOS;
  1277.     *ecode = ERRlock;
  1278.     return False;
  1279.   }
  1280.   return True; /* Did unlock */
  1281. }
  1282.  
  1283.  
  1284. /****************************************************************************
  1285.   open the socket communication
  1286. ****************************************************************************/
  1287. BOOL open_sockets(BOOL is_daemon,int port)
  1288. {
  1289.   extern int Client;
  1290.   char optval[4];
  1291.   int optlen=4;
  1292.  
  1293.   /* Check if we need to open a new socket by doing
  1294.      a harmless socket option on fd 0. If this fails
  1295.      we need to create one. */
  1296.   
  1297.   if (!is_daemon && 
  1298.       (getsockopt(0, SOL_SOCKET, SO_TYPE, optval, &optlen)==-1) &&
  1299.       (errno == ENOTSOCK))
  1300.     {
  1301.       DEBUG(0,("standard input is not a socket, will create a socket\n"));
  1302.       is_daemon = True;
  1303.     }
  1304.  
  1305.   if (is_daemon)
  1306.     {
  1307.       int s;
  1308.       int sockopt = 1;
  1309.       struct sockaddr addr;
  1310.       int in_addrlen = sizeof(addr);
  1311.        
  1312.       /* Stop zombies */
  1313.       signal(SIGCLD, SIGNAL_CAST sig_cld);
  1314.  
  1315.       /* open an incoming socket */
  1316.       s = open_socket_in(SOCK_STREAM, port);
  1317.       if (s == -1)
  1318.     return(False);
  1319.  
  1320.       if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&sockopt, sizeof(int)))
  1321.     {
  1322.       DEBUG(0,("Error in setting socket option: %s",strerror(errno)));
  1323.       close(s);
  1324.       return False;
  1325.     }
  1326.   
  1327.       /* ready to listen */
  1328.       if (listen(s, 5) == -1) 
  1329.     {
  1330.       DEBUG(0,("listen: %s",strerror(errno)));
  1331.       close(s);
  1332.       return False;
  1333.     }
  1334.   
  1335.   
  1336.       /* now accept incoming connections - forking a new process
  1337.      for each incoming connection */
  1338.       DEBUG(2,("waiting for a connection\n"));
  1339.       while ((Client = accept(s,&addr,&in_addrlen)))
  1340.     {
  1341.       if (Client == -1 && errno == EINTR)
  1342.         continue;
  1343.  
  1344.       if (Client == -1)
  1345.         {
  1346.           DEBUG(0,("accept: %s",strerror(errno)));
  1347.           return False;
  1348.         }
  1349.  
  1350. #ifdef NO_FORK_DEBUG
  1351.           /* now set appropriate socket options */
  1352.           signal(SIGPIPE, SIGNAL_CAST Abort);
  1353.           signal(SIGCLD, SIGNAL_CAST SIG_DFL);
  1354.         {
  1355.           int one=1;
  1356.           setsockopt(Client,SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(one));
  1357.         }
  1358.       return True;
  1359. #else
  1360.       if (Client != -1 && fork()==0)
  1361.         {
  1362.           signal(SIGPIPE, SIGNAL_CAST Abort);
  1363.           signal(SIGCLD, SIGNAL_CAST SIG_DFL);
  1364.  
  1365.           /* now set appropriate socket options */
  1366.           {
  1367.         int one=1;
  1368.         setsockopt(Client,SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(one));
  1369.           }
  1370.           return True; 
  1371.         }
  1372.           close(Client); /* The parent doesn't need this socket */
  1373. #endif
  1374.     }
  1375.       close(s);
  1376.       return False;
  1377.     }
  1378.   else
  1379.     {
  1380.       /* We will abort gracefully when the client or remote system 
  1381.      goes away */
  1382.       signal(SIGPIPE, SIGNAL_CAST Abort);
  1383.       Client = 0;
  1384.     }
  1385.  
  1386.   /* now set appropriate socket options */
  1387.   {
  1388.     int one=1;
  1389.     setsockopt(Client,SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(one));
  1390. #if (defined(TCP_NODELAY) && defined(SOL_TCP))
  1391.     setsockopt(Client,SOL_TCP,TCP_NODELAY,(char *)&one,sizeof(one)); 
  1392. #endif
  1393.   }
  1394.  
  1395.   return True;
  1396. }
  1397.  
  1398.  
  1399. /****************************************************************************
  1400. this prevents zombie child processes
  1401. ****************************************************************************/
  1402. int sig_cld()
  1403. {
  1404.   static int depth = 0;
  1405.   if (depth != 0)
  1406.     {
  1407.       DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
  1408.       return(0);
  1409.     }
  1410.   depth++;
  1411.  
  1412.   DEBUG(5,("got SIGCLD\n"));
  1413.  
  1414. #ifdef USE_WAITPID
  1415.   while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
  1416. #endif
  1417.  
  1418.   /* Stop zombies */
  1419.   /* Stevens, Adv. Unix Prog. says that on system V you must call
  1420.      wait before reinstalling the signal handler, because the kernel
  1421.      calls the handler from within the signal-call when there is a
  1422.      child that has exited. This would lead to an infinite recursion
  1423.      if done vice versa. */
  1424.         
  1425.   signal(SIGCLD, SIGNAL_CAST sig_cld);
  1426.  
  1427. #ifndef USE_WAITPID
  1428.   while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
  1429. #endif
  1430.   depth--;
  1431.   return 0;
  1432. }
  1433.  
  1434.  
  1435. /****************************************************************************
  1436.   make a connection to a service
  1437. ****************************************************************************/
  1438. int make_connection(char *service,char *user,char *password,char *dev,int vuid)
  1439. {
  1440.   int cnum;
  1441.   int snum;
  1442.   struct passwd *pass = NULL;
  1443.   BOOL guest = False;
  1444.  
  1445.   strlower(service);
  1446.  
  1447.   snum = find_service(service);
  1448.   if (snum < 0)
  1449.     {
  1450.       if (strequal(service,"IPC$"))
  1451.     {      
  1452.       DEBUG(3,("%s refusing IPC connection\n",timestring()));
  1453.       return(-3);
  1454.     }
  1455.  
  1456.       DEBUG(0,("%s couldn't find service %s\n",timestring(),service));      
  1457.       return(-2);
  1458.     }
  1459.  
  1460.   if (strequal(service,"homes"))
  1461.     {
  1462.       if (*user && Get_Pwnam(user))
  1463.     return(make_connection(user,user,password,dev,vuid));
  1464.  
  1465.       if (validated_username(vuid))
  1466.     {
  1467.       strcpy(user,validated_username(vuid));
  1468.       return(make_connection(user,user,password,dev,vuid));
  1469.     }
  1470.     }
  1471.  
  1472.   if (!check_access(snum))
  1473.     return(-1);
  1474.  
  1475.  
  1476.   if (*dev == '?' || !*dev)
  1477.     {
  1478.       if (strequal(service,"IPC$"))
  1479.     strcpy(dev,"IPC");
  1480.       else if (lp_print_ok(snum))
  1481.     strcpy(dev,"LPT");
  1482.       else
  1483.     strcpy(dev,"A");
  1484.     }
  1485.  
  1486.   /* if the request is as a printer and you can't print then refuse */
  1487.   strupper(dev);
  1488.   if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0))
  1489.     return(-2);
  1490.  
  1491.   /* lowercase the user name */
  1492.   strlower(user);
  1493.  
  1494.   /* shall we let them in? */
  1495.   if (!authorise_login(snum,user,password,&guest,vuid))
  1496.     {
  1497.       DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
  1498.       return(-1);
  1499.     }
  1500.   
  1501.   cnum = find_free_connection();
  1502.   if (cnum < 0)
  1503.     {
  1504.       DEBUG(0,("%s couldn't find free connection\n",timestring()));      
  1505.       return(-1);
  1506.     }
  1507.  
  1508.   /* find out some info about the user */
  1509.   pass = Get_Pwnam(user);
  1510.  
  1511.   if (pass == NULL)
  1512.     {
  1513.       DEBUG(0,("%s couldn't find account %s\n",timestring(),user)); 
  1514.       return(-1);
  1515.     }
  1516.  
  1517.   Connections[cnum].read_only = lp_readonly(snum);
  1518.  
  1519.   if (user_in_list(user,lp_readlist(snum)))
  1520.     Connections[cnum].read_only = True;
  1521.  
  1522.   if (user_in_list(user,lp_writelist(snum)))
  1523.     Connections[cnum].read_only = False;    
  1524.  
  1525.   Connections[cnum].uid = pass->pw_uid;
  1526.   Connections[cnum].gid = pass->pw_gid;
  1527.   Connections[cnum].connect_num = cnum;
  1528.   Connections[cnum].service = snum;
  1529.   Connections[cnum].printer = (strncmp(dev,"LPT",3) == 0);
  1530.   Connections[cnum].ipc = (strncmp(dev,"IPC",3) == 0);
  1531.   Connections[cnum].dirptr = NULL;
  1532.   Connections[cnum].dirpath[0] = 0;
  1533.   strcpy(Connections[cnum].connectpath, PATH(snum));    
  1534.  
  1535. #if HAVE_GETGRNAM 
  1536.   if (*lp_group(snum))
  1537.     {
  1538.       struct group *gptr = (struct group *)getgrnam(lp_group(snum));
  1539.       if (gptr)
  1540.     {
  1541.       Connections[cnum].gid = gptr->gr_gid;
  1542.       DEBUG(3,("In group %s\n",lp_group(snum)));
  1543.     }
  1544.       else
  1545.     DEBUG(1,("Couldn't find group %s\n",lp_group(snum)));
  1546.     }
  1547. #endif
  1548.  
  1549.   /* groups stuff added by ih */
  1550.   Connections[cnum].ngroups = 0;
  1551.   Connections[cnum].groups = NULL;
  1552.   if (-1 == initgroups(pass->pw_name,Connections[cnum].gid))
  1553.     DEBUG(0,("Unable to initgroups!\n")) ;
  1554.   else
  1555.     {
  1556.       int i,ngroups;
  1557.       int *igroups;
  1558.       GID_TYPE grp = 0;
  1559.       ngroups = getgroups(0,&grp);
  1560.       if (ngroups <= 0)
  1561.     ngroups = 32;
  1562.       igroups = (int *)malloc(sizeof(int)*ngroups);
  1563.       for (i=0;i<ngroups;i++)
  1564.     igroups[i] = 0x42424242;
  1565.       ngroups = getgroups(ngroups,(GID_TYPE *)igroups);
  1566.  
  1567.       if (igroups[0] == 0x42424242)
  1568.     ngroups = 0;
  1569.  
  1570.       Connections[cnum].ngroups = ngroups;
  1571.  
  1572.       /* The following bit of code is very strange. It is due to the
  1573.      fact that some OSes use int* and some use gid_t* for
  1574.      getgroups, and some (like SunOS) use both, one in prototypes,
  1575.      and one in man pages and the actual code. Thus we detect it
  1576.      dynamically using some very ugly code */
  1577.       if (ngroups > 0)
  1578.     {
  1579.       for (i=0;i<ngroups;i++)
  1580.         if (igroups[i] == 0x42424242)
  1581.           groups_use_ints = False;
  1582.  
  1583.       if (groups_use_ints)
  1584.         {
  1585.           Connections[cnum].igroups = igroups;
  1586.           Connections[cnum].groups = (gid_t *)igroups;      
  1587.         }
  1588.       else
  1589.         {
  1590.           gid_t *groups = (gid_t *)igroups;
  1591.           igroups = (int *)malloc(sizeof(int)*ngroups);
  1592.           for (i=0;i<ngroups;i++)
  1593.         igroups[i] = groups[i];
  1594.           Connections[cnum].igroups = igroups;
  1595.           Connections[cnum].groups = groups;                
  1596.         }
  1597.     }
  1598.       DEBUG(3,("%s is in %d groups\n",pass->pw_name,ngroups));
  1599.       for (i=0;i<ngroups;i++)
  1600.     DEBUG(3,("%d ",igroups[i]));
  1601.       DEBUG(3,("\n"));
  1602.     }
  1603.  
  1604.  
  1605.   /* check number of connections */
  1606.   if (!claim_connection(cnum,
  1607.             lp_servicename(SNUM(cnum)),
  1608.             lp_max_connections(SNUM(cnum)),False))
  1609.     {
  1610.       DEBUG(1,("too many connections - rejected\n"));
  1611.       return(-4);
  1612.     }  
  1613.  
  1614.   if (lp_status(SNUM(cnum)))
  1615.     claim_connection(cnum,"STATUS.",100000,True);
  1616.  
  1617.   Connections[cnum].open = True;
  1618.  
  1619.   add_session_user(user);
  1620.  
  1621.   {
  1622.     extern struct from_host Client_info;
  1623.     DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (pid %d)\n",
  1624.          timestring(),
  1625.          Client_info.name,Client_info.addr,
  1626.          lp_servicename(SNUM(cnum)),user,getpid()));
  1627.   }
  1628.  
  1629.   return(cnum);
  1630. }
  1631.  
  1632.  
  1633. /****************************************************************************
  1634.   find first available file slot
  1635. ****************************************************************************/
  1636. int find_free_file(void )
  1637. {
  1638.   int i;
  1639.   for (i=1;i<MAX_OPEN_FILES;i++)
  1640.     if (!Files[i].open)
  1641.       return(i);
  1642.   DEBUG(1,("ERROR! Out of file structures\n"));
  1643.   return(-1);
  1644. }
  1645.  
  1646. /****************************************************************************
  1647.   find first available connection slot, starting from a random position.
  1648. The randomisation stops problems with the server dieing and clients
  1649. thinking the server is still available.
  1650. ****************************************************************************/
  1651. int find_free_connection(void )
  1652. {
  1653.   int rand_start = (getpid() + (time(NULL)%1000)) % MAX_CONNECTIONS;
  1654.   int i;
  1655.  
  1656.   if (rand_start < 1) rand_start = 1;
  1657.  
  1658.   for (i=rand_start;i<MAX_CONNECTIONS;i++)
  1659.     if (!Connections[i].open) 
  1660.       {
  1661.     DEBUG(3,("found free connection number %d\n",i));
  1662.     return(i);
  1663.       }
  1664.  
  1665.   for (i=1;i<rand_start;i++)
  1666.     if (!Connections[i].open) 
  1667.       {
  1668.     DEBUG(3,("found free connection number %d\n",i));
  1669.     return(i);
  1670.       }
  1671.  
  1672.   DEBUG(1,("ERROR! Out of connection structures\n"));
  1673.   return(-1);
  1674. }
  1675.  
  1676.  
  1677. /* List of supported protocols, most desired first */
  1678. struct {
  1679.   char *proto_name;
  1680.   int (*proto_reply_fn)(char *);
  1681.   int protocol_level;
  1682. } supported_protocols[] = {
  1683.   {"NT LANMAN 1.0", reply_nt1 , PROTOCOL_NT1},
  1684.   {"LM1.2X002", reply_lanman2 , PROTOCOL_LANMAN2},
  1685.   {"DOS LM1.2X002", reply_lanman2 , PROTOCOL_LANMAN2},
  1686.   {"LANMAN1.0", reply_lanman1 , PROTOCOL_LANMAN1},
  1687.   {"MICROSOFT NETWORKS 3.0", reply_lanman1 , PROTOCOL_LANMAN1},
  1688.   {"MICROSOFT NETWORKS 1.03",reply_coreplus,PROTOCOL_COREPLUS},/* core+ protocol */
  1689.   {"PC NETWORK PROGRAM 1.0", reply_corep, PROTOCOL_CORE}, /* core protocol */
  1690.   {NULL,NULL},
  1691. };
  1692.  
  1693.  
  1694.  
  1695. /****************************************************************************
  1696. reply for the core protocol
  1697. ****************************************************************************/
  1698. int reply_corep(char *outbuf)
  1699. {
  1700.   int outsize = set_message(outbuf,1,0,True);
  1701.  
  1702.   Protocol = PROTOCOL_CORE;
  1703.  
  1704.   return outsize;
  1705. }
  1706.  
  1707.  
  1708. /****************************************************************************
  1709. reply for the coreplus protocol
  1710. ****************************************************************************/
  1711. int reply_coreplus(char *outbuf)
  1712. {
  1713.   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
  1714.   int outsize = set_message(outbuf,13,0,True);
  1715.   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
  1716.                  readbraw and writebraw (possibly) */
  1717.   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
  1718. #ifdef TESTING
  1719.   SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */    
  1720. #endif
  1721.  
  1722.   Protocol = PROTOCOL_COREPLUS;
  1723.  
  1724.   return outsize;
  1725. }
  1726.  
  1727.  
  1728. /****************************************************************************
  1729. reply for the lanman 1.0 protocol
  1730. ****************************************************************************/
  1731. int reply_lanman1(char *outbuf)
  1732. {
  1733.   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
  1734.   int outsize = set_message(outbuf,13,0,True);
  1735.   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
  1736.   SSVAL(outbuf,smb_vwv1,(lp_security()==SEC_USER)?1:0); /* user level security? don't encrypt */    
  1737.   SSVAL(outbuf,smb_vwv2,lp_maxxmit());
  1738.   SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
  1739.   SSVAL(outbuf,smb_vwv4,1);
  1740.   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
  1741.                  readbraw writebraw (possibly) */
  1742.   SIVAL(outbuf,smb_vwv6,getpid());
  1743.   SSVAL(outbuf,smb_vwv10, (TimeDiff() / 60) );
  1744.  
  1745.   put_dos_date(outbuf,smb_vwv8,time(NULL));
  1746.  
  1747.   Protocol = PROTOCOL_LANMAN1;
  1748.  
  1749.   return outsize;
  1750. }
  1751.  
  1752.  
  1753. /****************************************************************************
  1754. reply for the lanman 2.0 protocol
  1755. ****************************************************************************/
  1756. int reply_lanman2(char *outbuf)
  1757. {
  1758.   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
  1759.   int outsize = set_message(outbuf,13,0,True);
  1760.   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
  1761.   SSVAL(outbuf,smb_vwv1,(lp_security()==SEC_USER)?1:0); /* user level security? don't encrypt */    
  1762.   SSVAL(outbuf,smb_vwv2,lp_maxxmit());
  1763.   SSVAL(outbuf,smb_vwv3,lp_maxmux()); 
  1764.   SSVAL(outbuf,smb_vwv4,1);
  1765.   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
  1766.                  readbraw writebraw (possibly) */
  1767.   SIVAL(outbuf,smb_vwv6,getpid());
  1768.   SSVAL(outbuf,smb_vwv10, (TimeDiff() / 60) );
  1769.  
  1770.   put_dos_date(outbuf,smb_vwv8,time(NULL));
  1771.  
  1772.   Protocol = PROTOCOL_LANMAN2;
  1773.  
  1774.   return outsize;
  1775. }
  1776.  
  1777. /****************************************************************************
  1778. reply for the lanman 2.0 protocol
  1779. ****************************************************************************/
  1780. int reply_nt1(char *outbuf)
  1781. {
  1782.   int outsize = set_message(outbuf,15,0,True);
  1783.   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
  1784.   SSVAL(outbuf,smb_vwv1,(lp_security()==SEC_USER)?1:0); /* user level security? don't encrypt */    
  1785.   SSVAL(outbuf,smb_vwv2,lp_maxmux()); /* maxmpx */
  1786.   SSVAL(outbuf,smb_vwv3,1); /* num vcs */
  1787.   SIVAL(outbuf,smb_vwv4,0xFFFF); /* max buffer */
  1788.   SIVAL(outbuf,smb_vwv6,0xFFFF); /* raw size */
  1789.   SIVAL(outbuf,smb_vwv8,1); /* session key */
  1790.   SIVAL(outbuf,smb_vwv10,0); /* capabilities */
  1791.   put_dos_date(outbuf,smb_vwv12,time(NULL));
  1792.   SSVAL(outbuf,smb_vwv14, (TimeDiff() / 60) );
  1793.  
  1794.   Protocol = PROTOCOL_NT1;
  1795.  
  1796.   return outsize;
  1797. }
  1798.  
  1799.  
  1800.  
  1801. /****************************************************************************
  1802.   reply to a negprot
  1803. ****************************************************************************/
  1804. int reply_negprot(char *inbuf,char *outbuf)
  1805. {
  1806.   int outsize = set_message(outbuf,1,0,True);
  1807.   int index;
  1808.   int choice=-1;
  1809.   int protocol;
  1810.   char *p;
  1811.   int bcc = SVAL(smb_buf(inbuf),-2);
  1812.  
  1813.   /* Check for protocols, most desirable first */
  1814.   for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
  1815.     {
  1816.       p = smb_buf(inbuf)+1;
  1817.       index = 0;
  1818.       if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
  1819.     while (p < (smb_buf(inbuf) + bcc))
  1820.       { 
  1821.         DEBUG(3,("protocol [%s]\n",p));
  1822.         if (strequal(p,supported_protocols[protocol].proto_name))
  1823.           choice = index;
  1824.         index++;
  1825.         p += strlen(p) + 2;
  1826.       }
  1827.       if(choice != -1)
  1828.     break;
  1829.     }
  1830.   
  1831.   SSVAL(outbuf,smb_vwv0,choice);
  1832.   if(choice != -1)
  1833.     {
  1834.       outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
  1835.       DEBUG(2,("Chose protocol %s\n",supported_protocols[protocol].proto_name));
  1836.     }
  1837.   else {
  1838.     DEBUG(0,("No protocol supported !\n"));
  1839.   }
  1840.   
  1841.   if(Protocol >= PROTOCOL_LANMAN2)
  1842.     {
  1843.       if (lp_casesignames())
  1844.         casesignames = ((CVAL(inbuf,smb_flg) & 0x8) != 0x8);
  1845.       long_filenames = ((SVAL(inbuf, smb_flg2) & 0x1) != 0);
  1846.       DEBUG(3,("longfilenames=%s casesignames=%s\n",
  1847.            BOOLSTR(long_filenames),BOOLSTR(casesignames)));
  1848.     }
  1849.  
  1850.   DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
  1851.  
  1852.   return(outsize);
  1853. }
  1854.  
  1855.  
  1856. /****************************************************************************
  1857.   parse a connect packet
  1858. ****************************************************************************/
  1859. void parse_connect(char *buf,char *service,char *user,char *password,char *dev)
  1860. {
  1861.   char *p = smb_buf(buf) + 1;
  1862.   char *p2;
  1863.  
  1864.   DEBUG(4,("parsing connect string %s\n",p));
  1865.     
  1866.   p2 = strrchr(p,'\\');
  1867.   if (p2 == NULL)
  1868.     strcpy(service,p);
  1869.   else
  1870.     strcpy(service,p2+1);
  1871.   
  1872.   p += strlen(p) + 2;
  1873.   
  1874.   strcpy(password,p);
  1875.  
  1876.   p += strlen(p) + 2;
  1877.  
  1878.   strcpy(dev,p);
  1879.   
  1880.   *user = 0;
  1881.   p = strchr(service,'%');
  1882.   if (p != NULL)
  1883.     {
  1884.       *p = 0;
  1885.       strcpy(user,p+1);
  1886.     }
  1887. }
  1888.  
  1889.  
  1890.  
  1891.  
  1892.  
  1893.  
  1894.  
  1895. /****************************************************************************
  1896.   return number of 1K blocks available on a path and total number 
  1897. ****************************************************************************/
  1898. void disk_free(char *path,int *bsize,int *dfree,int *dsize)
  1899. {
  1900.   char *df_command = lp_dfree_command();
  1901. #ifdef USE_STATVFS
  1902.   struct statvfs fs;
  1903. #else
  1904. #ifdef ULTRIX
  1905.   struct fs_data fs;
  1906. #else
  1907.   struct statfs fs;
  1908. #endif
  1909. #endif
  1910.  
  1911.   /* possibly use system() to get the result */
  1912.   if (df_command && *df_command)
  1913.     {
  1914.       int ret;
  1915.       pstring syscmd;
  1916.       pstring outfile;
  1917.  
  1918.       sprintf(outfile,"/tmp/dfree.smb.%d",getpid());
  1919.       sprintf(syscmd,"%s %s > %s",df_command,path,outfile);
  1920.       ret = smbrun(syscmd);
  1921.       DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
  1922.  
  1923.       {
  1924.     FILE *f = fopen(outfile,"r");    
  1925.     *dsize = 0;
  1926.     *dfree = 0;
  1927.     *bsize = 1024;
  1928.     if (f)
  1929.       {
  1930.         fscanf(f,"%d %d %d",dsize,dfree,bsize);
  1931.         fclose(f);
  1932.       }
  1933.     else
  1934.       DEBUG(0,("Can't open %s\n",outfile));
  1935.       }
  1936.  
  1937.       unlink(outfile);
  1938.     }
  1939.   else
  1940.     {
  1941. #ifdef STATFS4
  1942.       if (statfs(path,&fs,sizeof(fs),0) != 0)
  1943. #else
  1944. #ifdef USE_STATVFS
  1945.     if (statvfs(path, &fs))
  1946. #else
  1947. #ifdef STATFS3
  1948.       if (statfs(path,&fs,sizeof(fs)) == -1)     
  1949. #else
  1950.       if (statfs(path,&fs) == -1)
  1951. #endif /* STATFS3 */
  1952. #endif /* USE_STATVFS */
  1953. #endif /* STATFS4 */
  1954.         {
  1955.           DEBUG(3,("dfree call failed code errno=%d\n",errno));
  1956.           *bsize = 0;
  1957.           *dfree = 0;
  1958.           *dsize = 0;
  1959.         }
  1960.       else
  1961.         {
  1962. #ifdef ULTRIX
  1963.           *bsize = 1024;
  1964.           *dfree = fs.fd_req.bfree;
  1965.           *dsize = fs.fd_req.btot;
  1966. #else
  1967. #ifdef USE_STATVFS
  1968.           *bsize = fs.f_frsize;
  1969. #else
  1970. #ifdef USE_F_FSIZE
  1971.           /* eg: osf1 has f_fsize = fundamental filesystem block size, 
  1972.          f_bsize = optimal transfer block size (MX: 94-04-19) */
  1973.               *bsize = fs.f_fsize;
  1974. #else
  1975. /* sun appears to be broken - (noticed by jra@vantive.com) */
  1976. #if defined(SUN) && !defined(sun386) /* Only appears to be wrong for SunOS4.x */
  1977.           *bsize = 1024;
  1978. #else
  1979.           *bsize = fs.f_bsize;
  1980. #endif
  1981. #endif /* STATFS3 */
  1982. #endif /* USE_STATVFS */
  1983. #ifdef STATFS4
  1984.           *dfree = fs.f_bfree;
  1985. #else
  1986.           *dfree = fs.f_bavail;
  1987. #endif /* STATFS4 */
  1988.           *dsize = fs.f_blocks;
  1989. #endif /* ULTRIX */
  1990. #ifdef SCO
  1991.           /* Workaround bug in SCO ODT 2.0 and 3.0.
  1992.            * (It returns the filesystem block size in bsize,
  1993.            * but returns bfree and blocks in 512-byte units!)
  1994.            */
  1995.           *bsize = 512;
  1996. #endif
  1997. /* sun appears to be broken - (noticed by jra@vantive.com) */
  1998. #ifdef SUN
  1999.           *bsize = 1024;
  2000. #endif
  2001. #ifdef MIPS
  2002.           *bsize = 512;
  2003. #endif
  2004.     }
  2005.     }
  2006.   
  2007.   /* normalise for DOS usage */
  2008.   while (*dfree > WORDMAX || *dsize > WORDMAX) 
  2009.     {
  2010.       *dfree /= 2;
  2011.       *dsize /= 2;
  2012.       *bsize *= 2;
  2013.       if (*bsize > WORDMAX )
  2014.     {
  2015.       *bsize = WORDMAX;
  2016.       if (*dsize > WORDMAX)
  2017.         *dsize = WORDMAX;
  2018.       if (*dfree >  WORDMAX)
  2019.         *dfree = WORDMAX;
  2020.       break;
  2021.     }
  2022.     }
  2023. }
  2024.  
  2025.  
  2026. /****************************************************************************
  2027. print a file - called on closing the file
  2028. ****************************************************************************/
  2029. void print_file(int fnum)
  2030. {
  2031.   pstring syscmd="";
  2032.   int cnum = Files[fnum].cnum;
  2033.   char *tempstr;
  2034.  
  2035.   tempstr = build_print_command(SNUM(cnum), PRINTCOMMAND(SNUM(cnum)), syscmd, Files[fnum].name);
  2036.   if (tempstr != NULL)
  2037.     {
  2038.       int ret = smbrun(syscmd);
  2039.       DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
  2040.     }
  2041.   else
  2042.     DEBUG(0,("Null print command?\n"));
  2043. }
  2044.  
  2045.  
  2046.  
  2047.  
  2048.  
  2049.  
  2050.  
  2051.  
  2052.  
  2053.  
  2054.  
  2055.  
  2056. /****************************************************************************
  2057. run a file if it is a magic script
  2058. ****************************************************************************/
  2059. void check_magic(int fnum,int cnum)
  2060. {
  2061.   DEBUG(5,("checking magic for %s\n",Files[fnum].name));
  2062.  
  2063.   if (!*lp_magicscript(SNUM(cnum)))
  2064.     return;
  2065.  
  2066.   {
  2067.     char *p;
  2068.     if (!(p = strrchr(Files[fnum].name,'/')))
  2069.       p = Files[fnum].name;
  2070.     else
  2071.       p++;
  2072.  
  2073.     if (!strequal(lp_magicscript(SNUM(cnum)),p))
  2074.       return;
  2075.   }
  2076.  
  2077.   {
  2078.     int ret;
  2079.     pstring command;
  2080.     pstring magic_output;
  2081.     pstring fname;
  2082.     strcpy(fname,Files[fnum].name);
  2083.  
  2084.     if (*lp_magicoutput(SNUM(cnum)))
  2085.       strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
  2086.     else
  2087.       sprintf(magic_output,"%s.out",fname);
  2088.  
  2089.     sprintf(command,"%s %s > %s",
  2090.         SHELL_PATH,
  2091.         fname,
  2092.         magic_output);
  2093.  
  2094.     ret = smbrun(command);
  2095.     DEBUG(3,("Invoking magic command %s gave %d\n",command,ret));
  2096.     unlink(fname);
  2097.   }
  2098. }
  2099.  
  2100.  
  2101.  
  2102.  
  2103. /****************************************************************************
  2104. close all open files for a connection
  2105. ****************************************************************************/
  2106. void close_open_files(int cnum)
  2107. {
  2108.   int i;
  2109.   for (i=0;i<MAX_OPEN_FILES;i++)
  2110.     if( Files[i].cnum == cnum && Files[i].open) {
  2111.       close_file(i);
  2112.     }
  2113. }
  2114.  
  2115.  
  2116.  
  2117. /****************************************************************************
  2118. close a cnum
  2119. ****************************************************************************/
  2120. void close_cnum(int cnum)
  2121. {
  2122.   extern struct from_host Client_info;
  2123.  
  2124.   unbecome_user();
  2125.  
  2126.   if (!OPEN_CNUM(cnum))
  2127.     {
  2128.       DEBUG(0,("Can't close cnum %d\n",cnum));
  2129.       return;
  2130.     }
  2131.  
  2132.   DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
  2133.               timestring(),
  2134.               Client_info.name,Client_info.addr,
  2135.               lp_servicename(SNUM(cnum))));
  2136.  
  2137.   yield_connection(cnum,
  2138.            lp_servicename(SNUM(cnum)),
  2139.            lp_max_connections(SNUM(cnum)));
  2140.  
  2141.   if (lp_status(SNUM(cnum)))
  2142.     yield_connection(cnum,"STATUS.",100000);
  2143.  
  2144.   close_open_files(cnum);
  2145.   Connections[cnum].open = False;
  2146.   if (Connections[cnum].ngroups && Connections[cnum].groups)
  2147.     {
  2148.       if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
  2149.     free(Connections[cnum].groups);
  2150.       free(Connections[cnum].igroups);
  2151.       Connections[cnum].groups = NULL;
  2152.       Connections[cnum].igroups = NULL;
  2153.       Connections[cnum].ngroups = 0;
  2154.     }
  2155. }
  2156.  
  2157.  
  2158. /****************************************************************************
  2159. simple routines to do connection counting
  2160. ****************************************************************************/
  2161. BOOL yield_connection(int cnum,char *name,int max_connections)
  2162. {
  2163.   struct connect_record crec;
  2164.   pstring fname;
  2165.   FILE *f;
  2166.   int mypid = getpid();
  2167.   int i;
  2168.  
  2169.   DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
  2170.  
  2171.   if (max_connections <= 0)
  2172.     return(True);
  2173.  
  2174.   strcpy(fname,lp_lockdir());
  2175.   trim_string(fname,"","/");
  2176.  
  2177.   strcat(fname,"/");
  2178.   strcat(fname,name);
  2179.   strcat(fname,".LCK");
  2180.  
  2181.   f = fopen(fname,"r+");
  2182.   if (!f)
  2183.     {
  2184.       DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
  2185.       return(False);
  2186.     }
  2187.  
  2188.   /* find a free spot */
  2189.   for (i=0;i<max_connections;i++)
  2190.     {
  2191.       if (fread(&crec,sizeof(crec),1,f) != 1)
  2192.     {
  2193.       DEBUG(2,("Entry not found in lock file %s\n",fname));
  2194.       fclose(f);
  2195.       return(False);
  2196.     }
  2197.       if (crec.pid == mypid && crec.cnum == cnum)
  2198.     break;
  2199.     }
  2200.  
  2201.   if (crec.pid != mypid || crec.cnum != cnum)
  2202.     {
  2203.       fclose(f);
  2204.       DEBUG(2,("Entry not found in lock file %s\n",fname));
  2205.       return(False);
  2206.     }
  2207.  
  2208.   memset(&crec,0,sizeof(crec));
  2209.   
  2210.   /* remove our mark */
  2211.   if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
  2212.       fwrite(&crec,sizeof(crec),1,f) != 1)
  2213.     {
  2214.       DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
  2215.       fclose(f);
  2216.       return(False);
  2217.     }
  2218.  
  2219.   DEBUG(3,("Yield successful\n"));
  2220.  
  2221.   fclose(f);
  2222.   return(True);
  2223. }
  2224.  
  2225.  
  2226. /****************************************************************************
  2227. simple routines to do connection counting
  2228. ****************************************************************************/
  2229. BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
  2230. {
  2231.   struct connect_record crec;
  2232.   pstring fname;
  2233.   FILE *f;
  2234.   int snum = SNUM(cnum);
  2235.   int i,foundi=-1;
  2236.  
  2237.   DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
  2238.  
  2239.   if (max_connections <= 0)
  2240.     return(True);
  2241.  
  2242.   strcpy(fname,lp_lockdir());
  2243.   trim_string(fname,"","/");
  2244.  
  2245.   if (!directory_exist(fname))
  2246.     mkdir(fname,0755);
  2247.  
  2248.   strcat(fname,"/");
  2249.   strcat(fname,name);
  2250.   strcat(fname,".LCK");
  2251.  
  2252.   if (!file_exist(fname))
  2253.     {
  2254.       f = fopen(fname,"w");
  2255.       if (f) fclose(f);
  2256.     }
  2257.  
  2258.  
  2259.   f = fopen(fname,"r+");
  2260.  
  2261.   if (!f)
  2262.     {
  2263.       DEBUG(1,("couldn't open lock file %s\n",fname));
  2264.       return(False);
  2265.     }
  2266.  
  2267.   /* find a free spot */
  2268.   for (i=0;i<max_connections;i++)
  2269.     {
  2270.       if (fread(&crec,sizeof(crec),1,f) != 1)
  2271.     {
  2272.       foundi = i;
  2273.       break;
  2274.     }
  2275.  
  2276.       DEBUG(3,("got pid %d at position %d\n",crec.pid,i));
  2277.       if (Clear && crec.pid && !process_exists(crec.pid))
  2278.     {
  2279.       fseek(f,-sizeof(crec),SEEK_CUR);
  2280.       memset(&crec,0,sizeof(crec));
  2281.       fwrite(&crec,sizeof(crec),1,f);
  2282.       if (foundi < 0) foundi = i;
  2283.       continue;
  2284.     }
  2285.       if (foundi >= 0) continue;
  2286.       if (foundi < 0 && (crec.pid == 0 || !process_exists(crec.pid)))
  2287.     {
  2288.       foundi=i;
  2289.       if (!Clear) break;
  2290.     }
  2291.     }  
  2292.  
  2293.   if (foundi < 0)
  2294.     {
  2295.       DEBUG(3,("no free locks in %s\n",fname));
  2296.       fclose(f);
  2297.       return(False);
  2298.     }      
  2299.  
  2300.   /* fill in the crec */
  2301.   memset(&crec,0,sizeof(crec));
  2302.   crec.magic = 0x280267;
  2303.   crec.pid = getpid();
  2304.   crec.cnum = cnum;
  2305.   crec.uid = Connections[cnum].uid;
  2306.   crec.gid = Connections[cnum].gid;
  2307.   StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
  2308.   crec.start = time(NULL) + GMT_TO_LOCAL*TimeDiff();
  2309.   {
  2310.     extern struct from_host Client_info;
  2311.     StrnCpy(crec.machine,Client_info.name,sizeof(crec.machine)-1);
  2312.     StrnCpy(crec.addr,Client_info.addr,sizeof(crec.addr)-1);
  2313.   }
  2314.   
  2315.   /* make our mark */
  2316.   if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
  2317.       fwrite(&crec,sizeof(crec),1,f) != 1)
  2318.     {
  2319.       fclose(f);
  2320.       return(False);
  2321.     }
  2322.  
  2323.   fclose(f);
  2324.   return(True);
  2325. }
  2326.  
  2327. /****************************************************************************
  2328. exit the server
  2329. ****************************************************************************/
  2330. void exit_server(void)
  2331. {
  2332.   int i;
  2333.   DEBUG(3,("%s Server exit\n",timestring()));
  2334.   for (i=0;i<MAX_CONNECTIONS;i++)
  2335.     if (Connections[i].open)
  2336.       close_cnum(i);
  2337.   exit(0);
  2338. }
  2339.  
  2340. /****************************************************************************
  2341. Build the print command in the supplied buffer. This means getting the
  2342. print command for the service and inserting the printer name and the
  2343. print file name. Return NULL on error, else the passed buffer pointer.
  2344. ****************************************************************************/
  2345. static char *build_print_command(int snum, char *command, char *syscmd, char *filename1)
  2346. {
  2347.    char *tstr;
  2348.    int iOffset;
  2349.    pstring filename;
  2350.  
  2351.    /* get the print command for the service. */
  2352.    tstr = command;
  2353.    if (tstr == NULL)
  2354.    {
  2355.       DEBUG(0,("No print command for service `%s'\n", SERVICE(snum)));
  2356.       return (NULL);
  2357.    }
  2358.  
  2359.    /* copy the command into the buffer for extensive meddling. */
  2360.    strcpy(syscmd, tstr);
  2361.  
  2362.    /* look for "%s" in the string. If there is no %s, we cannot print. */   
  2363.    if (!strstr(syscmd, "%s"))
  2364.    {
  2365.       DEBUG(0,("No placeholder for the filename in the print command "
  2366.               "for service %s!\n", SERVICE(snum)));
  2367.       return (NULL);
  2368.    }
  2369.  
  2370.    iOffset = strstr(syscmd, "%s") - syscmd;
  2371.  
  2372.    /* construct the full path for the filename, shouldn't be necessary unless
  2373.       the subshell causes a "cd" to be executed.
  2374.       Only use the full path if there isn't a / preceding the %s */
  2375.    if (iOffset==0 || syscmd[iOffset-1] != '/')
  2376.      {
  2377.        strcpy(filename,lp_pathname(snum));
  2378.        trim_string(filename,"","/");
  2379.        strcat(filename,"/");
  2380.        strcat(filename,filename1);
  2381.      }
  2382.    else
  2383.      strcpy(filename,filename1);
  2384.  
  2385.  
  2386.    string_sub(syscmd, "%s", filename);
  2387.  
  2388.    /* Does the service have a printername? If not, make a fake and empty    */
  2389.    /* printer name. That way a %p is treated sanely if no printer */
  2390.    /* name was specified to replace it. This eventuality is logged.         */
  2391.    tstr = PRINTERNAME(snum);
  2392.    if (tstr == NULL || tstr[0] == '\0')
  2393.    {
  2394.       DEBUG(3,( "No printer name - using %s.\n", SERVICE(snum)));
  2395.       tstr = SERVICE(snum);
  2396.    }
  2397.  
  2398.    string_sub(syscmd, "%p", tstr);
  2399.  
  2400.    return (syscmd);
  2401. }
  2402.  
  2403.  
  2404.  
  2405. /****************************************************************************
  2406. parse a lpq line
  2407.  
  2408. here is an example of lpq output under sunos
  2409.  
  2410. Only lines after the Rank get to this routine
  2411.  
  2412. Warning: no daemon present
  2413. Rank   Owner      Job  Files                                 Total Size
  2414. 1st    tridge     148  README                                8096 bytes
  2415. ****************************************************************************/
  2416. BOOL parse_lpq_entry(char *line,print_queue_struct *buf,BOOL first)
  2417. {
  2418.   char owner[50]="";
  2419.   char fname[50]="";
  2420.   int jobid = 0;
  2421.   int size = 0;
  2422.   pstring dummy;
  2423.   
  2424.   if (sscanf(line,"%s%s%d%s%d",dummy,owner,&jobid,fname,&size) < 5) 
  2425.   {
  2426.     if (sscanf(line,"%s%s%d (standard input) %d",dummy,owner,&jobid,&size) < 3) 
  2427.       return(False);
  2428.     strcpy(fname,"Stdin");
  2429.   }
  2430.  
  2431.   buf->job = jobid;
  2432.   buf->size = size;
  2433.   buf->status = first?LPQ_PRINTING:LPQ_QUEUED;
  2434.   buf->time = time(NULL) + GMT_TO_LOCAL*TimeDiff();
  2435.   StrnCpy(buf->user,owner,sizeof(buf->user)-1);
  2436.   StrnCpy(buf->file,fname,sizeof(buf->file)-1);
  2437.   return(True);
  2438. }
  2439.  
  2440.  
  2441.  
  2442.  
  2443. /****************************************************************************
  2444. get a printer queue
  2445. ****************************************************************************/
  2446. int get_printqueue(int snum,print_queue_struct **queue)
  2447. {
  2448.   char *lpq_command = lp_lpqcommand(snum);
  2449.   char *printername = PRINTERNAME(snum);
  2450.   int ret=0,count=0;
  2451.   BOOL foundrank=False;
  2452.   pstring syscmd;
  2453.   pstring outfile;
  2454.   pstring line="";
  2455.   FILE *f;
  2456.  
  2457.   if (!printername || !*printername)
  2458.     printername = "lp";
  2459.     
  2460.   if (!lpq_command || !(*lpq_command))
  2461.     {
  2462.       DEBUG(5,("No lpq command\n"));
  2463.       return(0);
  2464.     }
  2465.     
  2466.   sprintf(outfile,"/tmp/lpq.smb.%d",getpid());
  2467.  
  2468.   strcpy(syscmd,lpq_command);
  2469.   if (!string_sub(syscmd,"%p",printername))
  2470.     {
  2471.       strcat(syscmd," ");
  2472.       strcat(syscmd,printername);
  2473.     }
  2474.  
  2475.   strcat(syscmd," > ");
  2476.   strcat(syscmd,outfile);
  2477.  
  2478.   ret = smbrun(syscmd);
  2479.   DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
  2480.   
  2481.   f = fopen(outfile,"r");
  2482.   if (!f)
  2483.     return(0);
  2484.       
  2485.   /* read lines until we get one starting with "Rank" */
  2486.   while (!foundrank && !feof(f))
  2487.     {
  2488.       if (fgets(line,sizeof(pstring),f))
  2489.     {
  2490.       DEBUG(6,("QUEUE1: %s\n",line));
  2491.       if (strncmp(line,"Rank",strlen("Rank")) == 0)
  2492.         foundrank = True;
  2493.     }
  2494.     }
  2495.       
  2496.   if (foundrank)
  2497.     {      
  2498.       while (fgets(line,sizeof(pstring),f))
  2499.     {
  2500.       DEBUG(6,("QUEUE2: %s\n",line));
  2501.  
  2502.       *queue = Realloc(*queue,sizeof(print_queue_struct)*(count+1));
  2503.       if (! *queue)
  2504.         {
  2505.           count = 0;
  2506.           break;
  2507.         }
  2508.       
  2509.       /* parse it */
  2510.       if (!parse_lpq_entry(line,&(*queue)[count],count==0))
  2511.         break;
  2512.       
  2513.       count++;
  2514.     }          
  2515.     }
  2516.   else
  2517.     DEBUG(5,("Didn't find keyword Rank\n"));
  2518.   
  2519.   fclose(f);
  2520.   unlink(outfile);
  2521.   
  2522.   return(count);
  2523. }
  2524.  
  2525.  
  2526.  
  2527.  
  2528. /*
  2529. These flags determine some of the permissions required to do an operation 
  2530.  
  2531. Note that I don't set NEED_WRITE on some write operations because they
  2532. are used by some brain-dead clients when printing, and I don't want to
  2533. force write permissions on print services.
  2534. */
  2535. #define AS_USER (1<<0)
  2536. #define NEED_WRITE (1<<1)
  2537. #define TIME_INIT (1<<2)
  2538.  
  2539. /* 
  2540.    define a list of possible SMB messages and their corresponding
  2541.    functions. Any message that has a NULL function is unimplemented -
  2542.    please feel free to contribute implementations!
  2543. */
  2544. struct smb_message_struct
  2545. {
  2546.   int code;
  2547.   char *name;
  2548.   int (*fn)();
  2549.   int flags;
  2550. #if PROFILING
  2551.   unsigned long time;
  2552. #endif
  2553. }
  2554.  smb_messages[] = {
  2555.  
  2556.     /* CORE PROTOCOL */
  2557.  
  2558.    {SMBnegprot,"SMBnegprot",reply_negprot,0},
  2559.    {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
  2560.    {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
  2561.    {SMBtcon,"SMBtcon",reply_tcon,0},
  2562.    {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
  2563.    {SMBsearch,"SMBsearch",reply_search,AS_USER},
  2564.    {SMBopen,"SMBopen",reply_open,AS_USER},
  2565.  
  2566.    /* note that SMBmknew and SMBcreate are deliberately overloaded */   
  2567.    {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
  2568.    {SMBmknew,"SMBmknew",reply_mknew,AS_USER}, 
  2569.  
  2570.    {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
  2571.    {SMBread,"SMBread",reply_read,AS_USER},
  2572.    {SMBwrite,"SMBwrite",reply_write,AS_USER},
  2573.    {SMBclose,"SMBclose",reply_close,AS_USER},
  2574.    {SMBtdis,"SMBtdis",reply_tdis,0},
  2575.    {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
  2576.    {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
  2577.    {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
  2578.    {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
  2579.  
  2580.    /* this is a Pathworks specific call, allowing the 
  2581.       changing of the root path */
  2582.    {pSETDIR,"pSETDIR",reply_setdir,AS_USER}, 
  2583.  
  2584.    {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
  2585.    {SMBflush,"SMBflush",reply_flush,AS_USER},
  2586.    {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
  2587.    {SMBexit,"SMBexit",reply_exit,0},
  2588.    {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
  2589.    {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
  2590.    {SMBsplretq,"SMBsplretq",reply_printqueue,0},
  2591.    {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
  2592.    {SMBlock,"SMBlock",reply_lock,AS_USER},
  2593.    {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
  2594.    
  2595.    /* CORE+ PROTOCOL FOLLOWS */
  2596.    
  2597.    {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
  2598.    {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
  2599.    {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
  2600.    {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
  2601.    {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
  2602.    
  2603.    /* LANMAN1.0 PROTOCOL FOLLOWS */
  2604.    
  2605.    {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
  2606.    {SMBreadBs,"SMBreadBs",NULL,AS_USER},
  2607.    {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
  2608.    {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
  2609.    {SMBwritec,"SMBwritec",NULL,AS_USER},
  2610.    {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
  2611.    {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
  2612.    {SMBtrans,"SMBtrans",reply_trans,AS_USER},
  2613.    {SMBtranss,"SMBtranss",NULL,AS_USER},
  2614.    {SMBioctl,"SMBioctl",reply_ioctl,0},
  2615.    {SMBioctls,"SMBioctls",NULL,AS_USER},
  2616.    {SMBcopy,"SMBcopy",NULL,AS_USER},
  2617.    {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
  2618.    
  2619.    {SMBecho,"SMBecho",reply_echo,0},
  2620.    {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER},
  2621.    {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
  2622.    {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
  2623.    {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
  2624.    {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
  2625.    {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
  2626.    
  2627.    {SMBffirst,"SMBffirst",reply_search,AS_USER},
  2628.    {SMBfunique,"SMBfunique",reply_search,AS_USER},
  2629.    {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
  2630.  
  2631.    /* LANMAN2.0 PROTOCOL FOLLOWS */
  2632.    {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
  2633.    {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
  2634.    {SMBulogoffX, "SMBulogoffX", NULL, AS_USER}, /* Not implemented (yet) */
  2635.    {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
  2636.    {SMBtranss2, "SMBtranss2", NULL, AS_USER},
  2637.  
  2638.    /* messaging routines */
  2639. #if 0
  2640.    {SMBsends,"SMBsends",test_sends,AS_USER},
  2641.    {SMBsendstrt,"SMBsendstrt",string_start,AS_USER},
  2642.    {SMBsendend,"SMBsendend",string_stop,AS_USER},
  2643.    {SMBsendtxt,"SMBsendtxt",string_text,AS_USER},
  2644. #else
  2645.    {SMBsends,"SMBsends",NULL,AS_USER},
  2646.    {SMBsendstrt,"SMBsendstrt",NULL,AS_USER},
  2647.    {SMBsendend,"SMBsendend",NULL,AS_USER},
  2648.    {SMBsendtxt,"SMBsendtxt",NULL,AS_USER},
  2649. #endif   
  2650.    /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
  2651.    
  2652.    {SMBsendb,"SMBsendb",NULL,AS_USER},
  2653.    {SMBfwdname,"SMBfwdname",NULL,AS_USER},
  2654.    {SMBcancelf,"SMBcancelf",NULL,AS_USER},
  2655.    {SMBgetmac,"SMBgetmac",NULL,AS_USER}
  2656.  };
  2657.  
  2658. /****************************************************************************
  2659. return a string containing the function name of a SMB command
  2660. ****************************************************************************/
  2661. char *smb_fn_name(int type)
  2662. {
  2663.   static char *unknown_name = "SMBunknown";
  2664.   static int num_smb_messages = 
  2665.     sizeof(smb_messages) / sizeof(struct smb_message_struct);
  2666.   int match;
  2667.  
  2668.   for (match=0;match<num_smb_messages;match++)
  2669.     if (smb_messages[match].code == type)
  2670.       break;
  2671.  
  2672.   if (match == num_smb_messages)
  2673.     return(unknown_name);
  2674.  
  2675.   return(smb_messages[match].name);
  2676. }
  2677.  
  2678.  
  2679. /****************************************************************************
  2680. do a switch on the message type, and return the response size
  2681. ****************************************************************************/
  2682. int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
  2683. {
  2684.   int outsize = 0;
  2685.   static int num_smb_messages = 
  2686.     sizeof(smb_messages) / sizeof(struct smb_message_struct);
  2687.   int match;
  2688. #if PROFILING
  2689.   struct timeval msg_start_time;
  2690.   struct timeval msg_end_time;
  2691.   static unsigned long total_time = 0;
  2692.  
  2693.   gettimeofday(&msg_start_time,NULL);
  2694. #endif
  2695.  
  2696.   errno = 0;
  2697.   last_message = type;
  2698.  
  2699.   for (match=0;match<num_smb_messages;match++)
  2700.     if (smb_messages[match].code == type)
  2701.       break;
  2702.  
  2703.   if (match == num_smb_messages)
  2704.     {
  2705.       DEBUG(0,("Unknown message type %d!\n",type));
  2706.       outsize = reply_unknown(inbuf,outbuf);
  2707.     }
  2708.   else
  2709.     {
  2710.       DEBUG(3,("switch message %s\n",smb_messages[match].name));
  2711.       if (smb_messages[match].fn)
  2712.     {
  2713.       int cnum = SVAL(inbuf,smb_tid);
  2714.       int flags = smb_messages[match].flags;
  2715.  
  2716.       /* does this protocol need to be run as root? */
  2717.       if (!(flags & AS_USER) && (done_become_user != -1))
  2718.         unbecome_user();
  2719.  
  2720.       /* does this protocl need to be run as the connected user? */
  2721.       if ((flags & AS_USER) && !become_user(cnum))
  2722.         return(ERROR(ERRSRV,ERRinvnid));
  2723.  
  2724.       /* does it need write permission? */
  2725.       if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
  2726.         return(ERROR(ERRSRV,ERRaccess));
  2727.  
  2728.       /* load service specific parameters */
  2729.       become_service(cnum);
  2730.  
  2731.       outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
  2732.     }
  2733.       else
  2734.     outsize = reply_unknown(inbuf,outbuf);
  2735.     }
  2736.  
  2737. #if PROFILING
  2738.   gettimeofday(&msg_end_time,NULL);
  2739.   if (!(smb_messages[match].flags & TIME_INIT))
  2740.     {
  2741.       smb_messages[match].time = 0;
  2742.       smb_messages[match].flags |= TIME_INIT;
  2743.     }
  2744.   {
  2745.     unsigned long this_time =     
  2746.       (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
  2747.     (msg_end_time.tv_usec - msg_start_time.tv_usec);
  2748.     smb_messages[match].time += this_time;
  2749.     total_time += this_time;
  2750.   }
  2751.   DEBUG(2,("TIME %s  %d usecs   %g pct\n",
  2752.        smb_fn_name(type),smb_messages[match].time,
  2753.     (100.0*smb_messages[match].time) / total_time));
  2754. #endif
  2755.  
  2756.   return(outsize);
  2757. }
  2758.  
  2759.  
  2760. /****************************************************************************
  2761. construct a chained reply and add it to the already made reply
  2762.  
  2763. inbuf points to the original message start.
  2764. inbuf2 points to the smb_wct part of the secondary message
  2765. type is the type of the secondary message
  2766. outbuf points to the original outbuffer
  2767. outbuf2 points to the smb_wct field of the new outbuffer
  2768. size is the total length of the incoming message (from inbuf1)
  2769. bufsize is the total buffer size
  2770.  
  2771. return how many bytes were added to the response
  2772. ****************************************************************************/
  2773. int chain_reply(int type,char *inbuf,char *inbuf2,char *outbuf,char *outbuf2,int size,int bufsize)
  2774. {
  2775.   int outsize = 0;
  2776.   char *ibuf,*obuf;
  2777.   static int chain_size_in = 0;
  2778.   static BOOL in_chain = False;
  2779.   static char *last_inbuf=NULL,*last_outbuf=NULL;
  2780.   BOOL was_inchain = in_chain;
  2781.  
  2782.   chain_size += ((int)outbuf2 - (int)outbuf) - smb_wct;
  2783.   if (was_inchain)
  2784.     {
  2785.       inbuf = last_inbuf;
  2786.       outbuf = last_outbuf;
  2787.     }
  2788.   else
  2789.     chain_size_in = 0;
  2790.  
  2791.   in_chain = True;
  2792.   last_inbuf = inbuf;
  2793.   last_outbuf = outbuf;
  2794.  
  2795.  
  2796.   inbuf2 -= chain_size_in;
  2797.  
  2798.   chain_size_in += ((int)inbuf2 - (int)inbuf) - smb_wct;
  2799.  
  2800.  
  2801.   /* allocate some space for the in and out buffers of the chained message */
  2802.   ibuf = (char *)malloc(size + SAFETY_MARGIN);
  2803.   obuf = (char *)malloc(bufsize + SAFETY_MARGIN);
  2804.  
  2805.   if (!ibuf || !obuf)
  2806.     {
  2807.       DEBUG(0,("Out of memory in chain reply\n"));
  2808.       return(ERROR(ERRSRV,ERRnoresource));
  2809.     }
  2810.  
  2811.   /* create the in buffer */
  2812.   memcpy(ibuf,inbuf,smb_wct);
  2813.   memcpy(ibuf+smb_wct,inbuf2,size-(int)(inbuf2-inbuf));
  2814.   CVAL(ibuf,smb_com) = type;
  2815.  
  2816.   /* create the out buffer */
  2817.   memset(obuf,0,smb_size);
  2818.  
  2819.   set_message(obuf,0,0,True);
  2820.   CVAL(obuf,smb_com) = CVAL(ibuf,smb_com);
  2821.   
  2822.   memcpy(obuf+4,ibuf+4,4);
  2823.   CVAL(obuf,smb_rcls) = SUCCESS;
  2824.   CVAL(obuf,smb_reh) = 0;
  2825.   CVAL(obuf,smb_flg) = 0x80 | (CVAL(ibuf,smb_flg) & 0x8); /* bit 7 set 
  2826.                                  means a reply */
  2827.   CVAL(obuf,smb_flg2) = (CVAL(ibuf,smb_flg2) & 1); /* say we support 
  2828.                               long filenames if 
  2829.                               he does */
  2830.   SSVAL(obuf,smb_err,SUCCESS);
  2831.   SSVAL(obuf,smb_tid,SVAL(inbuf,smb_tid));
  2832.   SSVAL(obuf,smb_pid,SVAL(inbuf,smb_pid));
  2833.   SSVAL(obuf,smb_uid,SVAL(inbuf,smb_uid));
  2834.   SSVAL(obuf,smb_mid,SVAL(inbuf,smb_mid));
  2835.  
  2836.   /* process the request */
  2837.   outsize = switch_message(type,ibuf,obuf,
  2838.                (size+smb_wct)-(int)(inbuf2-inbuf),
  2839.                bufsize);
  2840.  
  2841.   /* copy the new reply header over the old one, but preserve 
  2842.      the smb_com field */
  2843.   memcpy(outbuf+smb_com+1,obuf+smb_com+1,smb_wct-(smb_com+1));
  2844.  
  2845.   /* and copy the data from the reply to the right spot */
  2846.   memcpy(outbuf2,obuf+smb_wct,outsize - smb_wct);
  2847.  
  2848.   /* free the allocated buffers */
  2849.   if (ibuf) free(ibuf);
  2850.   if (obuf) free(obuf);
  2851.  
  2852.   in_chain = was_inchain;
  2853.  
  2854.   /* return how much extra has been added to the packet */
  2855.   return(outsize - smb_wct);
  2856. }
  2857.  
  2858.  
  2859.  
  2860. /****************************************************************************
  2861.   construct a reply to the incoming packet
  2862. ****************************************************************************/
  2863. int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
  2864. {
  2865.   int type = CVAL(inbuf,smb_com);
  2866.   int outsize = 0;
  2867.   int msg_type = CVAL(inbuf,0);
  2868.  
  2869.   chain_size = 0;
  2870.  
  2871.   if(Protocol >= PROTOCOL_LANMAN2)
  2872.     {
  2873.       if (lp_casesignames())
  2874.     casesignames = ((CVAL(inbuf,smb_flg) & 0x8) != 0x8);
  2875.       long_filenames = ((SVAL(inbuf, smb_flg2) & 0x1) != 0);
  2876.     }
  2877.   
  2878.   if (msg_type != 0)
  2879.     return(reply_special(inbuf,outbuf));
  2880.   
  2881.   memset(outbuf,0,smb_size);
  2882.  
  2883.   CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
  2884.   set_message(outbuf,0,0,True);
  2885.   
  2886.   memcpy(outbuf+4,inbuf+4,4);
  2887.   CVAL(outbuf,smb_rcls) = SUCCESS;
  2888.   CVAL(outbuf,smb_reh) = 0;
  2889.   CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set 
  2890.                                  means a reply */
  2891.   CVAL(outbuf,smb_flg2) = (CVAL(inbuf,smb_flg2) & 1); /* say we support 
  2892.                               long filenames if 
  2893.                               he does */
  2894.   SSVAL(outbuf,smb_err,SUCCESS);
  2895.   SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
  2896.   SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
  2897.   SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
  2898.   SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
  2899.  
  2900.   outsize = switch_message(type,inbuf,outbuf,size,bufsize);
  2901.  
  2902.   if(outsize != -1)
  2903.     smb_setlen(outbuf,outsize - 4);
  2904.   return(outsize);
  2905. }
  2906.  
  2907.  
  2908. /****************************************************************************
  2909.   process commands from the client
  2910. ****************************************************************************/
  2911. void process(void )
  2912. {
  2913.   static int trans_num = 0;
  2914.   int nread;
  2915.   
  2916.   InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  2917.   OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  2918.   if ((InBuffer == NULL) || (OutBuffer == NULL)) 
  2919.     return;
  2920.  
  2921.   DEBUG(3,("priming nmbd\n"));
  2922.   {
  2923.     struct in_addr ip;
  2924.     uint32 a = interpret_addr("localhost");
  2925.     memcpy(&ip,&a,4);
  2926.     *OutBuffer = 0;
  2927.     send_packet(OutBuffer,1,&ip,137,SOCK_DGRAM);
  2928.   }
  2929.     
  2930.   
  2931.   while (True)
  2932.     {
  2933.       int32 len;      
  2934.       int msg_type;
  2935.       int msg_flags;
  2936.       int type;
  2937.       static BOOL all_down = False;
  2938.       int deadtime = lp_deadtime()*60*1000;
  2939.  
  2940.       if (all_down) /* automatic 3 minute deadtime if all 
  2941.                connections are closed */
  2942.     deadtime = MAX(deadtime,180*1000);
  2943.  
  2944.       if (deadtime <= 0)
  2945.     deadtime = 1000*60*60*24*3; /* 3 days max timeout */
  2946.  
  2947.       if (lp_readprediction())
  2948.     do_read_prediction();
  2949.  
  2950.       if (done_become_user != -1)
  2951.     {
  2952.       if (!receive_smb(InBuffer,2*1000))
  2953.         {
  2954.           unbecome_user();
  2955.           if (!receive_smb(InBuffer,
  2956.                    ((all_down || num_files_open == 0)?deadtime:0)))
  2957.         return;
  2958.         }
  2959.     }
  2960.       else
  2961.     {
  2962.       if (!receive_smb(InBuffer,(num_files_open == 0?deadtime:0)))    
  2963.         return;
  2964.     }
  2965.  
  2966.       all_down = False;
  2967.  
  2968.       msg_type = CVAL(InBuffer,0);
  2969.       msg_flags = CVAL(InBuffer,1);
  2970.       type = CVAL(InBuffer,smb_com);
  2971.  
  2972.       len = smb_len(InBuffer);
  2973.  
  2974.       DEBUG(3,("got message type 0x%x of len 0x%x\n",msg_type,len));
  2975.  
  2976.       nread = len + 4;
  2977.       
  2978.       DEBUG(3,("%s Transaction %d\n",timestring(),trans_num));
  2979.  
  2980.       if (msg_type == 0)
  2981.     show_msg(InBuffer);
  2982.  
  2983.       nread = construct_reply(InBuffer,OutBuffer,nread,MIN(BUFFER_SIZE,lp_maxxmit()));
  2984.       
  2985.       if(nread > 0) {
  2986.         if (CVAL(OutBuffer,0) == 0)
  2987.       show_msg(OutBuffer);
  2988.     
  2989.         if (nread != smb_len(OutBuffer) + 4) 
  2990.       {
  2991.         DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
  2992.              nread,
  2993.              smb_len(OutBuffer)));
  2994.       }
  2995.     else
  2996.       send_smb(OutBuffer);
  2997.       }
  2998.       trans_num++;
  2999.  
  3000.       /* If we got a tree disconnect, see if this was the
  3001.      last one in use, if so - exit */
  3002.       if(lp_deadtime() == 0 && type == SMBtdis) 
  3003.     {
  3004.       int i;
  3005.       for(i=0;i<MAX_CONNECTIONS;i++)
  3006.         if(Connections[i].open) 
  3007.           break; /* Stay in loop */
  3008.  
  3009.       if(i == MAX_CONNECTIONS)
  3010.         {
  3011.           all_down = True;
  3012.           DEBUG(3,("Last connection closed\n"));
  3013.         }
  3014.     }
  3015.     }
  3016. }
  3017.  
  3018.  
  3019. /****************************************************************************
  3020.   initialise connect, service and file structs
  3021. ****************************************************************************/
  3022. void init_structs(void )
  3023. {
  3024.   int i;
  3025.   get_myname(myhostname,&myip);
  3026.  
  3027.   for (i=0;i<MAX_CONNECTIONS;i++)
  3028.     Connections[i].open = False;
  3029.   for (i=0;i<MAX_OPEN_FILES;i++)
  3030.     Files[i].open = False;
  3031.  
  3032.   num_files_open=0;
  3033.  
  3034.   init_dptrs();
  3035. }
  3036.  
  3037. /****************************************************************************
  3038. usage on the program
  3039. ****************************************************************************/
  3040. void usage(char *pname)
  3041. {
  3042.   DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
  3043.  
  3044.   printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
  3045.   printf("Version %s\n",VERSION);
  3046.   printf("\t-D                    become a daemon\n");
  3047.   printf("\t-p port               listen on the specified port\n");
  3048.   printf("\t-d debuglevel         set the debuglevel\n");
  3049.   printf("\t-l log basename.      Basename for log/debug files\n");
  3050.   printf("\t-s services file.     Filename of services file\n");
  3051.   printf("\t-P                    passive only\n");
  3052.   printf("\t-a                    overwrite log file, don't append\n");
  3053.   printf("\n");
  3054. }
  3055.  
  3056.  
  3057. /****************************************************************************
  3058.   main program
  3059. ****************************************************************************/
  3060. int main(int argc,char *argv[])
  3061. {
  3062.   /* shall I run as a daemon */
  3063.   BOOL is_daemon = False;
  3064.   int port = 139;
  3065.   int opt;
  3066.   extern FILE *dbf;
  3067.   extern char *optarg;
  3068.  
  3069. #ifdef SecureWare
  3070.   set_auth_parameters(argc,argv);
  3071.   setluid(0);
  3072. #endif
  3073.  
  3074. #ifdef OSF1_ENH_SEC
  3075.   set_auth_parameters();
  3076. #endif
  3077.  
  3078.   sprintf(debugf,"%s.debug",DEBUGFILE);  
  3079.  
  3080.   umask(0777 & ~DEF_CREATE_MASK);
  3081.  
  3082.   initial_uid = geteuid();
  3083.   initial_gid = getegid();
  3084.  
  3085.   if (initial_gid != 0 && initial_uid == 0)
  3086.     {
  3087. #ifdef HPUX
  3088.       setresgid(0,0,0);
  3089. #else
  3090.       setgid(0);
  3091.       setegid(0);
  3092. #endif
  3093.     }
  3094.  
  3095.   initial_uid = geteuid();
  3096.   initial_gid = getegid();
  3097.  
  3098.   while ((opt = getopt (argc, argv, "i:l:s:d:Dp:hPa")) != EOF)
  3099.     switch (opt)
  3100.       {
  3101.       case 'i':
  3102.     strcpy(scope,optarg);
  3103.     break;
  3104.       case 'P':
  3105.     {
  3106.       extern BOOL passive;
  3107.       passive = True;
  3108.     }
  3109.     break;    
  3110.       case 's':
  3111.     strcpy(servicesf,optarg);
  3112.     break;
  3113.       case 'l':
  3114.     sprintf(debugf,"%s.debug",optarg);
  3115.     break;
  3116.       case 'a':
  3117.     append_log = !append_log;
  3118.     break;
  3119.       case 'D':
  3120.     is_daemon = True;
  3121.     break;
  3122.       case 'd':
  3123.     if (*optarg == 'A')
  3124.       DEBUGLEVEL = 10000;
  3125.     else
  3126.       DEBUGLEVEL = atoi(optarg);
  3127.     break;
  3128.       case 'p':
  3129.     port = atoi(optarg);
  3130.     break;
  3131.       case 'h':
  3132.     usage(argv[0]);
  3133.     exit(0);
  3134.     break;
  3135.       default:
  3136.     usage(argv[0]);
  3137.     exit(1);
  3138.       }
  3139.  
  3140.   
  3141.   NeedSwap = big_endian();
  3142.   
  3143.   if (DEBUGLEVEL > 100)
  3144.     {
  3145.       extern FILE *login,*logout;
  3146.       pstring fname="";
  3147.       sprintf(fname,"%s.in",debugf);
  3148.       login = fopen(fname,"w"); 
  3149.       if (login) chmod(fname,0600);
  3150.       sprintf(fname,"%s.out",debugf);
  3151.       logout = fopen(fname,"w");
  3152.       if (logout) chmod(fname,0600);
  3153.     }
  3154.   
  3155.   if (DEBUGLEVEL > 0)
  3156.     {
  3157.       if (dbf)
  3158.     fclose(dbf);
  3159.       if (append_log)
  3160.     dbf = fopen(debugf,"a");
  3161.       else
  3162.     dbf = fopen(debugf,"w");
  3163.       if (dbf)
  3164.     setbuf(dbf,NULL);
  3165.     }
  3166.  
  3167.   DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
  3168.   DEBUG(2,("Copyright Andrew Tridgell 1992,1993,1994\n"));
  3169.  
  3170.   GetWd(OriginalDir);
  3171.   get_machine_info();
  3172.   
  3173.   DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
  3174.     getuid(),getgid(),geteuid(),getegid()));
  3175.  
  3176.   if (sizeof(uint32) != 4 || sizeof(int32) != 4)
  3177.     DEBUG(0,("WARNING! Your machine is incorrectly setup.\nYou must define int32 and uint32 to be 4 byte quantities\n"));
  3178.   if (sizeof(uint16) != 2 || sizeof(int16) != 2)
  3179.     DEBUG(0,("WARNING! Your machine is incorrectly setup.\nYou must define int16 and uint16 to be 2 byte quantities\n"));
  3180.  
  3181.   init_structs();
  3182.  
  3183.   if (!lp_load(servicesf))
  3184.     return(-1);    
  3185.   
  3186.   if (DEBUGLEVEL > 1)
  3187.     DEBUG(3,("%s loaded services\n",timestring()));
  3188.  
  3189.   if (is_daemon)
  3190.     {
  3191.       DEBUG(3,("%s becoming a daemon\n",timestring()));
  3192.       become_daemon();
  3193.     }
  3194.  
  3195.   if (open_sockets(is_daemon,port))
  3196.     {
  3197.       /* reload the services file. It might have changed (if a daemon) */
  3198.       if (is_daemon && !lp_load(servicesf))
  3199.     return(-1);    
  3200.  
  3201.       if (*lp_rootdir())
  3202.     {
  3203.       chroot(lp_rootdir());
  3204.   
  3205.       if (DEBUGLEVEL > 1)
  3206.         DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
  3207.     }
  3208.  
  3209.       maxxmit = lp_maxxmit();
  3210.  
  3211.       create_mangled_stack(lp_mangledstack());
  3212.       {
  3213.     extern BOOL use_getwd_cache;
  3214.     use_getwd_cache = lp_getwdcache();
  3215.       }
  3216.       
  3217.       process();
  3218.       close_sockets();
  3219.     }
  3220.   exit_server();
  3221.   return(0);
  3222. }
  3223.  
  3224.  
  3225.