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