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