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