home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 July & August / Pcwk78a98.iso / Wtestowe / Clico / UNIX / SAMBA / SOURCE / SAMBA.TAR / samba-1.9.17 / source / server.c < prev    next >
C/C++ Source or Header  |  1997-08-22  |  119KB  |  4,356 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    Main SMB server routines
  5.    Copyright (C) Andrew Tridgell 1992-1997
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. #include "includes.h"
  23. #include "trans2.h"
  24.  
  25. pstring servicesf = CONFIGFILE;
  26. extern pstring debugf;
  27. extern pstring sesssetup_user;
  28. extern fstring myworkgroup;
  29.  
  30. char *InBuffer = NULL;
  31. char *OutBuffer = NULL;
  32. char *last_inbuf = NULL;
  33.  
  34. int am_parent = 1;
  35. int atexit_set = 0;
  36.  
  37. /* the last message the was processed */
  38. int last_message = -1;
  39.  
  40. /* a useful macro to debug the last message processed */
  41. #define LAST_MESSAGE() smb_fn_name(last_message)
  42.  
  43. extern pstring scope;
  44. extern int DEBUGLEVEL;
  45. extern int case_default;
  46. extern BOOL case_sensitive;
  47. extern BOOL case_preserve;
  48. extern BOOL use_mangled_map;
  49. extern BOOL short_case_preserve;
  50. extern BOOL case_mangle;
  51. extern time_t smb_last_time;
  52.  
  53. extern int smb_read_error;
  54.  
  55. extern pstring user_socket_options;
  56.  
  57. connection_struct Connections[MAX_CONNECTIONS];
  58. files_struct Files[MAX_OPEN_FILES];
  59.  
  60. /*
  61.  * Indirection for file fd's. Needed as POSIX locking
  62.  * is based on file/process, not fd/process.
  63.  */
  64. file_fd_struct FileFd[MAX_OPEN_FILES];
  65. int max_file_fd_used = 0;
  66.  
  67. extern int Protocol;
  68.  
  69. /* 
  70.  * Size of data we can send to client. Set
  71.  *  by the client for all protocols above CORE.
  72.  *  Set by us for CORE protocol.
  73.  */
  74. int max_send = BUFFER_SIZE;
  75. /*
  76.  * Size of the data we can receive. Set by us.
  77.  * Can be modified by the max xmit parameter.
  78.  */
  79. int max_recv = BUFFER_SIZE;
  80.  
  81. /* a fnum to use when chaining */
  82. int chain_fnum = -1;
  83.  
  84. /* number of open connections */
  85. static int num_connections_open = 0;
  86.  
  87. extern fstring remote_machine;
  88.  
  89. pstring OriginalDir;
  90.  
  91. /* these can be set by some functions to override the error codes */
  92. int unix_ERR_class=SUCCESS;
  93. int unix_ERR_code=0;
  94.  
  95.  
  96. extern int extra_time_offset;
  97.  
  98. extern pstring myhostname;
  99.  
  100. static int find_free_connection(int hash);
  101.  
  102. /* for readability... */
  103. #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
  104. #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
  105. #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
  106. #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
  107. #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
  108.  
  109. /****************************************************************************
  110.   when exiting, take the whole family
  111. ****************************************************************************/
  112. void  *dflt_sig(void)
  113. {
  114.   exit_server("caught signal");
  115.   return 0; /* Keep -Wall happy :-) */
  116. }
  117. /****************************************************************************
  118.   Send a SIGTERM to our process group.
  119. *****************************************************************************/
  120. void  killkids(void)
  121. {
  122.   if(am_parent) kill(0,SIGTERM);
  123. }
  124.  
  125. /****************************************************************************
  126.   change a dos mode to a unix mode
  127.     base permission for files:
  128.          everybody gets read bit set
  129.          dos readonly is represented in unix by removing everyone's write bit
  130.          dos archive is represented in unix by the user's execute bit
  131.          dos system is represented in unix by the group's execute bit
  132.          dos hidden is represented in unix by the other's execute bit
  133.          Then apply create mask,
  134.          then add force bits.
  135.     base permission for directories:
  136.          dos directory is represented in unix by unix's dir bit and the exec bit
  137.          Then apply create mask,
  138.          then add force bits.
  139. ****************************************************************************/
  140. mode_t unix_mode(int cnum,int dosmode)
  141. {
  142.   mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
  143.  
  144.   if ( !IS_DOS_READONLY(dosmode) )
  145.     result |= (S_IWUSR | S_IWGRP | S_IWOTH);
  146.  
  147.   if (IS_DOS_DIR(dosmode)) {
  148.     /* We never make directories read only for the owner as under DOS a user
  149.        can always create a file in a read-only directory. */
  150.     result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
  151.     /* Apply directory mask */
  152.     result &= lp_dir_mode(SNUM(cnum));
  153.     /* Add in force bits */
  154.     result |= lp_force_dir_mode(SNUM(cnum));
  155.   } else { 
  156.     if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
  157.       result |= S_IXUSR;
  158.  
  159.     if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
  160.       result |= S_IXGRP;
  161.  
  162.     if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
  163.       result |= S_IXOTH;  
  164.  
  165.     /* Apply mode mask */
  166.     result &= lp_create_mode(SNUM(cnum));
  167.     /* Add in force bits */
  168.     result |= lp_force_create_mode(SNUM(cnum));
  169.   }
  170.   return(result);
  171. }
  172.  
  173.  
  174. /****************************************************************************
  175.   change a unix mode to a dos mode
  176. ****************************************************************************/
  177. int dos_mode(int cnum,char *path,struct stat *sbuf)
  178. {
  179.   int result = 0;
  180.   extern struct current_user current_user;
  181.  
  182.   DEBUG(5,("dos_mode: %d %s\n", cnum, path));
  183.  
  184.   if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
  185.     if (!((sbuf->st_mode & S_IWOTH) ||
  186.       Connections[cnum].admin_user ||
  187.       ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) ||
  188.       ((sbuf->st_mode & S_IWGRP) && 
  189.        in_group(sbuf->st_gid,current_user.gid,
  190.             current_user.ngroups,current_user.igroups))))
  191.       result |= aRONLY;
  192.   } else {
  193.     if ((sbuf->st_mode & S_IWUSR) == 0)
  194.       result |= aRONLY;
  195.   }
  196.  
  197.   if (MAP_ARCHIVE(cnum) && ((sbuf->st_mode & S_IXUSR) != 0))
  198.     result |= aARCH;
  199.  
  200.   if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
  201.     result |= aSYSTEM;
  202.  
  203.   if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
  204.     result |= aHIDDEN;   
  205.   
  206.   if (S_ISDIR(sbuf->st_mode))
  207.     result = aDIR | (result & aRONLY);
  208.  
  209. #if LINKS_READ_ONLY
  210.   if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
  211.     result |= aRONLY;
  212. #endif
  213.  
  214.   /* hide files with a name starting with a . */
  215.   if (lp_hide_dot_files(SNUM(cnum)))
  216.     {
  217.       char *p = strrchr(path,'/');
  218.       if (p)
  219.     p++;
  220.       else
  221.     p = path;
  222.       
  223.       if (p[0] == '.' && p[1] != '.' && p[1] != 0)
  224.     result |= aHIDDEN;
  225.     }
  226.  
  227.   /* Optimization : Only call is_hidden_path if it's not already
  228.      hidden. */
  229.   if (!(result & aHIDDEN) && IS_HIDDEN_PATH(cnum,path))
  230.   {
  231.     result |= aHIDDEN;
  232.   }
  233.  
  234.   DEBUG(5,("dos_mode returning "));
  235.  
  236.   if (result & aHIDDEN) DEBUG(5, ("h"));
  237.   if (result & aRONLY ) DEBUG(5, ("r"));
  238.   if (result & aSYSTEM) DEBUG(5, ("s"));
  239.   if (result & aDIR   ) DEBUG(5, ("d"));
  240.   if (result & aARCH  ) DEBUG(5, ("a"));
  241.  
  242.   DEBUG(5,("\n"));
  243.  
  244.   return(result);
  245. }
  246.  
  247.  
  248. /*******************************************************************
  249. chmod a file - but preserve some bits
  250. ********************************************************************/
  251. int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
  252. {
  253.   struct stat st1;
  254.   int mask=0;
  255.   int tmp;
  256.   int unixmode;
  257.  
  258.   if (!st) {
  259.     st = &st1;
  260.     if (sys_stat(fname,st)) return(-1);
  261.   }
  262.  
  263.   if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
  264.  
  265.   if (dos_mode(cnum,fname,st) == dosmode) return(0);
  266.  
  267.   unixmode = unix_mode(cnum,dosmode);
  268.  
  269.   /* preserve the s bits */
  270.   mask |= (S_ISUID | S_ISGID);
  271.  
  272.   /* preserve the t bit */
  273. #ifdef S_ISVTX
  274.   mask |= S_ISVTX;
  275. #endif
  276.  
  277.   /* possibly preserve the x bits */
  278.   if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
  279.   if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
  280.   if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
  281.  
  282.   unixmode |= (st->st_mode & mask);
  283.  
  284.   /* if we previously had any r bits set then leave them alone */
  285.   if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
  286.     unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
  287.     unixmode |= tmp;
  288.   }
  289.  
  290.   /* if we previously had any w bits set then leave them alone 
  291.    if the new mode is not rdonly */
  292.   if (!IS_DOS_READONLY(dosmode) &&
  293.       (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
  294.     unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
  295.     unixmode |= tmp;
  296.   }
  297.  
  298.   return(sys_chmod(fname,unixmode));
  299. }
  300.  
  301.  
  302. /****************************************************************************
  303. check if two filenames are equal
  304.  
  305. this needs to be careful about whether we are case sensitive
  306. ****************************************************************************/
  307. static BOOL fname_equal(char *name1, char *name2)
  308. {
  309.   int l1 = strlen(name1);
  310.   int l2 = strlen(name2);
  311.  
  312.   /* handle filenames ending in a single dot */
  313.   if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
  314.     {
  315.       BOOL ret;
  316.       name1[l1-1] = 0;
  317.       ret = fname_equal(name1,name2);
  318.       name1[l1-1] = '.';
  319.       return(ret);
  320.     }
  321.  
  322.   if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
  323.     {
  324.       BOOL ret;
  325.       name2[l2-1] = 0;
  326.       ret = fname_equal(name1,name2);
  327.       name2[l2-1] = '.';
  328.       return(ret);
  329.     }
  330.  
  331.   /* now normal filename handling */
  332.   if (case_sensitive)
  333.     return(strcmp(name1,name2) == 0);
  334.  
  335.   return(strequal(name1,name2));
  336. }
  337.  
  338.  
  339. /****************************************************************************
  340. mangle the 2nd name and check if it is then equal to the first name
  341. ****************************************************************************/
  342. static BOOL mangled_equal(char *name1, char *name2)
  343. {
  344.   pstring tmpname;
  345.  
  346.   if (is_8_3(name2, True))
  347.     return(False);
  348.  
  349.   strcpy(tmpname,name2);
  350.   mangle_name_83(tmpname);
  351.  
  352.   return(strequal(name1,tmpname));
  353. }
  354.  
  355.  
  356. /****************************************************************************
  357. scan a directory to find a filename, matching without case sensitivity
  358.  
  359. If the name looks like a mangled name then try via the mangling functions
  360. ****************************************************************************/
  361. static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache)
  362. {
  363.   void *cur_dir;
  364.   char *dname;
  365.   BOOL mangled;
  366.   pstring name2;
  367.  
  368.   mangled = is_mangled(name);
  369.  
  370.   /* handle null paths */
  371.   if (*path == 0)
  372.     path = ".";
  373.  
  374.   if (docache && (dname = DirCacheCheck(path,name,SNUM(cnum)))) {
  375.     strcpy(name, dname);    
  376.     return(True);
  377.   }      
  378.  
  379.   if (mangled)
  380.     check_mangled_stack(name);
  381.  
  382.   /* open the directory */
  383.   if (!(cur_dir = OpenDir(cnum, path, True))) 
  384.     {
  385.       DEBUG(3,("scan dir didn't open dir [%s]\n",path));
  386.       return(False);
  387.     }
  388.  
  389.   /* now scan for matching names */
  390.   while ((dname = ReadDirName(cur_dir))) 
  391.     {
  392.       if (*dname == '.' &&
  393.       (strequal(dname,".") || strequal(dname,"..")))
  394.     continue;
  395.  
  396.       strcpy(name2,dname);
  397.       if (!name_map_mangle(name2,False,SNUM(cnum))) continue;
  398.  
  399.       if ((mangled && mangled_equal(name,name2))
  400.       || fname_equal(name, dname))
  401.     {
  402.       /* we've found the file, change it's name and return */
  403.       if (docache) DirCacheAdd(path,name,dname,SNUM(cnum));
  404.       strcpy(name, dname);
  405.       CloseDir(cur_dir);
  406.       return(True);
  407.     }
  408.     }
  409.  
  410.   CloseDir(cur_dir);
  411.   return(False);
  412. }
  413.  
  414. /****************************************************************************
  415. This routine is called to convert names from the dos namespace to unix
  416. namespace. It needs to handle any case conversions, mangling, format
  417. changes etc.
  418.  
  419. We assume that we have already done a chdir() to the right "root" directory
  420. for this service.
  421.  
  422. The function will return False if some part of the name except for the last
  423. part cannot be resolved
  424.  
  425. If the saved_last_component != 0, then the unmodified last component
  426. of the pathname is returned there. This is used in an exceptional
  427. case in reply_mv (so far). If saved_last_component == 0 then nothing
  428. is returned there.
  429.  
  430. The bad_path arg is set to True if the filename walk failed. This is
  431. used to pick the correct error code to return between ENOENT and ENOTDIR
  432. as Windows applications depend on ERRbadpath being returned if a component
  433. of a pathname does not exist.
  434. ****************************************************************************/
  435. BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_path)
  436. {
  437.   struct stat st;
  438.   char *start, *end;
  439.   pstring dirpath;
  440.   int saved_errno;
  441.  
  442.   *dirpath = 0;
  443.   *bad_path = False;
  444.  
  445.   if(saved_last_component)
  446.     *saved_last_component = 0;
  447.  
  448.   /* convert to basic unix format - removing \ chars and cleaning it up */
  449.   unix_format(name);
  450.   unix_clean_name(name);
  451.  
  452.   /* names must be relative to the root of the service - trim any leading /.
  453.    also trim trailing /'s */
  454.   trim_string(name,"/","/");
  455.  
  456.   /*
  457.    * Ensure saved_last_component is valid even if file exists.
  458.    */
  459.   if(saved_last_component) {
  460.     end = strrchr(name, '/');
  461.     if(end)
  462.       strcpy(saved_last_component, end + 1);
  463.     else
  464.       strcpy(saved_last_component, name);
  465.   }
  466.  
  467.   if (!case_sensitive && 
  468.       (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
  469.     strnorm(name);
  470.  
  471.   /* check if it's a printer file */
  472.   if (Connections[cnum].printer)
  473.     {
  474.       if ((! *name) || strchr(name,'/') || !is_8_3(name, True))
  475.     {
  476.       char *s;
  477.       fstring name2;
  478.       sprintf(name2,"%.6s.XXXXXX",remote_machine);
  479.       /* sanitise the name */
  480.       for (s=name2 ; *s ; s++)
  481.         if (!issafe(*s)) *s = '_';
  482.       strcpy(name,(char *)mktemp(name2));      
  483.     }      
  484.       return(True);
  485.     }
  486.  
  487.   /* stat the name - if it exists then we are all done! */
  488.   if (sys_stat(name,&st) == 0)
  489.     return(True);
  490.  
  491.   saved_errno = errno;
  492.  
  493.   DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
  494.  
  495.   /* a special case - if we don't have any mangling chars and are case
  496.      sensitive then searching won't help */
  497.   if (case_sensitive && !is_mangled(name) && 
  498.       !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT))
  499.     return(False);
  500.  
  501.   /* now we need to recursively match the name against the real 
  502.      directory structure */
  503.  
  504.   start = name;
  505.   while (strncmp(start,"./",2) == 0)
  506.     start += 2;
  507.  
  508.   /* now match each part of the path name separately, trying the names
  509.      as is first, then trying to scan the directory for matching names */
  510.   for (;start;start = (end?end+1:(char *)NULL)) 
  511.     {
  512.       /* pinpoint the end of this section of the filename */
  513.       end = strchr(start, '/');
  514.  
  515.       /* chop the name at this point */
  516.       if (end)     *end = 0;
  517.  
  518.       if(saved_last_component != 0)
  519.         strcpy(saved_last_component, end ? end + 1 : start);
  520.  
  521.       /* check if the name exists up to this point */
  522.       if (sys_stat(name, &st) == 0) 
  523.     {
  524.       /* it exists. it must either be a directory or this must be
  525.          the last part of the path for it to be OK */
  526.       if (end && !(st.st_mode & S_IFDIR)) 
  527.         {
  528.           /* an intermediate part of the name isn't a directory */
  529.           DEBUG(5,("Not a dir %s\n",start));
  530.           *end = '/';
  531.           return(False);
  532.         }
  533.     }
  534.       else 
  535.     {
  536.       pstring rest;
  537.  
  538.       *rest = 0;
  539.  
  540.       /* remember the rest of the pathname so it can be restored
  541.          later */
  542.       if (end) strcpy(rest,end+1);
  543.  
  544.       /* try to find this part of the path in the directory */
  545.       if (strchr(start,'?') || strchr(start,'*') ||
  546.           !scan_directory(dirpath, start, cnum, end?True:False))
  547.         {
  548.           if (end) 
  549.         {
  550.           /* an intermediate part of the name can't be found */
  551.           DEBUG(5,("Intermediate not found %s\n",start));
  552.           *end = '/';
  553.                   /* We need to return the fact that the intermediate
  554.                      name resolution failed. This is used to return an
  555.                      error of ERRbadpath rather than ERRbadfile. Some
  556.                      Windows applications depend on the difference between
  557.                      these two errors.
  558.                    */
  559.                   *bad_path = True;
  560.           return(False);
  561.         }
  562.           
  563.           /* just the last part of the name doesn't exist */
  564.           /* we may need to strupper() or strlower() it in case
  565.          this conversion is being used for file creation 
  566.          purposes */
  567.           /* if the filename is of mixed case then don't normalise it */
  568.           if (!case_preserve && 
  569.           (!strhasupper(start) || !strhaslower(start)))        
  570.         strnorm(start);
  571.  
  572.           /* check on the mangled stack to see if we can recover the 
  573.          base of the filename */
  574.           if (is_mangled(start))
  575.         check_mangled_stack(start);
  576.  
  577.           DEBUG(5,("New file %s\n",start));
  578.           return(True); 
  579.         }
  580.  
  581.       /* restore the rest of the string */
  582.       if (end) 
  583.         {
  584.           strcpy(start+strlen(start)+1,rest);
  585.           end = start + strlen(start);
  586.         }
  587.     }
  588.  
  589.       /* add to the dirpath that we have resolved so far */
  590.       if (*dirpath) strcat(dirpath,"/");
  591.       strcat(dirpath,start);
  592.  
  593.       /* restore the / that we wiped out earlier */
  594.       if (end) *end = '/';
  595.     }
  596.   
  597.   /* the name has been resolved */
  598.   DEBUG(5,("conversion finished %s\n",name));
  599.   return(True);
  600. }
  601.  
  602.  
  603. /****************************************************************************
  604. normalise for DOS usage 
  605. ****************************************************************************/
  606. static void disk_norm(int *bsize,int *dfree,int *dsize)
  607. {
  608.   /* check if the disk is beyond the max disk size */
  609.   int maxdisksize = lp_maxdisksize();
  610.   if (maxdisksize) {
  611.     /* convert to blocks - and don't overflow */
  612.     maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
  613.     if (*dsize > maxdisksize) *dsize = maxdisksize;
  614.     if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop 
  615.                              applications getting 
  616.                              div by 0 errors */
  617.   }  
  618.  
  619.   while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512) 
  620.     {
  621.       *dfree /= 2;
  622.       *dsize /= 2;
  623.       *bsize *= 2;
  624.       if (*bsize > WORDMAX )
  625.     {
  626.       *bsize = WORDMAX;
  627.       if (*dsize > WORDMAX)
  628.         *dsize = WORDMAX;
  629.       if (*dfree >  WORDMAX)
  630.         *dfree = WORDMAX;
  631.       break;
  632.     }
  633.     }
  634. }
  635.  
  636. /****************************************************************************
  637.   return number of 1K blocks available on a path and total number 
  638. ****************************************************************************/
  639. int disk_free(char *path,int *bsize,int *dfree,int *dsize)
  640. {
  641.   char *df_command = lp_dfree_command();
  642.   int dfree_retval;
  643. #ifdef QUOTAS
  644.   int dfreeq_retval;
  645.   int dfreeq = 0;
  646.   int bsizeq = *bsize;
  647.   int dsizeq = *dsize;
  648. #endif
  649.  
  650. #ifndef NO_STATFS
  651. #ifdef USE_STATVFS
  652.   struct statvfs fs;
  653. #else
  654. #ifdef ULTRIX
  655.   struct fs_data fs;
  656. #else
  657.   struct statfs fs;
  658. #endif
  659. #endif
  660. #endif
  661.  
  662.   /* possibly use system() to get the result */
  663.   if (df_command && *df_command)
  664.     {
  665.       int ret;
  666.       pstring syscmd;
  667.       pstring outfile;
  668.       
  669.       sprintf(outfile,"%s/dfree.smb.%d",tmpdir(),(int)getpid());
  670.       sprintf(syscmd,"%s %s",df_command,path);
  671.       standard_sub_basic(syscmd);
  672.  
  673.       ret = smbrun(syscmd,outfile,False);
  674.       DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
  675.       
  676.       {
  677.         FILE *f = fopen(outfile,"r");    
  678.         *dsize = 0;
  679.         *dfree = 0;
  680.         *bsize = 1024;
  681.         if (f)
  682.           {
  683.             fscanf(f,"%d %d %d",dsize,dfree,bsize);
  684.             fclose(f);
  685.           }
  686.         else
  687.           DEBUG(0,("Can't open %s\n",outfile));
  688.       }
  689.       
  690.       unlink(outfile);
  691.       disk_norm(bsize,dfree,dsize);
  692.       dfree_retval = ((*bsize)/1024)*(*dfree);
  693. #ifdef QUOTAS
  694.       /* Ensure we return the min value between the users quota and
  695.          what's free on the disk. Thanks to Albrecht Gebhardt 
  696.          <albrecht.gebhardt@uni-klu.ac.at> for this fix.
  697.       */
  698.       if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
  699.         {
  700.           disk_norm(&bsizeq, &dfreeq, &dsizeq);
  701.           dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
  702.           dfree_retval =  ( dfree_retval < dfreeq_retval ) ? 
  703.                            dfree_retval : dfreeq_retval ;
  704.           /* maybe dfree and dfreeq are calculated using different bsizes 
  705.              so convert dfree from bsize into bsizeq */
  706.           *dfree = ((*dfree) * (*bsize)) / (bsizeq);
  707.           *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; 
  708.           *bsize = bsizeq;
  709.           *dsize = dsizeq;
  710.         }
  711. #endif
  712.       return(dfree_retval);
  713.     }
  714.  
  715. #ifdef NO_STATFS
  716.   DEBUG(1,("Warning - no statfs function\n"));
  717.   return(1);
  718. #else
  719. #ifdef STATFS4
  720.   if (statfs(path,&fs,sizeof(fs),0) != 0)
  721. #else
  722. #ifdef USE_STATVFS
  723.     if (statvfs(path, &fs))
  724. #else
  725. #ifdef STATFS3
  726.       if (statfs(path,&fs,sizeof(fs)) == -1)     
  727. #else
  728.     if (statfs(path,&fs) == -1)
  729. #endif /* STATFS3 */
  730. #endif /* USE_STATVFS */
  731. #endif /* STATFS4 */
  732.       {
  733.         DEBUG(3,("dfree call failed code errno=%d\n",errno));
  734.         *bsize = 1024;
  735.         *dfree = 1;
  736.         *dsize = 1;
  737.         return(((*bsize)/1024)*(*dfree));
  738.       }
  739.  
  740. #ifdef ULTRIX
  741.   *bsize = 1024;
  742.   *dfree = fs.fd_req.bfree;
  743.   *dsize = fs.fd_req.btot;
  744. #else
  745. #ifdef USE_STATVFS
  746.   *bsize = fs.f_frsize;
  747. #else
  748. #ifdef USE_F_FSIZE
  749.   /* eg: osf1 has f_fsize = fundamental filesystem block size, 
  750.      f_bsize = optimal transfer block size (MX: 94-04-19) */
  751.   *bsize = fs.f_fsize;
  752. #else
  753.   *bsize = fs.f_bsize;
  754. #endif /* STATFS3 */
  755. #endif /* USE_STATVFS */
  756.  
  757. #ifdef STATFS4
  758.   *dfree = fs.f_bfree;
  759. #else
  760.   *dfree = fs.f_bavail;
  761. #endif /* STATFS4 */
  762.   *dsize = fs.f_blocks;
  763. #endif /* ULTRIX */
  764.  
  765. #if defined(SCO) || defined(ISC) || defined(MIPS)
  766.   *bsize = 512;
  767. #endif
  768.  
  769. /* handle rediculous bsize values - some OSes are broken */
  770. if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
  771.  
  772.   disk_norm(bsize,dfree,dsize);
  773.  
  774.   if (*bsize < 256)
  775.     *bsize = 512;
  776.   if ((*dsize)<1)
  777.     {
  778.       DEBUG(0,("dfree seems to be broken on your system\n"));
  779.       *dsize = 20*1024*1024/(*bsize);
  780.       *dfree = MAX(1,*dfree);
  781.     }
  782.   dfree_retval = ((*bsize)/1024)*(*dfree);
  783. #ifdef QUOTAS
  784.   /* Ensure we return the min value between the users quota and
  785.      what's free on the disk. Thanks to Albrecht Gebhardt 
  786.      <albrecht.gebhardt@uni-klu.ac.at> for this fix.
  787.   */
  788.   if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
  789.     {
  790.       disk_norm(&bsizeq, &dfreeq, &dsizeq);
  791.       dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
  792.       dfree_retval = ( dfree_retval < dfreeq_retval ) ? 
  793.                        dfree_retval : dfreeq_retval ;
  794.       /* maybe dfree and dfreeq are calculated using different bsizes 
  795.          so convert dfree from bsize into bsizeq */
  796.       *dfree = ((*dfree) * (*bsize)) / (bsizeq);
  797.       *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
  798.       *bsize = bsizeq;
  799.       *dsize = dsizeq;
  800.     }
  801. #endif
  802.   return(dfree_retval);
  803. #endif
  804. }
  805.  
  806.  
  807. /****************************************************************************
  808. wrap it to get filenames right
  809. ****************************************************************************/
  810. int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
  811. {
  812.   return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
  813. }
  814.  
  815.  
  816.  
  817. /****************************************************************************
  818. check a filename - possibly caling reducename
  819.  
  820. This is called by every routine before it allows an operation on a filename.
  821. It does any final confirmation necessary to ensure that the filename is
  822. a valid one for the user to access.
  823. ****************************************************************************/
  824. BOOL check_name(char *name,int cnum)
  825. {
  826.   BOOL ret;
  827.  
  828.   errno = 0;
  829.  
  830.   if( IS_VETO_PATH(cnum, name)) 
  831.     {
  832.       DEBUG(5,("file path name %s vetoed\n",name));
  833.       return(0);
  834.     }
  835.  
  836.   ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
  837.  
  838.   /* Check if we are allowing users to follow symlinks */
  839.   /* Patch from David Clerc <David.Clerc@cui.unige.ch>
  840.      University of Geneva */
  841.  
  842.   if (!lp_symlinks(SNUM(cnum)))
  843.     {
  844.       struct stat statbuf;
  845.       if ( (sys_lstat(name,&statbuf) != -1) &&
  846.           (S_ISLNK(statbuf.st_mode)) )
  847.         {
  848.           DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name));
  849.           ret=0; 
  850.         }
  851.     }
  852.  
  853.   if (!ret)
  854.     DEBUG(5,("check_name on %s failed\n",name));
  855.  
  856.   return(ret);
  857. }
  858.  
  859. /****************************************************************************
  860. check a filename - possibly caling reducename
  861. ****************************************************************************/
  862. static void check_for_pipe(char *fname)
  863. {
  864.   /* special case of pipe opens */
  865.   char s[10];
  866.   StrnCpy(s,fname,9);
  867.   strlower(s);
  868.   if (strstr(s,"pipe/"))
  869.     {
  870.       DEBUG(3,("Rejecting named pipe open for %s\n",fname));
  871.       unix_ERR_class = ERRSRV;
  872.       unix_ERR_code = ERRaccess;
  873.     }
  874. }
  875.  
  876. /****************************************************************************
  877. fd support routines - attempt to do a sys_open
  878. ****************************************************************************/
  879.  
  880. int fd_attempt_open(char *fname, int flags, int mode)
  881. {
  882.   int fd = sys_open(fname,flags,mode);
  883.  
  884.   /* Fix for files ending in '.' */
  885.   if((fd == -1) && (errno == ENOENT) &&
  886.      (strchr(fname,'.')==NULL))
  887.     {
  888.       strcat(fname,".");
  889.       fd = sys_open(fname,flags,mode);
  890.     }
  891.  
  892. #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
  893.   if ((fd == -1) && (errno == ENAMETOOLONG))
  894.     {
  895.       int max_len;
  896.       char *p = strrchr(fname, '/');
  897.  
  898.       if (p == fname)   /* name is "/xxx" */
  899.         {
  900.           max_len = pathconf("/", _PC_NAME_MAX);
  901.           p++;
  902.         }
  903.       else if ((p == NULL) || (p == fname))
  904.         {
  905.           p = fname;
  906.           max_len = pathconf(".", _PC_NAME_MAX);
  907.         }
  908.       else
  909.         {
  910.           *p = '\0';
  911.           max_len = pathconf(fname, _PC_NAME_MAX);
  912.           *p = '/';
  913.           p++;
  914.         }
  915.       if (strlen(p) > max_len)
  916.         {
  917.           char tmp = p[max_len];
  918.  
  919.           p[max_len] = '\0';
  920.           if ((fd = sys_open(fname,flags,mode)) == -1)
  921.             p[max_len] = tmp;
  922.         }
  923.     }
  924. #endif
  925.   return fd;
  926. }
  927.  
  928. /****************************************************************************
  929. fd support routines - attempt to find an already open file by dev
  930. and inode - increments the ref_count of the returned file_fd_struct *.
  931. ****************************************************************************/
  932. file_fd_struct *fd_get_already_open(struct stat *sbuf)
  933. {
  934.   int i;
  935.   file_fd_struct *fd_ptr;
  936.  
  937.   if(sbuf == 0)
  938.     return 0;
  939.  
  940.   for(i = 0; i <= max_file_fd_used; i++) {
  941.     fd_ptr = &FileFd[i];
  942.     if((fd_ptr->ref_count > 0) &&
  943.        (((uint32)sbuf->st_dev) == fd_ptr->dev) &&
  944.        (((uint32)sbuf->st_ino) == fd_ptr->inode)) {
  945.       fd_ptr->ref_count++;
  946.       DEBUG(3,
  947.        ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n",
  948.         i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count));
  949.       return fd_ptr;
  950.     }
  951.   }
  952.   return 0;
  953. }
  954.  
  955. /****************************************************************************
  956. fd support routines - attempt to find a empty slot in the FileFd array.
  957. Increments the ref_count of the returned entry.
  958. ****************************************************************************/
  959. file_fd_struct *fd_get_new()
  960. {
  961.   int i;
  962.   file_fd_struct *fd_ptr;
  963.  
  964.   for(i = 0; i < MAX_OPEN_FILES; i++) {
  965.     fd_ptr = &FileFd[i];
  966.     if(fd_ptr->ref_count == 0) {
  967.       fd_ptr->dev = (uint32)-1;
  968.       fd_ptr->inode = (uint32)-1;
  969.       fd_ptr->fd = -1;
  970.       fd_ptr->fd_readonly = -1;
  971.       fd_ptr->fd_writeonly = -1;
  972.       fd_ptr->real_open_flags = -1;
  973.       fd_ptr->ref_count++;
  974.       /* Increment max used counter if neccessary, cuts down
  975.      on search time when re-using */
  976.       if(i > max_file_fd_used)
  977.         max_file_fd_used = i;
  978.       DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n",
  979.                i, fd_ptr->dev, fd_ptr->inode));
  980.       return fd_ptr;
  981.     }
  982.   }
  983.   DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\
  984. n"));
  985.   return 0;
  986. }
  987.  
  988. /****************************************************************************
  989. fd support routines - attempt to re-open an already open fd as O_RDWR.
  990. Save the already open fd (we cannot close due to POSIX file locking braindamage.
  991. ****************************************************************************/
  992.  
  993. void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
  994. {
  995.   int fd = sys_open( fname, O_RDWR, mode);
  996.  
  997.   if(fd == -1)
  998.     return;
  999.  
  1000.   if(fd_ptr->real_open_flags == O_RDONLY)
  1001.     fd_ptr->fd_readonly = fd_ptr->fd;
  1002.   if(fd_ptr->real_open_flags == O_WRONLY)
  1003.     fd_ptr->fd_writeonly = fd_ptr->fd;
  1004.  
  1005.   fd_ptr->fd = fd;
  1006.   fd_ptr->real_open_flags = O_RDWR;
  1007. }
  1008.  
  1009. /****************************************************************************
  1010. fd support routines - attempt to close the file referenced by this fd.
  1011. Decrements the ref_count and returns it.
  1012. ****************************************************************************/
  1013. int fd_attempt_close(file_fd_struct *fd_ptr)
  1014. {
  1015.   DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n",
  1016.        fd_ptr - &FileFd[0],
  1017.        fd_ptr->fd, fd_ptr->dev, fd_ptr->inode,
  1018.        fd_ptr->real_open_flags,
  1019.        fd_ptr->ref_count));
  1020.   if(fd_ptr->ref_count > 0) {
  1021.     fd_ptr->ref_count--;
  1022.     if(fd_ptr->ref_count == 0) {
  1023.       if(fd_ptr->fd != -1)
  1024.         close(fd_ptr->fd);
  1025.       if(fd_ptr->fd_readonly != -1)
  1026.     close(fd_ptr->fd_readonly);
  1027.       if(fd_ptr->fd_writeonly != -1)
  1028.     close(fd_ptr->fd_writeonly);
  1029.       fd_ptr->fd = -1;
  1030.       fd_ptr->fd_readonly = -1;
  1031.       fd_ptr->fd_writeonly = -1;
  1032.       fd_ptr->real_open_flags = -1;
  1033.       fd_ptr->dev = (uint32)-1;
  1034.       fd_ptr->inode = (uint32)-1;
  1035.     }
  1036.   } 
  1037.  return fd_ptr->ref_count;
  1038. }
  1039.  
  1040. /****************************************************************************
  1041. open a file
  1042. ****************************************************************************/
  1043. static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf)
  1044. {
  1045.   extern struct current_user current_user;
  1046.   pstring fname;
  1047.   struct stat statbuf;
  1048.   file_fd_struct *fd_ptr;
  1049.  
  1050.   Files[fnum].open = False;
  1051.   Files[fnum].fd_ptr = 0;
  1052.   errno = EPERM;
  1053.  
  1054.   strcpy(fname,fname1);
  1055.  
  1056.   /* check permissions */
  1057.   if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
  1058.     {
  1059.       DEBUG(3,("Permission denied opening %s\n",fname));
  1060.       check_for_pipe(fname);
  1061.       return;
  1062.     }
  1063.  
  1064.   /* this handles a bug in Win95 - it doesn't say to create the file when it 
  1065.      should */
  1066.   if (Connections[cnum].printer)
  1067.     flags |= O_CREAT;
  1068.  
  1069. /*
  1070.   if (flags == O_WRONLY)
  1071.     DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
  1072. */
  1073.  
  1074. #if UTIME_WORKAROUND
  1075.   /* XXXX - is this OK?? */
  1076.   /* this works around a utime bug but can cause other problems */
  1077.   if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
  1078.     sys_unlink(fname);
  1079. #endif
  1080.  
  1081.   /*
  1082.    * Ensure we have a valid struct stat so we can search the
  1083.    * open fd table.
  1084.    */
  1085.   if(sbuf == 0) {
  1086.     if(stat(fname, &statbuf) < 0) {
  1087.       if(errno != ENOENT) {
  1088.         DEBUG(3,("Error doing stat on file %s (%s)\n",
  1089.                  fname,strerror(errno)));
  1090.  
  1091.         check_for_pipe(fname);
  1092.         return;
  1093.       }
  1094.       sbuf = 0;
  1095.     } else {
  1096.       sbuf = &statbuf;
  1097.     }
  1098.   }
  1099.  
  1100.   /*
  1101.    * Check to see if we have this file already
  1102.    * open. If we do, just use the already open fd and increment the
  1103.    * reference count (fd_get_already_open increments the ref_count).
  1104.    */
  1105.   if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
  1106.  
  1107.     int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
  1108.  
  1109.     /* File was already open. */
  1110.     if((flags & O_CREAT) && (flags & O_EXCL)) {
  1111.       fd_ptr->ref_count--;
  1112.       errno = EEXIST;
  1113.       return;
  1114.     }
  1115.  
  1116.     /* 
  1117.      * If not opened O_RDWR try
  1118.      * and do that here - a chmod may have been done
  1119.      * between the last open and now. 
  1120.      */
  1121.     if(fd_ptr->real_open_flags != O_RDWR)
  1122.       fd_attempt_reopen(fname, mode, fd_ptr);
  1123.  
  1124.     /*
  1125.      * Ensure that if we wanted write access
  1126.      * it has been opened for write, and if we wanted read it
  1127.      * was open for read. 
  1128.      */
  1129.     if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) ||
  1130.        ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) ||
  1131.        ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) {
  1132.       DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n",
  1133.                fd_ptr->real_open_flags, fname,strerror(EACCES),flags));
  1134.       check_for_pipe(fname);
  1135.       fd_ptr->ref_count--;
  1136.       return;
  1137.     }
  1138.  
  1139.   } else {
  1140.     int open_flags;
  1141.     /* We need to allocate a new file_fd_struct (this increments the
  1142.        ref_count). */
  1143.     if((fd_ptr = fd_get_new()) == 0)
  1144.       return;
  1145.     /*
  1146.      * Whatever the requested flags, attempt read/write access,
  1147.      * as we don't know what flags future file opens may require.
  1148.      * If this fails, try again with the required flags. 
  1149.      * Even if we open read/write when only read access was 
  1150.      * requested the setting of the can_write flag in
  1151.      * the file_struct will protect us from errant
  1152.      * write requests. We never need to worry about O_APPEND
  1153.      * as this is not set anywhere in Samba.
  1154.      */
  1155.     fd_ptr->real_open_flags = O_RDWR;
  1156.     /* Set the flags as needed without the read/write modes. */
  1157.     open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY);
  1158.     fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode);
  1159.     /*
  1160.      * On some systems opening a file for R/W access on a read only
  1161.      * filesystems sets errno to EROFS.
  1162.      */
  1163. #ifdef EROFS
  1164.     if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) {
  1165. #else /* No EROFS */
  1166.     if((fd_ptr->fd == -1) && (errno == EACCES)) {
  1167. #endif /* EROFS */
  1168.       if(flags & O_WRONLY) {
  1169.         fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode);
  1170.         fd_ptr->real_open_flags = O_WRONLY;
  1171.       } else {
  1172.     fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode);
  1173.         fd_ptr->real_open_flags = O_RDONLY;
  1174.       }
  1175.     }
  1176.   }
  1177.  
  1178.   if ((fd_ptr->fd >=0) && 
  1179.       Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
  1180.     pstring dname;
  1181.     int dum1,dum2,dum3;
  1182.     char *p;
  1183.     strcpy(dname,fname);
  1184.     p = strrchr(dname,'/');
  1185.     if (p) *p = 0;
  1186.     if (sys_disk_free(dname,&dum1,&dum2,&dum3) < 
  1187.     lp_minprintspace(SNUM(cnum))) {
  1188.       fd_attempt_close(fd_ptr);
  1189.       Files[fnum].fd_ptr = 0;
  1190.       if(fd_ptr->ref_count == 0)
  1191.         sys_unlink(fname);
  1192.       errno = ENOSPC;
  1193.       return;
  1194.     }
  1195.   }
  1196.     
  1197.   if (fd_ptr->fd < 0)
  1198.     {
  1199.       DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
  1200.            fname,strerror(errno),flags));
  1201.       /* Ensure the ref_count is decremented. */
  1202.       fd_attempt_close(fd_ptr);
  1203.       check_for_pipe(fname);
  1204.       return;
  1205.     }
  1206.  
  1207.   if (fd_ptr->fd >= 0)
  1208.     {
  1209.       if(sbuf == 0) {
  1210.         /* Do the fstat */
  1211.         if(fstat(fd_ptr->fd, &statbuf) == -1) {
  1212.           /* Error - backout !! */
  1213.           DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
  1214.                    fd_ptr->fd, fname,strerror(errno)));
  1215.           /* Ensure the ref_count is decremented. */
  1216.           fd_attempt_close(fd_ptr);
  1217.           return;
  1218.         }
  1219.         sbuf = &statbuf;
  1220.       }
  1221.       /* Set the correct entries in fd_ptr. */
  1222.       fd_ptr->dev = (uint32)sbuf->st_dev;
  1223.       fd_ptr->inode = (uint32)sbuf->st_ino;
  1224.  
  1225.       Files[fnum].fd_ptr = fd_ptr;
  1226.       Connections[cnum].num_files_open++;
  1227.       Files[fnum].mode = sbuf->st_mode;
  1228.       GetTimeOfDay(&Files[fnum].open_time);
  1229.       Files[fnum].uid = current_user.id;
  1230.       Files[fnum].size = 0;
  1231.       Files[fnum].pos = -1;
  1232.       Files[fnum].open = True;
  1233.       Files[fnum].mmap_ptr = NULL;
  1234.       Files[fnum].mmap_size = 0;
  1235.       Files[fnum].can_lock = True;
  1236.       Files[fnum].can_read = ((flags & O_WRONLY)==0);
  1237.       Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
  1238.       Files[fnum].share_mode = 0;
  1239.       Files[fnum].print_file = Connections[cnum].printer;
  1240.       Files[fnum].modified = False;
  1241.       Files[fnum].cnum = cnum;
  1242.       string_set(&Files[fnum].name,dos_to_unix(fname,False));
  1243.       Files[fnum].wbmpx_ptr = NULL;      
  1244.  
  1245.       /*
  1246.        * If the printer is marked as postscript output a leading
  1247.        * file identifier to ensure the file is treated as a raw
  1248.        * postscript file.
  1249.        * This has a similar effect as CtrlD=0 in WIN.INI file.
  1250.        * tim@fsg.com 09/06/94
  1251.        */
  1252.       if (Files[fnum].print_file && POSTSCRIPT(cnum) && 
  1253.       Files[fnum].can_write) 
  1254.     {
  1255.       DEBUG(3,("Writing postscript line\n"));
  1256.       write_file(fnum,"%!\n",3);
  1257.     }
  1258.       
  1259.       DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
  1260.            timestring(),Connections[cnum].user,fname,
  1261.            BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
  1262.            Connections[cnum].num_files_open,fnum));
  1263.  
  1264.     }
  1265.  
  1266. #if USE_MMAP
  1267.   /* mmap it if read-only */
  1268.   if (!Files[fnum].can_write)
  1269.     {
  1270.       Files[fnum].mmap_size = file_size(fname);
  1271.       Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
  1272.                       PROT_READ,MAP_SHARED,Files[fnum].fd_ptr->fd,0);
  1273.  
  1274.       if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
  1275.     {
  1276.       DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
  1277.       Files[fnum].mmap_ptr = NULL;
  1278.     }
  1279.     }
  1280. #endif
  1281. }
  1282.  
  1283. /*******************************************************************
  1284. sync a file
  1285. ********************************************************************/
  1286. void sync_file(int fnum)
  1287. {
  1288. #ifndef NO_FSYNC
  1289.   fsync(Files[fnum].fd_ptr->fd);
  1290. #endif
  1291. }
  1292.  
  1293. /****************************************************************************
  1294. run a file if it is a magic script
  1295. ****************************************************************************/
  1296. static void check_magic(int fnum,int cnum)
  1297. {
  1298.   if (!*lp_magicscript(SNUM(cnum)))
  1299.     return;
  1300.  
  1301.   DEBUG(5,("checking magic for %s\n",Files[fnum].name));
  1302.  
  1303.   {
  1304.     char *p;
  1305.     if (!(p = strrchr(Files[fnum].name,'/')))
  1306.       p = Files[fnum].name;
  1307.     else
  1308.       p++;
  1309.  
  1310.     if (!strequal(lp_magicscript(SNUM(cnum)),p))
  1311.       return;
  1312.   }
  1313.  
  1314.   {
  1315.     int ret;
  1316.     pstring magic_output;
  1317.     pstring fname;
  1318.     strcpy(fname,Files[fnum].name);
  1319.  
  1320.     if (*lp_magicoutput(SNUM(cnum)))
  1321.       strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
  1322.     else
  1323.       sprintf(magic_output,"%s.out",fname);
  1324.  
  1325.     chmod(fname,0755);
  1326.     ret = smbrun(fname,magic_output,False);
  1327.     DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
  1328.     unlink(fname);
  1329.   }
  1330. }
  1331.  
  1332.  
  1333. /****************************************************************************
  1334. close a file - possibly invalidating the read prediction
  1335. ****************************************************************************/
  1336. void close_file(int fnum)
  1337. {
  1338.   files_struct *fs_p = &Files[fnum];
  1339.   int cnum = fs_p->cnum;
  1340.   uint32 dev = fs_p->fd_ptr->dev;
  1341.   uint32 inode = fs_p->fd_ptr->inode;
  1342.   share_lock_token token;
  1343.  
  1344.   invalidate_read_prediction(fs_p->fd_ptr->fd);
  1345.   fs_p->open = False;
  1346.   Connections[cnum].num_files_open--;
  1347.   if(fs_p->wbmpx_ptr) 
  1348.     {
  1349.       free((char *)fs_p->wbmpx_ptr);
  1350.       fs_p->wbmpx_ptr = NULL;
  1351.     }
  1352.  
  1353. #if USE_MMAP
  1354.   if(fs_p->mmap_ptr) 
  1355.     {
  1356.       munmap(fs_p->mmap_ptr,fs_p->mmap_size);
  1357.       fs_p->mmap_ptr = NULL;
  1358.     }
  1359. #endif
  1360.  
  1361.   if (lp_share_modes(SNUM(cnum)))
  1362.   {
  1363.     lock_share_entry( cnum, dev, inode, &token);
  1364.     del_share_mode(token, fnum);
  1365.   }
  1366.  
  1367.   fd_attempt_close(fs_p->fd_ptr);
  1368.  
  1369.   if (lp_share_modes(SNUM(cnum)))
  1370.     unlock_share_entry( cnum, dev, inode, token);
  1371.  
  1372.   /* NT uses smbclose to start a print - weird */
  1373.   if (fs_p->print_file)
  1374.     print_file(fnum);
  1375.  
  1376.   /* check for magic scripts */
  1377.   check_magic(fnum,cnum);
  1378.  
  1379.   DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
  1380.        timestring(),Connections[cnum].user,fs_p->name,
  1381.        Connections[cnum].num_files_open));
  1382. }
  1383.  
  1384. enum {AFAIL,AREAD,AWRITE,AALL};
  1385.  
  1386. /*******************************************************************
  1387. reproduce the share mode access table
  1388. ********************************************************************/
  1389. static int access_table(int new_deny,int old_deny,int old_mode,
  1390.             int share_pid,char *fname)
  1391. {
  1392.   if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
  1393.  
  1394.   if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
  1395.     if (old_deny == new_deny && share_pid == getpid()) 
  1396.     return(AALL);    
  1397.  
  1398.     if (old_mode == 0) return(AREAD);
  1399.  
  1400.     /* the new smbpub.zip spec says that if the file extension is
  1401.        .com, .dll, .exe or .sym then allow the open. I will force
  1402.        it to read-only as this seems sensible although the spec is
  1403.        a little unclear on this. */
  1404.     if ((fname = strrchr(fname,'.'))) {
  1405.       if (strequal(fname,".com") ||
  1406.       strequal(fname,".dll") ||
  1407.       strequal(fname,".exe") ||
  1408.       strequal(fname,".sym"))
  1409.     return(AREAD);
  1410.     }
  1411.  
  1412.     return(AFAIL);
  1413.   }
  1414.  
  1415.   switch (new_deny) 
  1416.     {
  1417.     case DENY_WRITE:
  1418.       if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
  1419.       if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
  1420.       if (old_deny==DENY_NONE && old_mode==0) return(AALL);
  1421.       return(AFAIL);
  1422.     case DENY_READ:
  1423.       if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
  1424.       if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
  1425.       if (old_deny==DENY_NONE && old_mode==1) return(AALL);
  1426.       return(AFAIL);
  1427.     case DENY_NONE:
  1428.       if (old_deny==DENY_WRITE) return(AREAD);
  1429.       if (old_deny==DENY_READ) return(AWRITE);
  1430.       if (old_deny==DENY_NONE) return(AALL);
  1431.       return(AFAIL);      
  1432.     }
  1433.   return(AFAIL);      
  1434. }
  1435.  
  1436. /*******************************************************************
  1437. check if the share mode on a file allows it to be deleted or unlinked
  1438. return True if sharing doesn't prevent the operation
  1439. ********************************************************************/
  1440. BOOL check_file_sharing(int cnum,char *fname)
  1441. {
  1442.   int i;
  1443.   int ret = False;
  1444.   min_share_mode_entry *old_shares = 0;
  1445.   int num_share_modes;
  1446.   struct stat sbuf;
  1447.   share_lock_token token;
  1448.   int pid = getpid();
  1449.  
  1450.   if(!lp_share_modes(SNUM(cnum)))
  1451.     return True;
  1452.  
  1453.   if (stat(fname,&sbuf) == -1) return(True);
  1454.  
  1455.   lock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &token);
  1456.   num_share_modes = get_share_modes(cnum, token, 
  1457.                      (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &old_shares);
  1458.  
  1459.   for( i = 0; i < num_share_modes; i++)
  1460.   {
  1461.     if (old_shares[i].share_mode != DENY_DOS)
  1462.       goto free_and_exit;
  1463.  
  1464.     if(old_shares[i].pid != pid)
  1465.       goto free_and_exit;
  1466.   }
  1467.  
  1468.   /* XXXX exactly what share mode combinations should be allowed for
  1469.      deleting/renaming? */
  1470.   /* If we got here then either there were no share modes or
  1471.      all share modes were DENY_DOS and the pid == getpid() */
  1472.   ret = True;
  1473.  
  1474. free_and_exit:
  1475.  
  1476.   unlock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, token);
  1477.   if(old_shares != NULL)
  1478.     free((char *)old_shares);
  1479.   return(ret);
  1480. }
  1481.  
  1482. /****************************************************************************
  1483.   C. Hoch 11/22/95
  1484.   Helper for open_file_shared. 
  1485.   Truncate a file after checking locking; close file if locked.
  1486.   **************************************************************************/
  1487. static void truncate_unless_locked(int fnum, int cnum, share_lock_token token, 
  1488.        BOOL *share_locked)
  1489. {
  1490.   if (Files[fnum].can_write){
  1491.     if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
  1492.       /* If share modes are in force for this connection we
  1493.          have the share entry locked. Unlock it before closing. */
  1494.       if (*share_locked && lp_share_modes(SNUM(cnum)))
  1495.         unlock_share_entry( cnum, Files[fnum].fd_ptr->dev, 
  1496.                             Files[fnum].fd_ptr->inode, token);
  1497.       close_file(fnum);   
  1498.       /* Share mode no longer locked. */
  1499.       *share_locked = False;
  1500.       errno = EACCES;
  1501.       unix_ERR_class = ERRDOS;
  1502.       unix_ERR_code = ERRlock;
  1503.     }
  1504.     else
  1505.       ftruncate(Files[fnum].fd_ptr->fd,0); 
  1506.   }
  1507. }
  1508.  
  1509.  
  1510. /****************************************************************************
  1511. open a file with a share mode
  1512. ****************************************************************************/
  1513. void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
  1514.               int mode,int *Access,int *action)
  1515. {
  1516.   files_struct *fs_p = &Files[fnum];
  1517.   int flags=0;
  1518.   int flags2=0;
  1519.   int deny_mode = (share_mode>>4)&7;
  1520.   struct stat sbuf;
  1521.   BOOL file_existed = file_exist(fname,&sbuf);
  1522.   BOOL share_locked = False;
  1523.   BOOL fcbopen = False;
  1524.   share_lock_token token;
  1525.   uint32 dev = 0;
  1526.   uint32 inode = 0;
  1527.  
  1528.   fs_p->open = False;
  1529.   fs_p->fd_ptr = 0;
  1530.  
  1531.   /* this is for OS/2 EAs - try and say we don't support them */
  1532.   if (strstr(fname,".+,;=[].")) 
  1533.   {
  1534.     unix_ERR_class = ERRDOS;
  1535.     unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
  1536.     return;
  1537.   }
  1538.  
  1539.   if ((ofun & 0x3) == 0 && file_existed)  
  1540.   {
  1541.     errno = EEXIST;
  1542.     return;
  1543.   }
  1544.       
  1545.   if (ofun & 0x10)
  1546.     flags2 |= O_CREAT;
  1547.   if ((ofun & 0x3) == 2)
  1548.     flags2 |= O_TRUNC;
  1549.  
  1550.   /* note that we ignore the append flag as 
  1551.      append does not mean the same thing under dos and unix */
  1552.  
  1553.   switch (share_mode&0xF)
  1554.   {
  1555.     case 1: 
  1556.       flags = O_WRONLY; 
  1557.       break;
  1558.     case 0xF: 
  1559.       fcbopen = True;
  1560.       flags = O_RDWR; 
  1561.       break;
  1562.     case 2: 
  1563.       flags = O_RDWR; 
  1564.       break;
  1565.     default:
  1566.       flags = O_RDONLY;
  1567.       break;
  1568.   }
  1569.   
  1570.   if (flags != O_RDONLY && file_existed && 
  1571.       (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) 
  1572.   {
  1573.     if (!fcbopen) 
  1574.     {
  1575.       errno = EACCES;
  1576.       return;
  1577.     }
  1578.     flags = O_RDONLY;
  1579.   }
  1580.  
  1581.   if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) 
  1582.   {
  1583.     DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
  1584.     errno = EINVAL;
  1585.     return;
  1586.   }
  1587.  
  1588.   if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
  1589.  
  1590.   if (lp_share_modes(SNUM(cnum))) 
  1591.   {
  1592.     int num_shares = 0;
  1593.     int i;
  1594.     min_share_mode_entry *old_shares = 0;
  1595.  
  1596.  
  1597.     if (file_existed)
  1598.     {
  1599.       dev = (uint32)sbuf.st_dev;
  1600.       inode = (uint32)sbuf.st_ino;
  1601.       lock_share_entry(cnum, dev, inode, &token);
  1602.       share_locked = True;
  1603.       num_shares = get_share_modes(cnum, token, dev, inode, &old_shares);
  1604.     }
  1605.  
  1606.     for(i = 0; i < num_shares; i++)
  1607.     {
  1608.       /* someone else has a share lock on it, check to see 
  1609.      if we can too */
  1610.       int old_open_mode = old_shares[i].share_mode &0xF;
  1611.       int old_deny_mode = (old_shares[i].share_mode >>4)&7;
  1612.  
  1613.       if (old_deny_mode > 4 || old_open_mode > 2) 
  1614.       {
  1615.     DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n",
  1616.          deny_mode,old_deny_mode,old_open_mode,fname));
  1617.         free((char *)old_shares);
  1618.         if(share_locked)
  1619.           unlock_share_entry(cnum, dev, inode, token);
  1620.     errno = EACCES;
  1621.     unix_ERR_class = ERRDOS;
  1622.     unix_ERR_code = ERRbadshare;
  1623.     return;
  1624.       }
  1625.  
  1626.       {
  1627.     int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
  1628.                       old_shares[i].pid,fname);
  1629.  
  1630.     if ((access_allowed == AFAIL) ||
  1631.         (!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) ||
  1632.         (access_allowed == AREAD && flags == O_WRONLY) ||
  1633.         (access_allowed == AWRITE && flags == O_RDONLY)) 
  1634.         {
  1635.       DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
  1636.            deny_mode,old_deny_mode,old_open_mode,
  1637.            old_shares[i].pid,fname,
  1638.            access_allowed));
  1639.           free((char *)old_shares);
  1640.           if(share_locked)
  1641.             unlock_share_entry(cnum, dev, inode, token);
  1642.       errno = EACCES;
  1643.       unix_ERR_class = ERRDOS;
  1644.       unix_ERR_code = ERRbadshare;
  1645.       return;
  1646.         }
  1647.     
  1648.     if (access_allowed == AREAD)
  1649.       flags = O_RDONLY;
  1650.     
  1651.     if (access_allowed == AWRITE)
  1652.       flags = O_WRONLY;
  1653.       }
  1654.     }
  1655.     if(old_shares != 0)
  1656.       free((char *)old_shares);
  1657.   }
  1658.  
  1659.   DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
  1660.        flags,flags2,mode));
  1661.  
  1662.   open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
  1663.   if (!fs_p->open && flags==O_RDWR && errno!=ENOENT && fcbopen) 
  1664.   {
  1665.     flags = O_RDONLY;
  1666.     open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 );
  1667.   }
  1668.  
  1669.   if (fs_p->open) 
  1670.   {
  1671.     int open_mode=0;
  1672.  
  1673.     if((share_locked == False) && lp_share_modes(SNUM(cnum)))
  1674.     {
  1675.       /* We created the file - thus we must now lock the share entry before creating it. */
  1676.       dev = fs_p->fd_ptr->dev;
  1677.       inode = fs_p->fd_ptr->inode;
  1678.       lock_share_entry(cnum, dev, inode, &token);
  1679.       share_locked = True;
  1680.     }
  1681.  
  1682.     switch (flags) 
  1683.     {
  1684.       case O_RDONLY:
  1685.         open_mode = 0;
  1686.         break;
  1687.       case O_RDWR:
  1688.         open_mode = 2;
  1689.         break;
  1690.       case O_WRONLY:
  1691.         open_mode = 1;
  1692.         break;
  1693.     }
  1694.  
  1695.     fs_p->share_mode = (deny_mode<<4) | open_mode;
  1696.  
  1697.     if (Access)
  1698.       (*Access) = open_mode;
  1699.  
  1700.     if (action) 
  1701.     {
  1702.       if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
  1703.       if (!file_existed) *action = 2;
  1704.       if (file_existed && (flags2 & O_TRUNC)) *action = 3;
  1705.     }
  1706.     /* We must create the share mode entry before truncate as
  1707.        truncate can fail due to locking and have to close the
  1708.        file (which expects the share_mode_entry to be there).
  1709.      */
  1710.     if (lp_share_modes(SNUM(cnum)))
  1711.       set_share_mode(token, fnum);
  1712.  
  1713.     if ((flags2&O_TRUNC) && file_existed)
  1714.       truncate_unless_locked(fnum,cnum,token,&share_locked);
  1715.   }
  1716.  
  1717.   if (share_locked && lp_share_modes(SNUM(cnum)))
  1718.     unlock_share_entry( cnum, dev, inode, token);
  1719. }
  1720.  
  1721. /****************************************************************************
  1722. seek a file. Try to avoid the seek if possible
  1723. ****************************************************************************/
  1724. int seek_file(int fnum,uint32 pos)
  1725. {
  1726.   uint32 offset = 0;
  1727.   if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
  1728.     offset = 3;
  1729.  
  1730.   Files[fnum].pos = (int)(lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET) 
  1731.                                   - offset);
  1732.   return(Files[fnum].pos);
  1733. }
  1734.  
  1735. /****************************************************************************
  1736. read from a file
  1737. ****************************************************************************/
  1738. int read_file(int fnum,char *data,uint32 pos,int n)
  1739. {
  1740.   int ret=0,readret;
  1741.  
  1742.   if (!Files[fnum].can_write)
  1743.     {
  1744.       ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n);
  1745.  
  1746.       data += ret;
  1747.       n -= ret;
  1748.       pos += ret;
  1749.     }
  1750.  
  1751. #if USE_MMAP
  1752.   if (Files[fnum].mmap_ptr)
  1753.     {
  1754.       int num = MIN(n,(int)(Files[fnum].mmap_size-pos));
  1755.       if (num > 0)
  1756.     {
  1757.       memcpy(data,Files[fnum].mmap_ptr+pos,num);
  1758.       data += num;
  1759.       pos += num;
  1760.       n -= num;
  1761.       ret += num;
  1762.     }
  1763.     }
  1764. #endif
  1765.  
  1766.   if (n <= 0)
  1767.     return(ret);
  1768.  
  1769.   if (seek_file(fnum,pos) != pos)
  1770.     {
  1771.       DEBUG(3,("Failed to seek to %d\n",pos));
  1772.       return(ret);
  1773.     }
  1774.   
  1775.   if (n > 0) {
  1776.     readret = read(Files[fnum].fd_ptr->fd,data,n);
  1777.     if (readret > 0) ret += readret;
  1778.   }
  1779.  
  1780.   return(ret);
  1781. }
  1782.  
  1783.  
  1784. /****************************************************************************
  1785. write to a file
  1786. ****************************************************************************/
  1787. int write_file(int fnum,char *data,int n)
  1788. {
  1789.   if (!Files[fnum].can_write) {
  1790.     errno = EPERM;
  1791.     return(0);
  1792.   }
  1793.  
  1794.   if (!Files[fnum].modified) {
  1795.     struct stat st;
  1796.     Files[fnum].modified = True;
  1797.     if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) {
  1798.       int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
  1799.       if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {    
  1800.     dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
  1801.       }
  1802.     }  
  1803.   }
  1804.  
  1805.   return(write_data(Files[fnum].fd_ptr->fd,data,n));
  1806. }
  1807.  
  1808.  
  1809. /****************************************************************************
  1810. load parameters specific to a connection/service
  1811. ****************************************************************************/
  1812. BOOL become_service(int cnum,BOOL do_chdir)
  1813. {
  1814.   extern char magic_char;
  1815.   static int last_cnum = -1;
  1816.   int snum;
  1817.  
  1818.   if (!OPEN_CNUM(cnum))
  1819.     {
  1820.       last_cnum = -1;
  1821.       return(False);
  1822.     }
  1823.  
  1824.   Connections[cnum].lastused = smb_last_time;
  1825.  
  1826.   snum = SNUM(cnum);
  1827.   
  1828.   if (do_chdir &&
  1829.       ChDir(Connections[cnum].connectpath) != 0 &&
  1830.       ChDir(Connections[cnum].origpath) != 0)
  1831.     {
  1832.       DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
  1833.         Connections[cnum].connectpath,cnum));     
  1834.       return(False);
  1835.     }
  1836.  
  1837.   if (cnum == last_cnum)
  1838.     return(True);
  1839.  
  1840.   last_cnum = cnum;
  1841.  
  1842.   case_default = lp_defaultcase(snum);
  1843.   case_preserve = lp_preservecase(snum);
  1844.   short_case_preserve = lp_shortpreservecase(snum);
  1845.   case_mangle = lp_casemangle(snum);
  1846.   case_sensitive = lp_casesensitive(snum);
  1847.   magic_char = lp_magicchar(snum);
  1848.   use_mangled_map = (*lp_mangled_map(snum) ? True:False);
  1849.   return(True);
  1850. }
  1851.  
  1852.  
  1853. /****************************************************************************
  1854.   find a service entry
  1855. ****************************************************************************/
  1856. int find_service(char *service)
  1857. {
  1858.    int iService;
  1859.  
  1860.    string_sub(service,"\\","/");
  1861.  
  1862.    iService = lp_servicenumber(service);
  1863.  
  1864.    /* now handle the special case of a home directory */
  1865.    if (iService < 0)
  1866.    {
  1867.       char *phome_dir = get_home_dir(service);
  1868.       DEBUG(3,("checking for home directory %s gave %s\n",service,
  1869.         phome_dir?phome_dir:"(NULL)"));
  1870.       if (phome_dir)
  1871.       {   
  1872.      int iHomeService;
  1873.      if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
  1874.      {
  1875.         lp_add_home(service,iHomeService,phome_dir);
  1876.         iService = lp_servicenumber(service);
  1877.      }
  1878.       }
  1879.    }
  1880.  
  1881.    /* If we still don't have a service, attempt to add it as a printer. */
  1882.    if (iService < 0)
  1883.    {
  1884.       int iPrinterService;
  1885.  
  1886.       if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
  1887.       {
  1888.          char *pszTemp;
  1889.  
  1890.          DEBUG(3,("checking whether %s is a valid printer name...\n", service));
  1891.          pszTemp = PRINTCAP;
  1892.          if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
  1893.          {
  1894.             DEBUG(3,("%s is a valid printer name\n", service));
  1895.             DEBUG(3,("adding %s as a printer service\n", service));
  1896.             lp_add_printer(service,iPrinterService);
  1897.             iService = lp_servicenumber(service);
  1898.             if (iService < 0)
  1899.                DEBUG(0,("failed to add %s as a printer service!\n", service));
  1900.          }
  1901.          else
  1902.             DEBUG(3,("%s is not a valid printer name\n", service));
  1903.       }
  1904.    }
  1905.  
  1906.    /* just possibly it's a default service? */
  1907.    if (iService < 0) 
  1908.      {
  1909.        char *defservice = lp_defaultservice();
  1910.        if (defservice && *defservice && !strequal(defservice,service)) {
  1911.      iService = find_service(defservice);
  1912.      if (iService >= 0) {
  1913.        string_sub(service,"_","/");
  1914.        iService = lp_add_service(service,iService);
  1915.      }
  1916.        }
  1917.      }
  1918.  
  1919.    if (iService >= 0)
  1920.       if (!VALID_SNUM(iService))
  1921.       {
  1922.          DEBUG(0,("Invalid snum %d for %s\n",iService,service));
  1923.      iService = -1;
  1924.       }
  1925.  
  1926.    if (iService < 0)
  1927.       DEBUG(3,("find_service() failed to find service %s\n", service));
  1928.  
  1929.    return (iService);
  1930. }
  1931.  
  1932.  
  1933. /****************************************************************************
  1934.   create an error packet from a cached error.
  1935. ****************************************************************************/
  1936. int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
  1937. {
  1938.   write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
  1939.  
  1940.   int32 eclass = wbmpx->wr_errclass;
  1941.   int32 err = wbmpx->wr_error;
  1942.  
  1943.   /* We can now delete the auxiliary struct */
  1944.   free((char *)wbmpx);
  1945.   Files[fnum].wbmpx_ptr = NULL;
  1946.   return error_packet(inbuf,outbuf,eclass,err,line);
  1947. }
  1948.  
  1949.  
  1950. struct
  1951. {
  1952.   int unixerror;
  1953.   int smbclass;
  1954.   int smbcode;
  1955. } unix_smb_errmap[] =
  1956. {
  1957.   {EPERM,ERRDOS,ERRnoaccess},
  1958.   {EACCES,ERRDOS,ERRnoaccess},
  1959.   {ENOENT,ERRDOS,ERRbadfile},
  1960.   {ENOTDIR,ERRDOS,ERRbaddirectory},
  1961.   {EIO,ERRHRD,ERRgeneral},
  1962.   {EBADF,ERRSRV,ERRsrverror},
  1963.   {EINVAL,ERRSRV,ERRsrverror},
  1964.   {EEXIST,ERRDOS,ERRfilexists},
  1965.   {ENFILE,ERRDOS,ERRnofids},
  1966.   {EMFILE,ERRDOS,ERRnofids},
  1967.   {ENOSPC,ERRHRD,ERRdiskfull},
  1968. #ifdef EDQUOT
  1969.   {EDQUOT,ERRHRD,ERRdiskfull},
  1970. #endif
  1971. #ifdef ENOTEMPTY
  1972.   {ENOTEMPTY,ERRDOS,ERRnoaccess},
  1973. #endif
  1974. #ifdef EXDEV
  1975.   {EXDEV,ERRDOS,ERRdiffdevice},
  1976. #endif
  1977.   {EROFS,ERRHRD,ERRnowrite},
  1978.   {0,0,0}
  1979. };
  1980.  
  1981.  
  1982. /****************************************************************************
  1983.   create an error packet from errno
  1984. ****************************************************************************/
  1985. int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
  1986. {
  1987.   int eclass=def_class;
  1988.   int ecode=def_code;
  1989.   int i=0;
  1990.  
  1991.   if (unix_ERR_class != SUCCESS)
  1992.     {
  1993.       eclass = unix_ERR_class;
  1994.       ecode = unix_ERR_code;
  1995.       unix_ERR_class = SUCCESS;
  1996.       unix_ERR_code = 0;
  1997.     }
  1998.   else
  1999.     {
  2000.       while (unix_smb_errmap[i].smbclass != 0)
  2001.     {
  2002.       if (unix_smb_errmap[i].unixerror == errno)
  2003.         {
  2004.           eclass = unix_smb_errmap[i].smbclass;
  2005.           ecode = unix_smb_errmap[i].smbcode;
  2006.           break;
  2007.         }
  2008.       i++;
  2009.     }
  2010.     }
  2011.  
  2012.   return(error_packet(inbuf,outbuf,eclass,ecode,line));
  2013. }
  2014.  
  2015.  
  2016. /****************************************************************************
  2017.   create an error packet. Normally called using the ERROR() macro
  2018. ****************************************************************************/
  2019. int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
  2020. {
  2021.   int outsize = set_message(outbuf,0,0,True);
  2022.   int cmd;
  2023.   cmd = CVAL(inbuf,smb_com);
  2024.   
  2025.   CVAL(outbuf,smb_rcls) = error_class;
  2026.   SSVAL(outbuf,smb_err,error_code);  
  2027.   
  2028.   DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
  2029.        timestring(),
  2030.        line,
  2031.        (int)CVAL(inbuf,smb_com),
  2032.        smb_fn_name(CVAL(inbuf,smb_com)),
  2033.        error_class,
  2034.        error_code));
  2035.  
  2036.   if (errno != 0)
  2037.     DEBUG(3,("error string = %s\n",strerror(errno)));
  2038.   
  2039.   return(outsize);
  2040. }
  2041.  
  2042.  
  2043. #ifndef SIGCLD_IGNORE
  2044. /****************************************************************************
  2045. this prevents zombie child processes
  2046. ****************************************************************************/
  2047. static int sig_cld()
  2048. {
  2049.   static int depth = 0;
  2050.   if (depth != 0)
  2051.     {
  2052.       DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
  2053.       depth=0;
  2054.       return(0);
  2055.     }
  2056.   depth++;
  2057.  
  2058.   BlockSignals(True,SIGCLD);
  2059.   DEBUG(5,("got SIGCLD\n"));
  2060.  
  2061. #ifdef USE_WAITPID
  2062.   while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
  2063. #endif
  2064.  
  2065.   /* Stop zombies */
  2066.   /* Stevens, Adv. Unix Prog. says that on system V you must call
  2067.      wait before reinstalling the signal handler, because the kernel
  2068.      calls the handler from within the signal-call when there is a
  2069.      child that has exited. This would lead to an infinite recursion
  2070.      if done vice versa. */
  2071.         
  2072. #ifndef DONT_REINSTALL_SIG
  2073. #ifdef SIGCLD_IGNORE
  2074.   signal(SIGCLD, SIG_IGN);  
  2075. #else
  2076.   signal(SIGCLD, SIGNAL_CAST sig_cld);
  2077. #endif
  2078. #endif
  2079.  
  2080. #ifndef USE_WAITPID
  2081.   while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
  2082. #endif
  2083.   depth--;
  2084.   BlockSignals(False,SIGCLD);
  2085.   return 0;
  2086. }
  2087. #endif
  2088.  
  2089. /****************************************************************************
  2090.   this is called when the client exits abruptly
  2091.   **************************************************************************/
  2092. static int sig_pipe()
  2093. {
  2094.   extern int password_client;
  2095.   BlockSignals(True,SIGPIPE);
  2096.  
  2097.   if (password_client != -1) {
  2098.     DEBUG(3,("lost connection to password server\n"));
  2099.     close(password_client);
  2100.     password_client = -1;
  2101. #ifndef DONT_REINSTALL_SIG
  2102.     signal(SIGPIPE, SIGNAL_CAST sig_pipe);
  2103. #endif
  2104.     BlockSignals(False,SIGPIPE);
  2105.     return 0;
  2106.   }
  2107.  
  2108.   exit_server("Got sigpipe\n");
  2109.   return(0);
  2110. }
  2111.  
  2112. /****************************************************************************
  2113.   open the socket communication
  2114. ****************************************************************************/
  2115. static BOOL open_sockets(BOOL is_daemon,int port)
  2116. {
  2117.   extern int Client;
  2118.  
  2119.   if (is_daemon)
  2120.     {
  2121.       int s;
  2122.       struct sockaddr addr;
  2123.       int in_addrlen = sizeof(addr);
  2124.        
  2125.       /* Stop zombies */
  2126. #ifdef SIGCLD_IGNORE
  2127.       signal(SIGCLD, SIG_IGN);
  2128. #else
  2129.       signal(SIGCLD, SIGNAL_CAST sig_cld);
  2130. #endif
  2131.  
  2132.       /* open an incoming socket */
  2133.       s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
  2134.       if (s == -1)
  2135.     return(False);
  2136.  
  2137.       /* ready to listen */
  2138.       if (listen(s, 5) == -1) 
  2139.     {
  2140.       DEBUG(0,("listen: %s\n",strerror(errno)));
  2141.       close(s);
  2142.       return False;
  2143.     }
  2144.       
  2145.       if(atexit_set == 0)
  2146.         atexit(killkids);
  2147.  
  2148.       /* now accept incoming connections - forking a new process
  2149.      for each incoming connection */
  2150.       DEBUG(2,("waiting for a connection\n"));
  2151.       while (1)
  2152.     {
  2153.       Client = accept(s,&addr,&in_addrlen);
  2154.  
  2155.       if (Client == -1 && errno == EINTR)
  2156.         continue;
  2157.  
  2158.       if (Client == -1)
  2159.         {
  2160.           DEBUG(0,("accept: %s\n",strerror(errno)));
  2161.           continue;
  2162.         }
  2163.  
  2164. #ifdef NO_FORK_DEBUG
  2165. #ifndef NO_SIGNAL_TEST
  2166.           signal(SIGPIPE, SIGNAL_CAST sig_pipe);
  2167.           signal(SIGCLD, SIGNAL_CAST SIG_DFL);
  2168. #endif
  2169.       return True;
  2170. #else
  2171.       if (Client != -1 && fork()==0)
  2172.         {
  2173.               /* Child code ... */
  2174. #ifndef NO_SIGNAL_TEST
  2175.           signal(SIGPIPE, SIGNAL_CAST sig_pipe);
  2176.           signal(SIGCLD, SIGNAL_CAST SIG_DFL);
  2177. #endif
  2178.           /* close the listening socket */
  2179.           close(s);
  2180.  
  2181.           /* close our standard file descriptors */
  2182.           close_low_fds();
  2183.               am_parent = 0;
  2184.   
  2185.           set_socket_options(Client,"SO_KEEPALIVE");
  2186.           set_socket_options(Client,user_socket_options);
  2187.  
  2188.               /* Reset global variables in util.c so that
  2189.                  client substitutions will be done correctly
  2190.                  in the process.
  2191.                */
  2192.               reset_globals_after_fork();
  2193.           return True; 
  2194.         }
  2195.           close(Client); /* The parent doesn't need this socket */
  2196. #endif
  2197.     }
  2198.     }
  2199.   else
  2200.     {
  2201.       /* We will abort gracefully when the client or remote system 
  2202.      goes away */
  2203. #ifndef NO_SIGNAL_TEST
  2204.       signal(SIGPIPE, SIGNAL_CAST sig_pipe);
  2205. #endif
  2206.       Client = dup(0);
  2207.  
  2208.       /* close our standard file descriptors */
  2209.       close_low_fds();
  2210.  
  2211.       set_socket_options(Client,"SO_KEEPALIVE");
  2212.       set_socket_options(Client,user_socket_options);
  2213.     }
  2214.  
  2215.   return True;
  2216. }
  2217.  
  2218.  
  2219. /****************************************************************************
  2220. check if a snum is in use
  2221. ****************************************************************************/
  2222. BOOL snum_used(int snum)
  2223. {
  2224.   int i;
  2225.   for (i=0;i<MAX_CONNECTIONS;i++)
  2226.     if (OPEN_CNUM(i) && (SNUM(i) == snum))
  2227.       return(True);
  2228.   return(False);
  2229. }
  2230.  
  2231. /****************************************************************************
  2232.   reload the services file
  2233.   **************************************************************************/
  2234. BOOL reload_services(BOOL test)
  2235. {
  2236.   BOOL ret;
  2237.  
  2238.   if (lp_loaded())
  2239.     {
  2240.       pstring fname;
  2241.       strcpy(fname,lp_configfile());
  2242.       if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
  2243.     {
  2244.       strcpy(servicesf,fname);
  2245.       test = False;
  2246.     }
  2247.     }
  2248.  
  2249.   reopen_logs();
  2250.  
  2251.   if (test && !lp_file_list_changed())
  2252.     return(True);
  2253.  
  2254.   lp_killunused(snum_used);
  2255.  
  2256.   ret = lp_load(servicesf,False);
  2257.  
  2258.   /* perhaps the config filename is now set */
  2259.   if (!test)
  2260.     reload_services(True);
  2261.  
  2262.   reopen_logs();
  2263.  
  2264.   load_interfaces();
  2265.  
  2266.   {
  2267.     extern int Client;
  2268.     if (Client != -1) {      
  2269.       set_socket_options(Client,"SO_KEEPALIVE");
  2270.       set_socket_options(Client,user_socket_options);
  2271.     }
  2272.   }
  2273.  
  2274.   create_mangled_stack(lp_mangledstack());
  2275.  
  2276.   /* this forces service parameters to be flushed */
  2277.   become_service(-1,True);
  2278.  
  2279.   return(ret);
  2280. }
  2281.  
  2282.  
  2283.  
  2284. /****************************************************************************
  2285. this prevents zombie child processes
  2286. ****************************************************************************/
  2287. static int sig_hup()
  2288. {
  2289.   BlockSignals(True,SIGHUP);
  2290.   DEBUG(0,("Got SIGHUP\n"));
  2291.   reload_services(False);
  2292. #ifndef DONT_REINSTALL_SIG
  2293.   signal(SIGHUP,SIGNAL_CAST sig_hup);
  2294. #endif
  2295.   BlockSignals(False,SIGHUP);
  2296.   return(0);
  2297. }
  2298.  
  2299. /****************************************************************************
  2300. Setup the groups a user belongs to.
  2301. ****************************************************************************/
  2302. int setup_groups(char *user, int uid, int gid, int *p_ngroups, 
  2303.          int **p_igroups, gid_t **p_groups)
  2304. {
  2305.   if (-1 == initgroups(user,gid))
  2306.     {
  2307.       if (getuid() == 0)
  2308.     {
  2309.       DEBUG(0,("Unable to initgroups!\n"));
  2310.       if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
  2311.         DEBUG(0,("This is probably a problem with the account %s\n",user));
  2312.     }
  2313.     }
  2314.   else
  2315.     {
  2316.       int i,ngroups;
  2317.       int *igroups;
  2318.       gid_t grp = 0;
  2319.       ngroups = getgroups(0,&grp);
  2320.       if (ngroups <= 0)
  2321.         ngroups = 32;
  2322.       igroups = (int *)malloc(sizeof(int)*ngroups);
  2323.       for (i=0;i<ngroups;i++)
  2324.         igroups[i] = 0x42424242;
  2325.       ngroups = getgroups(ngroups,(gid_t *)igroups);
  2326.  
  2327.       if (igroups[0] == 0x42424242)
  2328.         ngroups = 0;
  2329.  
  2330.       *p_ngroups = ngroups;
  2331.  
  2332.       /* The following bit of code is very strange. It is due to the
  2333.          fact that some OSes use int* and some use gid_t* for
  2334.          getgroups, and some (like SunOS) use both, one in prototypes,
  2335.          and one in man pages and the actual code. Thus we detect it
  2336.          dynamically using some very ugly code */
  2337.       if (ngroups > 0)
  2338.         {
  2339.       /* does getgroups return ints or gid_t ?? */
  2340.       static BOOL groups_use_ints = True;
  2341.  
  2342.       if (groups_use_ints && 
  2343.           ngroups == 1 && 
  2344.           SVAL(igroups,2) == 0x4242)
  2345.         groups_use_ints = False;
  2346.       
  2347.           for (i=0;groups_use_ints && i<ngroups;i++)
  2348.             if (igroups[i] == 0x42424242)
  2349.               groups_use_ints = False;
  2350.           
  2351.           if (groups_use_ints)
  2352.             {
  2353.               *p_igroups = igroups;
  2354.               *p_groups = (gid_t *)igroups;      
  2355.             }
  2356.           else
  2357.             {
  2358.           gid_t *groups = (gid_t *)igroups;
  2359.           igroups = (int *)malloc(sizeof(int)*ngroups);
  2360.           for (i=0;i<ngroups;i++)
  2361.             igroups[i] = groups[i];
  2362.           *p_igroups = igroups;
  2363.           *p_groups = (gid_t *)groups;
  2364.         }
  2365.     }
  2366.       DEBUG(3,("%s is in %d groups\n",user,ngroups));
  2367.       for (i=0;i<ngroups;i++)
  2368.         DEBUG(3,("%d ",igroups[i]));
  2369.       DEBUG(3,("\n"));
  2370.     }
  2371.   return 0;
  2372. }
  2373.  
  2374. /****************************************************************************
  2375.   make a connection to a service
  2376. ****************************************************************************/
  2377. int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid)
  2378. {
  2379.   int cnum;
  2380.   int snum;
  2381.   struct passwd *pass = NULL;
  2382.   connection_struct *pcon;
  2383.   BOOL guest = False;
  2384.   BOOL force = False;
  2385.   static BOOL first_connection = True;
  2386.  
  2387.   strlower(service);
  2388.  
  2389.   snum = find_service(service);
  2390.   if (snum < 0)
  2391.     {
  2392.       if (strequal(service,"IPC$"))
  2393.     {      
  2394.       DEBUG(3,("%s refusing IPC connection\n",timestring()));
  2395.       return(-3);
  2396.     }
  2397.  
  2398.       DEBUG(0,("%s couldn't find service %s\n",timestring(),service));      
  2399.       return(-2);
  2400.     }
  2401.  
  2402.   if (strequal(service,HOMES_NAME))
  2403.     {
  2404.       if (*user && Get_Pwnam(user,True))
  2405.     return(make_connection(user,user,password,pwlen,dev,vuid));
  2406.  
  2407.       if (validated_username(vuid))
  2408.     {
  2409.       strcpy(user,validated_username(vuid));
  2410.       return(make_connection(user,user,password,pwlen,dev,vuid));
  2411.     }
  2412.     }
  2413.  
  2414.   if (!lp_snum_ok(snum) || !check_access(snum)) {    
  2415.     return(-4);
  2416.   }
  2417.  
  2418.   /* you can only connect to the IPC$ service as an ipc device */
  2419.   if (strequal(service,"IPC$"))
  2420.     strcpy(dev,"IPC");
  2421.  
  2422.   if (*dev == '?' || !*dev)
  2423.     {
  2424.       if (lp_print_ok(snum))
  2425.     strcpy(dev,"LPT1:");
  2426.       else
  2427.     strcpy(dev,"A:");
  2428.     }
  2429.  
  2430.   /* if the request is as a printer and you can't print then refuse */
  2431.   strupper(dev);
  2432.   if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
  2433.     DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
  2434.     return(-6);
  2435.   }
  2436.  
  2437.   /* lowercase the user name */
  2438.   strlower(user);
  2439.  
  2440.   /* add it as a possible user name */
  2441.   add_session_user(service);
  2442.  
  2443.   /* shall we let them in? */
  2444.   if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
  2445.     {
  2446.       DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
  2447.       return(-1);
  2448.     }
  2449.   
  2450.   cnum = find_free_connection(str_checksum(service) + str_checksum(user));
  2451.   if (cnum < 0)
  2452.     {
  2453.       DEBUG(0,("%s couldn't find free connection\n",timestring()));      
  2454.       return(-1);
  2455.     }
  2456.  
  2457.   pcon = &Connections[cnum];
  2458.   bzero((char *)pcon,sizeof(*pcon));
  2459.  
  2460.   /* find out some info about the user */
  2461.   pass = Get_Pwnam(user,True);
  2462.  
  2463.   if (pass == NULL)
  2464.     {
  2465.       DEBUG(0,("%s couldn't find account %s\n",timestring(),user)); 
  2466.       return(-7);
  2467.     }
  2468.  
  2469.   pcon->read_only = lp_readonly(snum);
  2470.  
  2471.   {
  2472.     pstring list;
  2473.     StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
  2474.     string_sub(list,"%S",service);
  2475.  
  2476.     if (user_in_list(user,list))
  2477.       pcon->read_only = True;
  2478.  
  2479.     StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
  2480.     string_sub(list,"%S",service);
  2481.  
  2482.     if (user_in_list(user,list))
  2483.       pcon->read_only = False;    
  2484.   }
  2485.  
  2486.   /* admin user check */
  2487.   if (user_in_list(user,lp_admin_users(snum)) &&
  2488.       !pcon->read_only)
  2489.     {
  2490.       pcon->admin_user = True;
  2491.       DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
  2492.     }
  2493.   else
  2494.     pcon->admin_user = False;
  2495.     
  2496.   pcon->force_user = force;
  2497.   pcon->vuid = vuid;
  2498.   pcon->uid = pass->pw_uid;
  2499.   pcon->gid = pass->pw_gid;
  2500.   pcon->num_files_open = 0;
  2501.   pcon->lastused = time(NULL);
  2502.   pcon->service = snum;
  2503.   pcon->used = True;
  2504.   pcon->printer = (strncmp(dev,"LPT",3) == 0);
  2505.   pcon->ipc = (strncmp(dev,"IPC",3) == 0);
  2506.   pcon->dirptr = NULL;
  2507.   pcon->veto_list = NULL;
  2508.   pcon->hide_list = NULL;
  2509.   string_set(&pcon->dirpath,"");
  2510.   string_set(&pcon->user,user);
  2511.  
  2512. #if HAVE_GETGRNAM 
  2513.   if (*lp_force_group(snum))
  2514.     {
  2515.       struct group *gptr;
  2516.       pstring gname;
  2517.  
  2518.       StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1);
  2519.       /* default service may be a group name         */
  2520.       string_sub(gname,"%S",service);
  2521.       gptr = (struct group *)getgrnam(gname);
  2522.  
  2523.       if (gptr)
  2524.     {
  2525.       pcon->gid = gptr->gr_gid;
  2526.       DEBUG(3,("Forced group %s\n",gname));
  2527.     }
  2528.       else
  2529.     DEBUG(1,("Couldn't find group %s\n",gname));
  2530.     }
  2531. #endif
  2532.  
  2533.   if (*lp_force_user(snum))
  2534.     {
  2535.       struct passwd *pass2;
  2536.       fstring fuser;
  2537.       strcpy(fuser,lp_force_user(snum));
  2538.       pass2 = (struct passwd *)Get_Pwnam(fuser,True);
  2539.       if (pass2)
  2540.     {
  2541.       pcon->uid = pass2->pw_uid;
  2542.       string_set(&pcon->user,fuser);
  2543.       strcpy(user,fuser);
  2544.       pcon->force_user = True;
  2545.       DEBUG(3,("Forced user %s\n",fuser));      
  2546.     }
  2547.       else
  2548.     DEBUG(1,("Couldn't find user %s\n",fuser));
  2549.     }
  2550.  
  2551.   {
  2552.     pstring s;
  2553.     strcpy(s,lp_pathname(snum));
  2554.     standard_sub(cnum,s);
  2555.     string_set(&pcon->connectpath,s);
  2556.     DEBUG(3,("Connect path is %s\n",s));
  2557.   }
  2558.  
  2559.   /* groups stuff added by ih */
  2560.   pcon->ngroups = 0;
  2561.   pcon->groups = NULL;
  2562.  
  2563.   if (!IS_IPC(cnum))
  2564.     {
  2565.       /* Find all the groups this uid is in and store them. Used by become_user() */
  2566.       setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
  2567.       
  2568.       /* check number of connections */
  2569.       if (!claim_connection(cnum,
  2570.                 lp_servicename(SNUM(cnum)),
  2571.                 lp_max_connections(SNUM(cnum)),False))
  2572.     {
  2573.       DEBUG(1,("too many connections - rejected\n"));
  2574.       return(-8);
  2575.     }  
  2576.  
  2577.       if (lp_status(SNUM(cnum)))
  2578.     claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
  2579.  
  2580.       first_connection = False;
  2581.     } /* IS_IPC */
  2582.  
  2583.   pcon->open = True;
  2584.  
  2585.   /* execute any "root preexec = " line */
  2586.   if (*lp_rootpreexec(SNUM(cnum)))
  2587.     {
  2588.       pstring cmd;
  2589.       strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
  2590.       standard_sub(cnum,cmd);
  2591.       DEBUG(5,("cmd=%s\n",cmd));
  2592.       smbrun(cmd,NULL,False);
  2593.     }
  2594.  
  2595.   if (!become_user(cnum,pcon->vuid))
  2596.     {
  2597.       DEBUG(0,("Can't become connected user!\n"));
  2598.       pcon->open = False;
  2599.       if (!IS_IPC(cnum)) {
  2600.     yield_connection(cnum,
  2601.              lp_servicename(SNUM(cnum)),
  2602.              lp_max_connections(SNUM(cnum)));
  2603.     if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
  2604.       }
  2605.       return(-1);
  2606.     }
  2607.  
  2608.   if (ChDir(pcon->connectpath) != 0)
  2609.     {
  2610.       DEBUG(0,("Can't change directory to %s (%s)\n",
  2611.            pcon->connectpath,strerror(errno)));
  2612.       pcon->open = False;
  2613.       unbecome_user();
  2614.       if (!IS_IPC(cnum)) {
  2615.     yield_connection(cnum,
  2616.              lp_servicename(SNUM(cnum)),
  2617.              lp_max_connections(SNUM(cnum)));
  2618.     if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
  2619.       }
  2620.       return(-5);      
  2621.     }
  2622.  
  2623.   string_set(&pcon->origpath,pcon->connectpath);
  2624.  
  2625. #if SOFTLINK_OPTIMISATION
  2626.   /* resolve any soft links early */
  2627.   {
  2628.     pstring s;
  2629.     strcpy(s,pcon->connectpath);
  2630.     GetWd(s);
  2631.     string_set(&pcon->connectpath,s);
  2632.     ChDir(pcon->connectpath);
  2633.   }
  2634. #endif
  2635.  
  2636.   num_connections_open++;
  2637.   add_session_user(user);
  2638.   
  2639.   /* execute any "preexec = " line */
  2640.   if (*lp_preexec(SNUM(cnum)))
  2641.     {
  2642.       pstring cmd;
  2643.       strcpy(cmd,lp_preexec(SNUM(cnum)));
  2644.       standard_sub(cnum,cmd);
  2645.       smbrun(cmd,NULL,False);
  2646.     }
  2647.   
  2648.   /* we've finished with the sensitive stuff */
  2649.   unbecome_user();
  2650.  
  2651.   /* Add veto/hide lists */
  2652.   if (!IS_IPC(cnum) && !IS_PRINT(cnum))
  2653.   {
  2654.     set_namearray( &pcon->veto_list, lp_veto_files(SNUM(cnum)));
  2655.     set_namearray( &pcon->hide_list, lp_hide_files(SNUM(cnum)));
  2656.   }
  2657.  
  2658.   {
  2659.     DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
  2660.                 timestring(),
  2661.                 remote_machine,
  2662.                 client_addr(),
  2663.                 lp_servicename(SNUM(cnum)),user,
  2664.                 pcon->uid,
  2665.                 pcon->gid,
  2666.                 (int)getpid()));
  2667.   }
  2668.  
  2669.   return(cnum);
  2670. }
  2671.  
  2672.  
  2673. /****************************************************************************
  2674.   find first available file slot
  2675. ****************************************************************************/
  2676. int find_free_file(void )
  2677. {
  2678.   int i;
  2679.   /* we start at 1 here for an obscure reason I can't now remember,
  2680.      but I think is important :-) */
  2681.   for (i=1;i<MAX_OPEN_FILES;i++)
  2682.     if (!Files[i].open)
  2683.       return(i);
  2684.   DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
  2685.   return(-1);
  2686. }
  2687.  
  2688. /****************************************************************************
  2689.   find first available connection slot, starting from a random position.
  2690. The randomisation stops problems with the server dieing and clients
  2691. thinking the server is still available.
  2692. ****************************************************************************/
  2693. static int find_free_connection(int hash )
  2694. {
  2695.   int i;
  2696.   BOOL used=False;
  2697.   hash = (hash % (MAX_CONNECTIONS-2))+1;
  2698.  
  2699.  again:
  2700.  
  2701.   for (i=hash+1;i!=hash;)
  2702.     {
  2703.       if (!Connections[i].open && Connections[i].used == used) 
  2704.     {
  2705.       DEBUG(3,("found free connection number %d\n",i));
  2706.       return(i);
  2707.     }
  2708.       i++;
  2709.       if (i == MAX_CONNECTIONS)
  2710.     i = 1;
  2711.     }
  2712.  
  2713.   if (!used)
  2714.     {
  2715.       used = !used;
  2716.       goto again;
  2717.     }
  2718.  
  2719.   DEBUG(1,("ERROR! Out of connection structures\n"));
  2720.   return(-1);
  2721. }
  2722.  
  2723.  
  2724. /****************************************************************************
  2725. reply for the core protocol
  2726. ****************************************************************************/
  2727. int reply_corep(char *outbuf)
  2728. {
  2729.   int outsize = set_message(outbuf,1,0,True);
  2730.  
  2731.   Protocol = PROTOCOL_CORE;
  2732.  
  2733.   return outsize;
  2734. }
  2735.  
  2736.  
  2737. /****************************************************************************
  2738. reply for the coreplus protocol
  2739. ****************************************************************************/
  2740. int reply_coreplus(char *outbuf)
  2741. {
  2742.   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
  2743.   int outsize = set_message(outbuf,13,0,True);
  2744.   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
  2745.                  readbraw and writebraw (possibly) */
  2746.   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
  2747.   SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */    
  2748.  
  2749.   Protocol = PROTOCOL_COREPLUS;
  2750.  
  2751.   return outsize;
  2752. }
  2753.  
  2754.  
  2755. /****************************************************************************
  2756. reply for the lanman 1.0 protocol
  2757. ****************************************************************************/
  2758. int reply_lanman1(char *outbuf)
  2759. {
  2760.   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
  2761.   int secword=0;
  2762.   BOOL doencrypt = SMBENCRYPT();
  2763.   time_t t = time(NULL);
  2764.   /* We need to save and restore this as it can be destroyed
  2765.      if we call another server if security=server
  2766.      Thanks to Paul Nelson @ Thursby for pointing this out.
  2767.    */
  2768.   uint16 mid = SVAL(outbuf, smb_mid);
  2769.  
  2770.   if (lp_security()>=SEC_USER) secword |= 1;
  2771.   if (doencrypt) secword |= 2;
  2772.  
  2773.   set_message(outbuf,13,doencrypt?8:0,True);
  2774.   SSVAL(outbuf,smb_vwv1,secword); 
  2775. #ifdef SMB_PASSWD
  2776.   /* Create a token value and add it to the outgoing packet. */
  2777.   if (doencrypt) 
  2778.     generate_next_challenge(smb_buf(outbuf));
  2779. #endif
  2780.  
  2781.   Protocol = PROTOCOL_LANMAN1;
  2782.  
  2783.   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
  2784.     DEBUG(3,("using password server validation\n"));
  2785. #ifdef SMB_PASSWD
  2786.   if (doencrypt) set_challenge(smb_buf(outbuf));    
  2787. #endif
  2788.   }
  2789.  
  2790.   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
  2791.   SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
  2792.   SSVAL(outbuf,smb_vwv2,max_recv);
  2793.   SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
  2794.   SSVAL(outbuf,smb_vwv4,1);
  2795.   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
  2796.                  readbraw writebraw (possibly) */
  2797.   SIVAL(outbuf,smb_vwv6,getpid());
  2798.   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
  2799.  
  2800.   put_dos_date(outbuf,smb_vwv8,t);
  2801.  
  2802.   return (smb_len(outbuf)+4);
  2803. }
  2804.  
  2805.  
  2806. /****************************************************************************
  2807. reply for the lanman 2.0 protocol
  2808. ****************************************************************************/
  2809. int reply_lanman2(char *outbuf)
  2810. {
  2811.   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
  2812.   int secword=0;
  2813.   BOOL doencrypt = SMBENCRYPT();
  2814.   time_t t = time(NULL);
  2815.   /* We need to save and restore this as it can be destroyed
  2816.      if we call another server if security=server
  2817.      Thanks to Paul Nelson @ Thursby for pointing this out.
  2818.    */
  2819.   uint16 mid = SVAL(outbuf, smb_mid);
  2820.  
  2821.   if (lp_security()>=SEC_USER) secword |= 1;
  2822.   if (doencrypt) secword |= 2;
  2823.  
  2824.   set_message(outbuf,13,doencrypt?8:0,True);
  2825.   SSVAL(outbuf,smb_vwv1,secword); 
  2826. #ifdef SMB_PASSWD
  2827.   /* Create a token value and add it to the outgoing packet. */
  2828.   if (doencrypt) 
  2829.     generate_next_challenge(smb_buf(outbuf));
  2830. #endif
  2831.  
  2832.   SIVAL(outbuf,smb_vwv6,getpid());
  2833.  
  2834.   Protocol = PROTOCOL_LANMAN2;
  2835.  
  2836.   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
  2837.     DEBUG(3,("using password server validation\n"));
  2838. #ifdef SMB_PASSWD
  2839.     if (doencrypt) set_challenge(smb_buf(outbuf));    
  2840. #endif
  2841.   }
  2842.  
  2843.   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
  2844.   SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
  2845.   SSVAL(outbuf,smb_vwv2,max_recv);
  2846.   SSVAL(outbuf,smb_vwv3,lp_maxmux()); 
  2847.   SSVAL(outbuf,smb_vwv4,1);
  2848.   SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
  2849.   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
  2850.   put_dos_date(outbuf,smb_vwv8,t);
  2851.  
  2852.   return (smb_len(outbuf)+4);
  2853. }
  2854.  
  2855.  
  2856. /****************************************************************************
  2857. reply for the nt protocol
  2858. ****************************************************************************/
  2859. int reply_nt1(char *outbuf)
  2860. {
  2861.   /* dual names + lock_and_read + nt SMBs + remote API calls */
  2862.   int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ;
  2863. /*
  2864.   other valid capabilities which we may support at some time...
  2865.                      CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
  2866.                      CAP_LARGE_FILES|CAP_LARGE_READX|
  2867.                      CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
  2868.  */
  2869.  
  2870.   int secword=0;
  2871.   BOOL doencrypt = SMBENCRYPT();
  2872.   time_t t = time(NULL);
  2873.   int data_len;
  2874.   int encrypt_len;
  2875.   char challenge_len = 8;
  2876.   /* We need to save and restore this as it can be destroyed
  2877.      if we call another server if security=server
  2878.      Thanks to Paul Nelson @ Thursby for pointing this out.
  2879.    */
  2880.   uint16 mid = SVAL(outbuf, smb_mid);
  2881.  
  2882.   if (lp_readraw() && lp_writeraw())
  2883.   {
  2884.     capabilities |= CAP_RAW_MODE;
  2885.   }
  2886.  
  2887.   if (lp_security()>=SEC_USER) secword |= 1;
  2888.   if (doencrypt) secword |= 2;
  2889.  
  2890.   /* decide where (if) to put the encryption challenge, and
  2891.      follow it with the OEM'd domain name
  2892.    */
  2893.   encrypt_len = doencrypt?challenge_len:0;
  2894. #if UNICODE
  2895.   data_len = encrypt_len + 2*(strlen(myworkgroup)+1);
  2896. #else
  2897.   data_len = encrypt_len + strlen(myworkgroup) + 1;
  2898. #endif
  2899.  
  2900.   set_message(outbuf,17,data_len,True);
  2901.  
  2902. #if UNICODE
  2903.   /* put the OEM'd domain name */
  2904.   PutUniCode(smb_buf(outbuf)+encrypt_len,myworkgroup);
  2905. #else
  2906.   strcpy(smb_buf(outbuf)+encrypt_len, myworkgroup);
  2907. #endif
  2908.  
  2909.   CVAL(outbuf,smb_vwv1) = secword;
  2910. #ifdef SMB_PASSWD
  2911.   /* Create a token value and add it to the outgoing packet. */
  2912.   if (doencrypt)
  2913.   {
  2914.     generate_next_challenge(smb_buf(outbuf));
  2915.  
  2916.     /* Tell the nt machine how long the challenge is. */
  2917.     SSVALS(outbuf,smb_vwv16+1,challenge_len);
  2918.   }
  2919. #endif
  2920.  
  2921.   Protocol = PROTOCOL_NT1;
  2922.  
  2923.   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
  2924.     DEBUG(3,("using password server validation\n"));
  2925. #ifdef SMB_PASSWD
  2926.     if (doencrypt) set_challenge(smb_buf(outbuf));    
  2927. #endif
  2928.   }
  2929.  
  2930.   SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
  2931.   SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
  2932.   SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
  2933.   SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
  2934.   SIVAL(outbuf,smb_vwv5+1,0xffff); /* raw size. LOTS! */
  2935.   SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
  2936.   SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
  2937.   put_long_date(outbuf+smb_vwv11+1,t);
  2938.   SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
  2939.   SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */
  2940.  
  2941.   return (smb_len(outbuf)+4);
  2942. }
  2943.  
  2944. /* these are the protocol lists used for auto architecture detection:
  2945.  
  2946. WinNT 3.51:
  2947. protocol [PC NETWORK PROGRAM 1.0]
  2948. protocol [XENIX CORE]
  2949. protocol [MICROSOFT NETWORKS 1.03]
  2950. protocol [LANMAN1.0]
  2951. protocol [Windows for Workgroups 3.1a]
  2952. protocol [LM1.2X002]
  2953. protocol [LANMAN2.1]
  2954. protocol [NT LM 0.12]
  2955.  
  2956. Win95:
  2957. protocol [PC NETWORK PROGRAM 1.0]
  2958. protocol [XENIX CORE]
  2959. protocol [MICROSOFT NETWORKS 1.03]
  2960. protocol [LANMAN1.0]
  2961. protocol [Windows for Workgroups 3.1a]
  2962. protocol [LM1.2X002]
  2963. protocol [LANMAN2.1]
  2964. protocol [NT LM 0.12]
  2965.  
  2966. OS/2:
  2967. protocol [PC NETWORK PROGRAM 1.0]
  2968. protocol [XENIX CORE]
  2969. protocol [LANMAN1.0]
  2970. protocol [LM1.2X002]
  2971. protocol [LANMAN2.1]
  2972. */
  2973.  
  2974. /*
  2975.   * Modified to recognize the architecture of the remote machine better.
  2976.   *
  2977.   * This appears to be the matrix of which protocol is used by which
  2978.   * MS product.
  2979.        Protocol                       WfWg    Win95   WinNT  OS/2
  2980.        PC NETWORK PROGRAM 1.0          1       1       1      1
  2981.        XENIX CORE                                      2      2
  2982.        MICROSOFT NETWORKS 3.0          2       2       
  2983.        DOS LM1.2X002                   3       3       
  2984.        MICROSOFT NETWORKS 1.03                         3
  2985.        DOS LANMAN2.1                   4       4       
  2986.        LANMAN1.0                                       4      3
  2987.        Windows for Workgroups 3.1a     5       5       5
  2988.        LM1.2X002                                       6      4
  2989.        LANMAN2.1                                       7      5
  2990.        NT LM 0.12                              6       8
  2991.   *
  2992.   *  tim@fsg.com 09/29/95
  2993.   */
  2994.   
  2995. #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
  2996. #define ARCH_WIN95    0x2
  2997. #define    ARCH_OS2      0xC      /* Again OS/2 is like NT */
  2998. #define ARCH_WINNT    0x8
  2999. #define ARCH_SAMBA    0x10
  3000.  
  3001. #define ARCH_ALL      0x1F
  3002.  
  3003. /* List of supported protocols, most desired first */
  3004. struct {
  3005.   char *proto_name;
  3006.   char *short_name;
  3007.   int (*proto_reply_fn)(char *);
  3008.   int protocol_level;
  3009. } supported_protocols[] = {
  3010.   {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
  3011.   {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
  3012.   {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
  3013.   {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
  3014.   {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
  3015.   {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
  3016.   {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
  3017.   {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
  3018.   {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
  3019.   {NULL,NULL},
  3020. };
  3021.  
  3022.  
  3023. /****************************************************************************
  3024.   reply to a negprot
  3025. ****************************************************************************/
  3026. static int reply_negprot(char *inbuf,char *outbuf)
  3027. {
  3028.   extern fstring remote_arch;
  3029.   int outsize = set_message(outbuf,1,0,True);
  3030.   int Index=0;
  3031.   int choice= -1;
  3032.   int protocol;
  3033.   char *p;
  3034.   int bcc = SVAL(smb_buf(inbuf),-2);
  3035.   int arch = ARCH_ALL;
  3036.  
  3037.   p = smb_buf(inbuf)+1;
  3038.   while (p < (smb_buf(inbuf) + bcc))
  3039.     { 
  3040.       Index++;
  3041.       DEBUG(3,("Requested protocol [%s]\n",p));
  3042.       if (strcsequal(p,"Windows for Workgroups 3.1a"))
  3043.     arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
  3044.       else if (strcsequal(p,"DOS LM1.2X002"))
  3045.     arch &= ( ARCH_WFWG | ARCH_WIN95 );
  3046.       else if (strcsequal(p,"DOS LANMAN2.1"))
  3047.     arch &= ( ARCH_WFWG | ARCH_WIN95 );
  3048.       else if (strcsequal(p,"NT LM 0.12"))
  3049.     arch &= ( ARCH_WIN95 | ARCH_WINNT );
  3050.       else if (strcsequal(p,"LANMAN2.1"))
  3051.     arch &= ( ARCH_WINNT | ARCH_OS2 );
  3052.       else if (strcsequal(p,"LM1.2X002"))
  3053.     arch &= ( ARCH_WINNT | ARCH_OS2 );
  3054.       else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
  3055.     arch &= ARCH_WINNT;
  3056.       else if (strcsequal(p,"XENIX CORE"))
  3057.     arch &= ( ARCH_WINNT | ARCH_OS2 );
  3058.       else if (strcsequal(p,"Samba")) {
  3059.     arch = ARCH_SAMBA;
  3060.     break;
  3061.       }
  3062.  
  3063.       p += strlen(p) + 2;
  3064.     }
  3065.     
  3066.   switch ( arch ) {
  3067.   case ARCH_SAMBA:
  3068.     strcpy(remote_arch,"Samba");
  3069.     break;
  3070.   case ARCH_WFWG:
  3071.     strcpy(remote_arch,"WfWg");
  3072.     break;
  3073.   case ARCH_WIN95:
  3074.     strcpy(remote_arch,"Win95");
  3075.     break;
  3076.   case ARCH_WINNT:
  3077.     strcpy(remote_arch,"WinNT");
  3078.     break;
  3079.   case ARCH_OS2:
  3080.     strcpy(remote_arch,"OS2");
  3081.     break;
  3082.   default:
  3083.     strcpy(remote_arch,"UNKNOWN");
  3084.     break;
  3085.   }
  3086.  
  3087.   /* possibly reload - change of architecture */
  3088.   reload_services(True);      
  3089.     
  3090.   /* a special case to stop password server loops */
  3091.   if (Index == 1 && strequal(remote_machine,myhostname) && 
  3092.       lp_security()==SEC_SERVER)
  3093.     exit_server("Password server loop!");
  3094.   
  3095.   /* Check for protocols, most desirable first */
  3096.   for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
  3097.     {
  3098.       p = smb_buf(inbuf)+1;
  3099.       Index = 0;
  3100.       if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
  3101.     while (p < (smb_buf(inbuf) + bcc))
  3102.       { 
  3103.         if (strequal(p,supported_protocols[protocol].proto_name))
  3104.           choice = Index;
  3105.         Index++;
  3106.         p += strlen(p) + 2;
  3107.       }
  3108.       if(choice != -1)
  3109.     break;
  3110.     }
  3111.   
  3112.   SSVAL(outbuf,smb_vwv0,choice);
  3113.   if(choice != -1) {
  3114.     extern fstring remote_proto;
  3115.     strcpy(remote_proto,supported_protocols[protocol].short_name);
  3116.     reload_services(True);          
  3117.     outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
  3118.     DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
  3119.   }
  3120.   else {
  3121.     DEBUG(0,("No protocol supported !\n"));
  3122.   }
  3123.   SSVAL(outbuf,smb_vwv0,choice);
  3124.   
  3125.   DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
  3126.  
  3127.   return(outsize);
  3128. }
  3129.  
  3130.  
  3131. /****************************************************************************
  3132. close all open files for a connection
  3133. ****************************************************************************/
  3134. static void close_open_files(int cnum)
  3135. {
  3136.   int i;
  3137.   for (i=0;i<MAX_OPEN_FILES;i++)
  3138.     if( Files[i].cnum == cnum && Files[i].open) {
  3139.       close_file(i);
  3140.     }
  3141. }
  3142.  
  3143.  
  3144.  
  3145. /****************************************************************************
  3146. close a cnum
  3147. ****************************************************************************/
  3148. void close_cnum(int cnum, uint16 vuid)
  3149. {
  3150.   DirCacheFlush(SNUM(cnum));
  3151.  
  3152.   unbecome_user();
  3153.  
  3154.   if (!OPEN_CNUM(cnum))
  3155.     {
  3156.       DEBUG(0,("Can't close cnum %d\n",cnum));
  3157.       return;
  3158.     }
  3159.  
  3160.   DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
  3161.               timestring(),
  3162.               remote_machine,client_addr(),
  3163.               lp_servicename(SNUM(cnum))));
  3164.  
  3165.   yield_connection(cnum,
  3166.            lp_servicename(SNUM(cnum)),
  3167.            lp_max_connections(SNUM(cnum)));
  3168.  
  3169.   if (lp_status(SNUM(cnum)))
  3170.     yield_connection(cnum,"STATUS.",MAXSTATUS);
  3171.  
  3172.   close_open_files(cnum);
  3173.   dptr_closecnum(cnum);
  3174.  
  3175.   /* execute any "postexec = " line */
  3176.   if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid))
  3177.     {
  3178.       pstring cmd;
  3179.       strcpy(cmd,lp_postexec(SNUM(cnum)));
  3180.       standard_sub(cnum,cmd);
  3181.       smbrun(cmd,NULL,False);
  3182.       unbecome_user();
  3183.     }
  3184.  
  3185.   unbecome_user();
  3186.   /* execute any "root postexec = " line */
  3187.   if (*lp_rootpostexec(SNUM(cnum)))
  3188.     {
  3189.       pstring cmd;
  3190.       strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
  3191.       standard_sub(cnum,cmd);
  3192.       smbrun(cmd,NULL,False);
  3193.     }
  3194.  
  3195.   Connections[cnum].open = False;
  3196.   num_connections_open--;
  3197.   if (Connections[cnum].ngroups && Connections[cnum].groups)
  3198.     {
  3199.       if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
  3200.     free(Connections[cnum].groups);
  3201.       free(Connections[cnum].igroups);
  3202.       Connections[cnum].groups = NULL;
  3203.       Connections[cnum].igroups = NULL;
  3204.       Connections[cnum].ngroups = 0;
  3205.     }
  3206.  
  3207.   free_namearray(Connections[cnum].veto_list);
  3208.   free_namearray(Connections[cnum].hide_list);
  3209.  
  3210.   string_set(&Connections[cnum].user,"");
  3211.   string_set(&Connections[cnum].dirpath,"");
  3212.   string_set(&Connections[cnum].connectpath,"");
  3213. }
  3214.  
  3215.  
  3216. /****************************************************************************
  3217. simple routines to do connection counting
  3218. ****************************************************************************/
  3219. BOOL yield_connection(int cnum,char *name,int max_connections)
  3220. {
  3221.   struct connect_record crec;
  3222.   pstring fname;
  3223.   FILE *f;
  3224.   int mypid = getpid();
  3225.   int i;
  3226.  
  3227.   DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
  3228.  
  3229.   if (max_connections <= 0)
  3230.     return(True);
  3231.  
  3232.   bzero(&crec,sizeof(crec));
  3233.  
  3234.   strcpy(fname,lp_lockdir());
  3235.   standard_sub(cnum,fname);
  3236.   trim_string(fname,"","/");
  3237.  
  3238.   strcat(fname,"/");
  3239.   strcat(fname,name);
  3240.   strcat(fname,".LCK");
  3241.  
  3242.   f = fopen(fname,"r+");
  3243.   if (!f)
  3244.     {
  3245.       DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno)));
  3246.       return(False);
  3247.     }
  3248.  
  3249.   fseek(f,0,SEEK_SET);
  3250.  
  3251.   /* find a free spot */
  3252.   for (i=0;i<max_connections;i++)
  3253.     {
  3254.       if (fread(&crec,sizeof(crec),1,f) != 1)
  3255.     {
  3256.       DEBUG(2,("Entry not found in lock file %s\n",fname));
  3257.       fclose(f);
  3258.       return(False);
  3259.     }
  3260.       if (crec.pid == mypid && crec.cnum == cnum)
  3261.     break;
  3262.     }
  3263.  
  3264.   if (crec.pid != mypid || crec.cnum != cnum)
  3265.     {
  3266.       fclose(f);
  3267.       DEBUG(2,("Entry not found in lock file %s\n",fname));
  3268.       return(False);
  3269.     }
  3270.  
  3271.   bzero((void *)&crec,sizeof(crec));
  3272.   
  3273.   /* remove our mark */
  3274.   if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
  3275.       fwrite(&crec,sizeof(crec),1,f) != 1)
  3276.     {
  3277.       DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
  3278.       fclose(f);
  3279.       return(False);
  3280.     }
  3281.  
  3282.   DEBUG(3,("Yield successful\n"));
  3283.  
  3284.   fclose(f);
  3285.   return(True);
  3286. }
  3287.  
  3288.  
  3289. /****************************************************************************
  3290. simple routines to do connection counting
  3291. ****************************************************************************/
  3292. BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
  3293. {
  3294.   struct connect_record crec;
  3295.   pstring fname;
  3296.   FILE *f;
  3297.   int snum = SNUM(cnum);
  3298.   int i,foundi= -1;
  3299.   int total_recs;
  3300.  
  3301.   if (max_connections <= 0)
  3302.     return(True);
  3303.  
  3304.   DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
  3305.  
  3306.   strcpy(fname,lp_lockdir());
  3307.   standard_sub(cnum,fname);
  3308.   trim_string(fname,"","/");
  3309.  
  3310.   if (!directory_exist(fname,NULL))
  3311.     mkdir(fname,0755);
  3312.  
  3313.   strcat(fname,"/");
  3314.   strcat(fname,name);
  3315.   strcat(fname,".LCK");
  3316.  
  3317.   if (!file_exist(fname,NULL))
  3318.     {
  3319.       int oldmask = umask(022);
  3320.       f = fopen(fname,"w");
  3321.       if (f) fclose(f);
  3322.       umask(oldmask);
  3323.     }
  3324.  
  3325.   total_recs = file_size(fname) / sizeof(crec);
  3326.  
  3327.   f = fopen(fname,"r+");
  3328.  
  3329.   if (!f)
  3330.     {
  3331.       DEBUG(1,("couldn't open lock file %s\n",fname));
  3332.       return(False);
  3333.     }
  3334.  
  3335.   /* find a free spot */
  3336.   for (i=0;i<max_connections;i++)
  3337.     {
  3338.  
  3339.       if (i>=total_recs || 
  3340.       fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
  3341.       fread(&crec,sizeof(crec),1,f) != 1)
  3342.     {
  3343.       if (foundi < 0) foundi = i;
  3344.       break;
  3345.     }
  3346.  
  3347.       if (Clear && crec.pid && !process_exists(crec.pid))
  3348.     {
  3349.       fseek(f,i*sizeof(crec),SEEK_SET);
  3350.       bzero((void *)&crec,sizeof(crec));
  3351.       fwrite(&crec,sizeof(crec),1,f);
  3352.       if (foundi < 0) foundi = i;
  3353.       continue;
  3354.     }
  3355.       if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
  3356.     {
  3357.       foundi=i;
  3358.       if (!Clear) break;
  3359.     }
  3360.     }  
  3361.  
  3362.   if (foundi < 0)
  3363.     {
  3364.       DEBUG(3,("no free locks in %s\n",fname));
  3365.       fclose(f);
  3366.       return(False);
  3367.     }      
  3368.  
  3369.   /* fill in the crec */
  3370.   bzero((void *)&crec,sizeof(crec));
  3371.   crec.magic = 0x280267;
  3372.   crec.pid = getpid();
  3373.   crec.cnum = cnum;
  3374.   crec.uid = Connections[cnum].uid;
  3375.   crec.gid = Connections[cnum].gid;
  3376.   StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
  3377.   crec.start = time(NULL);
  3378.  
  3379.   StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
  3380.   StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1);
  3381.   
  3382.   /* make our mark */
  3383.   if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
  3384.       fwrite(&crec,sizeof(crec),1,f) != 1)
  3385.     {
  3386.       fclose(f);
  3387.       return(False);
  3388.     }
  3389.  
  3390.   fclose(f);
  3391.   return(True);
  3392. }
  3393.  
  3394. #if DUMP_CORE
  3395. /*******************************************************************
  3396. prepare to dump a core file - carefully!
  3397. ********************************************************************/
  3398. static BOOL dump_core(void)
  3399. {
  3400.   char *p;
  3401.   pstring dname;
  3402.   strcpy(dname,debugf);
  3403.   if ((p=strrchr(dname,'/'))) *p=0;
  3404.   strcat(dname,"/corefiles");
  3405.   mkdir(dname,0700);
  3406.   sys_chown(dname,getuid(),getgid());
  3407.   chmod(dname,0700);
  3408.   if (chdir(dname)) return(False);
  3409.   umask(~(0700));
  3410.  
  3411. #ifndef NO_GETRLIMIT
  3412. #ifdef RLIMIT_CORE
  3413.   {
  3414.     struct rlimit rlp;
  3415.     getrlimit(RLIMIT_CORE, &rlp);
  3416.     rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
  3417.     setrlimit(RLIMIT_CORE, &rlp);
  3418.     getrlimit(RLIMIT_CORE, &rlp);
  3419.     DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
  3420.   }
  3421. #endif
  3422. #endif
  3423.  
  3424.  
  3425.   DEBUG(0,("Dumping core in %s\n",dname));
  3426.   return(True);
  3427. }
  3428. #endif
  3429.  
  3430. /****************************************************************************
  3431. exit the server
  3432. ****************************************************************************/
  3433. void exit_server(char *reason)
  3434. {
  3435.   static int firsttime=1;
  3436.   int i;
  3437.  
  3438.   if (!firsttime) exit(0);
  3439.   firsttime = 0;
  3440.  
  3441.   unbecome_user();
  3442.   DEBUG(2,("Closing connections\n"));
  3443.   for (i=0;i<MAX_CONNECTIONS;i++)
  3444.     if (Connections[i].open)
  3445.       close_cnum(i,(uint16)-1);
  3446. #ifdef DFS_AUTH
  3447.   if (dcelogin_atmost_once)
  3448.     dfs_unlogin();
  3449. #endif
  3450.   if (!reason) {   
  3451.     int oldlevel = DEBUGLEVEL;
  3452.     DEBUGLEVEL = 10;
  3453.     DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
  3454.     if (last_inbuf)
  3455.       show_msg(last_inbuf);
  3456.     DEBUGLEVEL = oldlevel;
  3457.     DEBUG(0,("===============================================================\n"));
  3458. #if DUMP_CORE
  3459.     if (dump_core()) return;
  3460. #endif
  3461.   }    
  3462.  
  3463. #ifdef FAST_SHARE_MODES
  3464.   stop_share_mode_mgmt();
  3465. #endif /* FAST_SHARE_MODES */
  3466.  
  3467.   DEBUG(3,("%s Server exit  (%s)\n",timestring(),reason?reason:""));
  3468.   exit(0);
  3469. }
  3470.  
  3471. /****************************************************************************
  3472. do some standard substitutions in a string
  3473. ****************************************************************************/
  3474. void standard_sub(int cnum,char *string)
  3475. {
  3476.   if (VALID_CNUM(cnum)) {
  3477.     char *p, *s, *home;
  3478.  
  3479.     for ( s=string ; (p=strchr(s, '%')) != NULL ; s=p ) {
  3480.       switch (*(p+1)) {
  3481.         case 'H' : if ((home = get_home_dir(Connections[cnum].user))!=NULL)
  3482.                      string_sub(p,"%H",home);
  3483.                    else
  3484.                      p += 2;
  3485.                    break;
  3486.         case 'P' : string_sub(p,"%P",Connections[cnum].connectpath); break;
  3487.         case 'S' : string_sub(p,"%S",lp_servicename(Connections[cnum].service)); break;
  3488.         case 'g' : string_sub(p,"%g",gidtoname(Connections[cnum].gid)); break;
  3489.         case 'u' : string_sub(p,"%u",Connections[cnum].user); break;
  3490.         case '\0' : p++; break; /* don't run off the end of the string */
  3491.         default  : p+=2; break;
  3492.       }
  3493.     }
  3494.   }
  3495.   standard_sub_basic(string);
  3496. }
  3497.  
  3498. /*
  3499. These flags determine some of the permissions required to do an operation 
  3500.  
  3501. Note that I don't set NEED_WRITE on some write operations because they
  3502. are used by some brain-dead clients when printing, and I don't want to
  3503. force write permissions on print services.
  3504. */
  3505. #define AS_USER (1<<0)
  3506. #define NEED_WRITE (1<<1)
  3507. #define TIME_INIT (1<<2)
  3508. #define CAN_IPC (1<<3)
  3509. #define AS_GUEST (1<<5)
  3510.  
  3511.  
  3512. /* 
  3513.    define a list of possible SMB messages and their corresponding
  3514.    functions. Any message that has a NULL function is unimplemented -
  3515.    please feel free to contribute implementations!
  3516. */
  3517. struct smb_message_struct
  3518. {
  3519.   int code;
  3520.   char *name;
  3521.   int (*fn)();
  3522.   int flags;
  3523. #if PROFILING
  3524.   unsigned long time;
  3525. #endif
  3526. }
  3527.  smb_messages[] = {
  3528.  
  3529.     /* CORE PROTOCOL */
  3530.  
  3531.    {SMBnegprot,"SMBnegprot",reply_negprot,0},
  3532.    {SMBtcon,"SMBtcon",reply_tcon,0},
  3533.    {SMBtdis,"SMBtdis",reply_tdis,0},
  3534.    {SMBexit,"SMBexit",reply_exit,0},
  3535.    {SMBioctl,"SMBioctl",reply_ioctl,0},
  3536.    {SMBecho,"SMBecho",reply_echo,0},
  3537.    {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
  3538.    {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
  3539.    {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
  3540.    {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
  3541.    {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
  3542.    {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
  3543.    {SMBsearch,"SMBsearch",reply_search,AS_USER},
  3544.    {SMBopen,"SMBopen",reply_open,AS_USER},
  3545.  
  3546.    /* note that SMBmknew and SMBcreate are deliberately overloaded */   
  3547.    {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
  3548.    {SMBmknew,"SMBmknew",reply_mknew,AS_USER}, 
  3549.  
  3550.    {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
  3551.    {SMBread,"SMBread",reply_read,AS_USER},
  3552.    {SMBwrite,"SMBwrite",reply_write,AS_USER},
  3553.    {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
  3554.    {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
  3555.    {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
  3556.    {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
  3557.    {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
  3558.  
  3559.    /* this is a Pathworks specific call, allowing the 
  3560.       changing of the root path */
  3561.    {pSETDIR,"pSETDIR",reply_setdir,AS_USER}, 
  3562.  
  3563.    {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
  3564.    {SMBflush,"SMBflush",reply_flush,AS_USER},
  3565.    {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
  3566.    {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
  3567.    {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
  3568.    {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST},
  3569.    {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
  3570.    {SMBlock,"SMBlock",reply_lock,AS_USER},
  3571.    {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
  3572.    
  3573.    /* CORE+ PROTOCOL FOLLOWS */
  3574.    
  3575.    {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
  3576.    {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
  3577.    {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
  3578.    {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
  3579.    {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
  3580.    
  3581.    /* LANMAN1.0 PROTOCOL FOLLOWS */
  3582.    
  3583.    {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
  3584.    {SMBreadBs,"SMBreadBs",NULL,AS_USER},
  3585.    {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
  3586.    {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
  3587.    {SMBwritec,"SMBwritec",NULL,AS_USER},
  3588.    {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
  3589.    {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
  3590.    {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
  3591.    {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
  3592.    {SMBioctls,"SMBioctls",NULL,AS_USER},
  3593.    {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
  3594.    {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
  3595.    
  3596.    {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC},
  3597.    {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
  3598.    {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
  3599.    {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
  3600.    
  3601.    {SMBffirst,"SMBffirst",reply_search,AS_USER},
  3602.    {SMBfunique,"SMBfunique",reply_search,AS_USER},
  3603.    {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
  3604.  
  3605.    /* LANMAN2.0 PROTOCOL FOLLOWS */
  3606.    {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
  3607.    {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
  3608.    {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
  3609.    {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
  3610.  
  3611.    /* messaging routines */
  3612.    {SMBsends,"SMBsends",reply_sends,AS_GUEST},
  3613.    {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
  3614.    {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
  3615.    {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
  3616.  
  3617.    /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
  3618.    
  3619.    {SMBsendb,"SMBsendb",NULL,AS_GUEST},
  3620.    {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
  3621.    {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
  3622.    {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
  3623.  };
  3624.  
  3625. /****************************************************************************
  3626. return a string containing the function name of a SMB command
  3627. ****************************************************************************/
  3628. char *smb_fn_name(int type)
  3629. {
  3630.   static char *unknown_name = "SMBunknown";
  3631.   static int num_smb_messages = 
  3632.     sizeof(smb_messages) / sizeof(struct smb_message_struct);
  3633.   int match;
  3634.  
  3635.   for (match=0;match<num_smb_messages;match++)
  3636.     if (smb_messages[match].code == type)
  3637.       break;
  3638.  
  3639.   if (match == num_smb_messages)
  3640.     return(unknown_name);
  3641.  
  3642.   return(smb_messages[match].name);
  3643. }
  3644.  
  3645.  
  3646. /****************************************************************************
  3647. do a switch on the message type, and return the response size
  3648. ****************************************************************************/
  3649. static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
  3650. {
  3651.   static int pid= -1;
  3652.   int outsize = 0;
  3653.   static int num_smb_messages = 
  3654.     sizeof(smb_messages) / sizeof(struct smb_message_struct);
  3655.   int match;
  3656.  
  3657. #if PROFILING
  3658.   struct timeval msg_start_time;
  3659.   struct timeval msg_end_time;
  3660.   static unsigned long total_time = 0;
  3661.  
  3662.   GetTimeOfDay(&msg_start_time);
  3663. #endif
  3664.  
  3665.   if (pid == -1)
  3666.     pid = getpid();
  3667.  
  3668.   errno = 0;
  3669.   last_message = type;
  3670.  
  3671.   /* make sure this is an SMB packet */
  3672.   if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
  3673.     {
  3674.       DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
  3675.       return(-1);
  3676.     }
  3677.  
  3678.   for (match=0;match<num_smb_messages;match++)
  3679.     if (smb_messages[match].code == type)
  3680.       break;
  3681.  
  3682.   if (match == num_smb_messages)
  3683.     {
  3684.       DEBUG(0,("Unknown message type %d!\n",type));
  3685.       outsize = reply_unknown(inbuf,outbuf);
  3686.     }
  3687.   else
  3688.     {
  3689.       DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
  3690.       if (smb_messages[match].fn)
  3691.     {
  3692.       int cnum = SVAL(inbuf,smb_tid);
  3693.       int flags = smb_messages[match].flags;
  3694.       uint16 session_tag = SVAL(inbuf,smb_uid);
  3695.  
  3696.       /* does this protocol need to be run as root? */
  3697.       if (!(flags & AS_USER))
  3698.         unbecome_user();
  3699.  
  3700.       /* does this protocol need to be run as the connected user? */
  3701.       if ((flags & AS_USER) && !become_user(cnum,session_tag)) {
  3702.         if (flags & AS_GUEST) 
  3703.           flags &= ~AS_USER;
  3704.         else
  3705.           return(ERROR(ERRSRV,ERRinvnid));
  3706.       }
  3707.       /* this code is to work around a bug is MS client 3 without
  3708.          introducing a security hole - it needs to be able to do
  3709.          print queue checks as guest if it isn't logged in properly */
  3710.       if (flags & AS_USER)
  3711.         flags &= ~AS_GUEST;
  3712.  
  3713.       /* does it need write permission? */
  3714.       if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
  3715.         return(ERROR(ERRSRV,ERRaccess));
  3716.  
  3717.       /* ipc services are limited */
  3718.       if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
  3719.         return(ERROR(ERRSRV,ERRaccess));        
  3720.  
  3721.       /* load service specific parameters */
  3722.       if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
  3723.         return(ERROR(ERRSRV,ERRaccess));
  3724.  
  3725.       /* does this protocol need to be run as guest? */
  3726.       if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
  3727.         return(ERROR(ERRSRV,ERRaccess));
  3728.  
  3729.       last_inbuf = inbuf;
  3730.  
  3731.       outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
  3732.     }
  3733.       else
  3734.     {
  3735.       outsize = reply_unknown(inbuf,outbuf);
  3736.     }
  3737.     }
  3738.  
  3739. #if PROFILING
  3740.   GetTimeOfDay(&msg_end_time);
  3741.   if (!(smb_messages[match].flags & TIME_INIT))
  3742.     {
  3743.       smb_messages[match].time = 0;
  3744.       smb_messages[match].flags |= TIME_INIT;
  3745.     }
  3746.   {
  3747.     unsigned long this_time =     
  3748.       (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
  3749.     (msg_end_time.tv_usec - msg_start_time.tv_usec);
  3750.     smb_messages[match].time += this_time;
  3751.     total_time += this_time;
  3752.   }
  3753.   DEBUG(2,("TIME %s  %d usecs   %g pct\n",
  3754.        smb_fn_name(type),smb_messages[match].time,
  3755.     (100.0*smb_messages[match].time) / total_time));
  3756. #endif
  3757.  
  3758.   return(outsize);
  3759. }
  3760.  
  3761.  
  3762. /****************************************************************************
  3763.   construct a chained reply and add it to the already made reply
  3764.   **************************************************************************/
  3765. int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
  3766. {
  3767.   static char *orig_inbuf;
  3768.   static char *orig_outbuf;
  3769.   int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
  3770.   unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
  3771.   char *inbuf2, *outbuf2;
  3772.   int outsize2;
  3773.   char inbuf_saved[smb_wct];
  3774.   char outbuf_saved[smb_wct];
  3775.   extern int chain_size;
  3776.   int wct = CVAL(outbuf,smb_wct);
  3777.   int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
  3778.  
  3779.   /* maybe its not chained */
  3780.   if (smb_com2 == 0xFF) {
  3781.     CVAL(outbuf,smb_vwv0) = 0xFF;
  3782.     return outsize;
  3783.   }
  3784.  
  3785.   if (chain_size == 0) {
  3786.     /* this is the first part of the chain */
  3787.     orig_inbuf = inbuf;
  3788.     orig_outbuf = outbuf;
  3789.   }
  3790.  
  3791.   /* we need to tell the client where the next part of the reply will be */
  3792.   SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
  3793.   CVAL(outbuf,smb_vwv0) = smb_com2;
  3794.  
  3795.   /* remember how much the caller added to the chain, only counting stuff
  3796.      after the parameter words */
  3797.   chain_size += outsize - smb_wct;
  3798.  
  3799.   /* work out pointers into the original packets. The
  3800.      headers on these need to be filled in */
  3801.   inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
  3802.   outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
  3803.  
  3804.   /* remember the original command type */
  3805.   smb_com1 = CVAL(orig_inbuf,smb_com);
  3806.  
  3807.   /* save the data which will be overwritten by the new headers */
  3808.   memcpy(inbuf_saved,inbuf2,smb_wct);
  3809.   memcpy(outbuf_saved,outbuf2,smb_wct);
  3810.  
  3811.   /* give the new packet the same header as the last part of the SMB */
  3812.   memmove(inbuf2,inbuf,smb_wct);
  3813.  
  3814.   /* create the in buffer */
  3815.   CVAL(inbuf2,smb_com) = smb_com2;
  3816.  
  3817.   /* create the out buffer */
  3818.   bzero(outbuf2,smb_size);
  3819.   set_message(outbuf2,0,0,True);
  3820.   CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com);
  3821.   
  3822.   memcpy(outbuf2+4,inbuf2+4,4);
  3823.   CVAL(outbuf2,smb_rcls) = SUCCESS;
  3824.   CVAL(outbuf2,smb_reh) = 0;
  3825.   CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set 
  3826.                                   means a reply */
  3827.   SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */
  3828.   SSVAL(outbuf2,smb_err,SUCCESS);
  3829.   SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid));
  3830.   SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid));
  3831.   SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid));
  3832.   SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid));
  3833.  
  3834.   DEBUG(3,("Chained message\n"));
  3835.   show_msg(inbuf2);
  3836.  
  3837.   /* process the request */
  3838.   outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
  3839.                 bufsize-chain_size);
  3840.  
  3841.   /* copy the new reply and request headers over the old ones, but
  3842.      preserve the smb_com field */
  3843.   memmove(orig_outbuf,outbuf2,smb_wct);
  3844.   CVAL(orig_outbuf,smb_com) = smb_com1;
  3845.  
  3846.   /* restore the saved data, being careful not to overwrite any
  3847.    data from the reply header */
  3848.   memcpy(inbuf2,inbuf_saved,smb_wct);
  3849.   {
  3850.     int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
  3851.     if (ofs < 0) ofs = 0;
  3852.     memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
  3853.   }
  3854.  
  3855.   return outsize2;
  3856. }
  3857.  
  3858.  
  3859.  
  3860. /****************************************************************************
  3861.   construct a reply to the incoming packet
  3862. ****************************************************************************/
  3863. int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
  3864. {
  3865.   int type = CVAL(inbuf,smb_com);
  3866.   int outsize = 0;
  3867.   int msg_type = CVAL(inbuf,0);
  3868.   extern int chain_size;
  3869.  
  3870.   smb_last_time = time(NULL);
  3871.  
  3872.   chain_size = 0;
  3873.   chain_fnum = -1;
  3874.  
  3875.   bzero(outbuf,smb_size);
  3876.  
  3877.   if (msg_type != 0)
  3878.     return(reply_special(inbuf,outbuf));  
  3879.  
  3880.   CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
  3881.   set_message(outbuf,0,0,True);
  3882.   
  3883.   memcpy(outbuf+4,inbuf+4,4);
  3884.   CVAL(outbuf,smb_rcls) = SUCCESS;
  3885.   CVAL(outbuf,smb_reh) = 0;
  3886.   CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set 
  3887.                                  means a reply */
  3888.   SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
  3889.   SSVAL(outbuf,smb_err,SUCCESS);
  3890.   SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
  3891.   SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
  3892.   SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
  3893.   SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
  3894.  
  3895.   outsize = switch_message(type,inbuf,outbuf,size,bufsize);
  3896.  
  3897.   outsize += chain_size;
  3898.  
  3899.   if(outsize > 4)
  3900.     smb_setlen(outbuf,outsize - 4);
  3901.   return(outsize);
  3902. }
  3903.  
  3904.  
  3905. /****************************************************************************
  3906.   process commands from the client
  3907. ****************************************************************************/
  3908. static void process(void)
  3909. {
  3910.   static int trans_num = 0;
  3911.   int nread;
  3912.   extern int Client;
  3913.  
  3914.   InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  3915.   OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  3916.   if ((InBuffer == NULL) || (OutBuffer == NULL)) 
  3917.     return;
  3918.  
  3919.   InBuffer += SMB_ALIGNMENT;
  3920.   OutBuffer += SMB_ALIGNMENT;
  3921.  
  3922. #if PRIME_NMBD
  3923.   DEBUG(3,("priming nmbd\n"));
  3924.   {
  3925.     struct in_addr ip;
  3926.     ip = *interpret_addr2("localhost");
  3927.     if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
  3928.     *OutBuffer = 0;
  3929.     send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
  3930.   }
  3931. #endif    
  3932.  
  3933.   while (True)
  3934.     {
  3935.       int32 len;      
  3936.       int msg_type;
  3937.       int msg_flags;
  3938.       int type;
  3939.       int deadtime = lp_deadtime()*60;
  3940.       int counter;
  3941.       int last_keepalive=0;
  3942.       int service_load_counter = 0;
  3943.  
  3944.       if (deadtime <= 0)
  3945.     deadtime = DEFAULT_SMBD_TIMEOUT;
  3946.  
  3947.       if (lp_readprediction())
  3948.     do_read_prediction();
  3949.  
  3950.       errno = 0;      
  3951.  
  3952.       for (counter=SMBD_SELECT_LOOP; 
  3953.        !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000); 
  3954.        counter += SMBD_SELECT_LOOP)
  3955.     {
  3956.       int i;
  3957.       time_t t;
  3958.       BOOL allidle = True;
  3959.       extern int keepalive;
  3960.  
  3961.       if (counter > 365 * 3600) /* big number of seconds. */
  3962.       {
  3963.         counter = 0;
  3964.         service_load_counter = 0;
  3965.       }
  3966.  
  3967.       if (smb_read_error == READ_EOF) {
  3968.         DEBUG(3,("end of file from client\n"));
  3969.         return;
  3970.       }
  3971.  
  3972.       if (smb_read_error == READ_ERROR) {
  3973.         DEBUG(3,("receive_smb error (%s) exiting\n",
  3974.              strerror(errno)));
  3975.         return;
  3976.       }
  3977.  
  3978.       t = time(NULL);
  3979.  
  3980.       /* become root again if waiting */
  3981.       unbecome_user();
  3982.  
  3983.       /* check for smb.conf reload */
  3984.       if (counter >= service_load_counter + SMBD_RELOAD_CHECK)
  3985.       {
  3986.         service_load_counter = counter;
  3987.  
  3988.         /* reload services, if files have changed. */
  3989.         reload_services(True);
  3990.       }
  3991.  
  3992.       /* automatic timeout if all connections are closed */      
  3993.       if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
  3994.         DEBUG(2,("%s Closing idle connection\n",timestring()));
  3995.         return;
  3996.       }
  3997.  
  3998.       if (keepalive && (counter-last_keepalive)>keepalive) {
  3999.         extern int password_client;
  4000.         if (!send_keepalive(Client)) {
  4001.           DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
  4002.           return;
  4003.         }        
  4004.         /* also send a keepalive to the password server if its still
  4005.            connected */
  4006.         if (password_client != -1)
  4007.           send_keepalive(password_client);
  4008.         last_keepalive = counter;
  4009.       }
  4010.  
  4011.       /* check for connection timeouts */
  4012.       for (i=0;i<MAX_CONNECTIONS;i++)
  4013.         if (Connections[i].open)
  4014.           {
  4015.         /* close dirptrs on connections that are idle */
  4016.         if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
  4017.           dptr_idlecnum(i);
  4018.  
  4019.         if (Connections[i].num_files_open > 0 ||
  4020.             (t-Connections[i].lastused)<deadtime)
  4021.           allidle = False;
  4022.           }
  4023.  
  4024.       if (allidle && num_connections_open>0) {
  4025.         DEBUG(2,("%s Closing idle connection 2\n",timestring()));
  4026.         return;
  4027.       }
  4028.     }
  4029.  
  4030.       msg_type = CVAL(InBuffer,0);
  4031.       msg_flags = CVAL(InBuffer,1);
  4032.       type = CVAL(InBuffer,smb_com);
  4033.  
  4034.       len = smb_len(InBuffer);
  4035.  
  4036.       DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
  4037.  
  4038.       nread = len + 4;
  4039.       
  4040.       DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
  4041.  
  4042. #ifdef WITH_VTP
  4043.       if(trans_num == 1 && VT_Check(InBuffer)) {
  4044.         VT_Process();
  4045.         return;
  4046.       }
  4047. #endif
  4048.  
  4049.  
  4050.       if (msg_type == 0)
  4051.     show_msg(InBuffer);
  4052.  
  4053.       nread = construct_reply(InBuffer,OutBuffer,nread,max_send);
  4054.       
  4055.       if(nread > 0) {
  4056.         if (CVAL(OutBuffer,0) == 0)
  4057.       show_msg(OutBuffer);
  4058.     
  4059.         if (nread != smb_len(OutBuffer) + 4) 
  4060.       {
  4061.         DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
  4062.              nread,
  4063.              smb_len(OutBuffer)));
  4064.       }
  4065.     else
  4066.       send_smb(Client,OutBuffer);
  4067.       }
  4068.       trans_num++;
  4069.     }
  4070. }
  4071.  
  4072.  
  4073. /****************************************************************************
  4074.   initialise connect, service and file structs
  4075. ****************************************************************************/
  4076. static void init_structs(void )
  4077. {
  4078.   int i;
  4079.   get_myname(myhostname,NULL);
  4080.  
  4081.   for (i=0;i<MAX_CONNECTIONS;i++)
  4082.     {
  4083.       Connections[i].open = False;
  4084.       Connections[i].num_files_open=0;
  4085.       Connections[i].lastused=0;
  4086.       Connections[i].used=False;
  4087.       string_init(&Connections[i].user,"");
  4088.       string_init(&Connections[i].dirpath,"");
  4089.       string_init(&Connections[i].connectpath,"");
  4090.       string_init(&Connections[i].origpath,"");
  4091.     }
  4092.  
  4093.   for (i=0;i<MAX_OPEN_FILES;i++)
  4094.     {
  4095.       Files[i].open = False;
  4096.       string_init(&Files[i].name,"");
  4097.  
  4098.     }
  4099.  
  4100.   for (i=0;i<MAX_OPEN_FILES;i++)
  4101.     {
  4102.       file_fd_struct *fd_ptr = &FileFd[i];
  4103.       fd_ptr->ref_count = 0;
  4104.       fd_ptr->dev = (int32)-1;
  4105.       fd_ptr->inode = (int32)-1;
  4106.       fd_ptr->fd = -1;
  4107.       fd_ptr->fd_readonly = -1;
  4108.       fd_ptr->fd_writeonly = -1;
  4109.       fd_ptr->real_open_flags = -1;
  4110.     }
  4111.  
  4112.   init_dptrs();
  4113. }
  4114.  
  4115. /****************************************************************************
  4116. usage on the program
  4117. ****************************************************************************/
  4118. static void usage(char *pname)
  4119. {
  4120.   DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
  4121.  
  4122.   printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
  4123.   printf("Version %s\n",VERSION);
  4124.   printf("\t-D                    become a daemon\n");
  4125.   printf("\t-p port               listen on the specified port\n");
  4126.   printf("\t-d debuglevel         set the debuglevel\n");
  4127.   printf("\t-l log basename.      Basename for log/debug files\n");
  4128.   printf("\t-s services file.     Filename of services file\n");
  4129.   printf("\t-P                    passive only\n");
  4130.   printf("\t-a                    overwrite log file, don't append\n");
  4131.   printf("\n");
  4132. }
  4133.  
  4134.  
  4135. /****************************************************************************
  4136.   main program
  4137. ****************************************************************************/
  4138.  int main(int argc,char *argv[])
  4139. {
  4140.   extern BOOL append_log;
  4141.   /* shall I run as a daemon */
  4142.   BOOL is_daemon = False;
  4143.   int port = SMB_PORT;
  4144.   int opt;
  4145.   extern char *optarg;
  4146.   char pidFile[100] = { 0 };
  4147.  
  4148. #ifdef NEED_AUTH_PARAMETERS
  4149.   set_auth_parameters(argc,argv);
  4150. #endif
  4151.  
  4152. #ifdef SecureWare
  4153.   setluid(0);
  4154. #endif
  4155.  
  4156.   append_log = True;
  4157.  
  4158.   TimeInit();
  4159.  
  4160.   strcpy(debugf,SMBLOGFILE);  
  4161.  
  4162.   setup_logging(argv[0],False);
  4163.  
  4164.   charset_initialise();
  4165.  
  4166.   /* make absolutely sure we run as root - to handle cases whre people
  4167.      are crazy enough to have it setuid */
  4168. #ifdef USE_SETRES
  4169.   setresuid(0,0,0);
  4170. #else
  4171.   setuid(0);
  4172.   seteuid(0);
  4173.   setuid(0);
  4174.   seteuid(0);
  4175. #endif
  4176.  
  4177.   fault_setup(exit_server);
  4178.   signal(SIGTERM , SIGNAL_CAST dflt_sig);
  4179.  
  4180.   /* we want total control over the permissions on created files,
  4181.      so set our umask to 0 */
  4182.   umask(0);
  4183.  
  4184.   GetWd(OriginalDir);
  4185.  
  4186.   init_uid();
  4187.  
  4188.   /* this is for people who can't start the program correctly */
  4189.   while (argc > 1 && (*argv[1] != '-'))
  4190.     {
  4191.       argv++;
  4192.       argc--;
  4193.     }
  4194.  
  4195.   while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF)
  4196.     switch (opt)
  4197.       {
  4198.       case 'f':
  4199.         strncpy(pidFile, optarg, sizeof(pidFile));
  4200.         break;
  4201.       case 'O':
  4202.     strcpy(user_socket_options,optarg);
  4203.     break;
  4204.       case 'i':
  4205.     strcpy(scope,optarg);
  4206.     break;
  4207.       case 'P':
  4208.     {
  4209.       extern BOOL passive;
  4210.       passive = True;
  4211.     }
  4212.     break;    
  4213.       case 's':
  4214.     strcpy(servicesf,optarg);
  4215.     break;
  4216.       case 'l':
  4217.     strcpy(debugf,optarg);
  4218.     break;
  4219.       case 'a':
  4220.     {
  4221.       extern BOOL append_log;
  4222.       append_log = !append_log;
  4223.     }
  4224.     break;
  4225.       case 'D':
  4226.     is_daemon = True;
  4227.     break;
  4228.       case 'd':
  4229.     if (*optarg == 'A')
  4230.       DEBUGLEVEL = 10000;
  4231.     else
  4232.       DEBUGLEVEL = atoi(optarg);
  4233.     break;
  4234.       case 'p':
  4235.     port = atoi(optarg);
  4236.     break;
  4237.       case 'h':
  4238.     usage(argv[0]);
  4239.     exit(0);
  4240.     break;
  4241.       default:
  4242.     usage(argv[0]);
  4243.     exit(1);
  4244.       }
  4245.  
  4246.   reopen_logs();
  4247.  
  4248.   DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
  4249.   DEBUG(2,("Copyright Andrew Tridgell 1992-1997\n"));
  4250.  
  4251. #ifndef NO_GETRLIMIT
  4252. #ifdef RLIMIT_NOFILE
  4253.   {
  4254.     struct rlimit rlp;
  4255.     getrlimit(RLIMIT_NOFILE, &rlp);
  4256.     rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
  4257.     setrlimit(RLIMIT_NOFILE, &rlp);
  4258.     getrlimit(RLIMIT_NOFILE, &rlp);
  4259.     DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
  4260.   }
  4261. #endif
  4262. #endif
  4263.  
  4264.   
  4265.   DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
  4266.     getuid(),getgid(),geteuid(),getegid()));
  4267.  
  4268.   if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
  4269.     {
  4270.       DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
  4271.       exit(1);
  4272.     }
  4273.  
  4274.   init_structs();
  4275.  
  4276.   if (!reload_services(False))
  4277.     return(-1);    
  4278.  
  4279.   codepage_initialise(lp_client_code_page());
  4280.  
  4281.   strcpy(myworkgroup, lp_workgroup());
  4282.  
  4283. #ifndef NO_SIGNAL_TEST
  4284.   signal(SIGHUP,SIGNAL_CAST sig_hup);
  4285. #endif
  4286.   
  4287.   DEBUG(3,("%s loaded services\n",timestring()));
  4288.  
  4289.   if (!is_daemon && !is_a_socket(0))
  4290.     {
  4291.       DEBUG(0,("standard input is not a socket, assuming -D option\n"));
  4292.       is_daemon = True;
  4293.     }
  4294.  
  4295.   if (is_daemon)
  4296.     {
  4297.       DEBUG(3,("%s becoming a daemon\n",timestring()));
  4298.       become_daemon();
  4299.     }
  4300.  
  4301.   if (*pidFile)
  4302.     {
  4303.       int     fd;
  4304.       char    buf[20];
  4305.  
  4306.       if ((fd = open(pidFile,
  4307. #ifdef O_NONBLOCK
  4308.          O_NONBLOCK | 
  4309. #endif
  4310.          O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
  4311.         {
  4312.            DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
  4313.            exit(1);
  4314.         }
  4315.       if(fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
  4316.         {
  4317.           DEBUG(0,("ERROR: smbd is already running\n"));
  4318.           exit(1);
  4319.         }
  4320.       sprintf(buf, "%u\n", (unsigned int) getpid());
  4321.       if (write(fd, buf, strlen(buf)) < 0)
  4322.         {
  4323.           DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
  4324.           exit(1);
  4325.         }
  4326.       /* Leave pid file open & locked for the duration... */
  4327.     }
  4328.  
  4329.   if (!open_sockets(is_daemon,port))
  4330.     exit(1);
  4331.  
  4332. #ifdef FAST_SHARE_MODES
  4333.   if (!start_share_mode_mgmt())
  4334.     exit(1);
  4335. #endif /* FAST_SHARE_MODES */
  4336.  
  4337.   /* possibly reload the services file. */
  4338.   reload_services(True);
  4339.  
  4340.   max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
  4341.  
  4342.   if (*lp_rootdir())
  4343.     {
  4344.       if (sys_chroot(lp_rootdir()) == 0)
  4345.     DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
  4346.     }
  4347.  
  4348.   process();
  4349.   close_sockets();
  4350.  
  4351.   exit_server("normal exit");
  4352.   return(0);
  4353. }
  4354.  
  4355.  
  4356.