35774c0a43aca3ef781d00c2b0649b5267835141
[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,int pos)
1708 {
1709   int offset = 0;
1710   if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1711     offset = 3;
1712
1713   Files[fnum].pos = lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET) - offset;
1714   return(Files[fnum].pos);
1715 }
1716
1717 /****************************************************************************
1718 read from a file
1719 ****************************************************************************/
1720 int read_file(int fnum,char *data,int pos,int n)
1721 {
1722   int ret=0,readret;
1723
1724   if (!Files[fnum].can_write)
1725     {
1726       ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n);
1727
1728       data += ret;
1729       n -= ret;
1730       pos += ret;
1731     }
1732
1733 #if USE_MMAP
1734   if (Files[fnum].mmap_ptr)
1735     {
1736       int num = MIN(n,Files[fnum].mmap_size-pos);
1737       if (num > 0)
1738         {
1739           memcpy(data,Files[fnum].mmap_ptr+pos,num);
1740           data += num;
1741           pos += num;
1742           n -= num;
1743           ret += num;
1744         }
1745     }
1746 #endif
1747
1748   if (n <= 0)
1749     return(ret);
1750
1751   if (seek_file(fnum,pos) != pos)
1752     {
1753       DEBUG(3,("Failed to seek to %d\n",pos));
1754       return(ret);
1755     }
1756   
1757   if (n > 0) {
1758     readret = read(Files[fnum].fd_ptr->fd,data,n);
1759     if (readret > 0) ret += readret;
1760   }
1761
1762   return(ret);
1763 }
1764
1765
1766 /****************************************************************************
1767 write to a file
1768 ****************************************************************************/
1769 int write_file(int fnum,char *data,int n)
1770 {
1771   if (!Files[fnum].can_write) {
1772     errno = EPERM;
1773     return(0);
1774   }
1775
1776   if (!Files[fnum].modified) {
1777     struct stat st;
1778     Files[fnum].modified = True;
1779     if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) {
1780       int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1781       if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {  
1782         dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1783       }
1784     }  
1785   }
1786
1787   return(write_data(Files[fnum].fd_ptr->fd,data,n));
1788 }
1789
1790
1791 /****************************************************************************
1792 load parameters specific to a connection/service
1793 ****************************************************************************/
1794 BOOL become_service(int cnum,BOOL do_chdir)
1795 {
1796   extern char magic_char;
1797   static int last_cnum = -1;
1798   int snum;
1799
1800   if (!OPEN_CNUM(cnum))
1801     {
1802       last_cnum = -1;
1803       return(False);
1804     }
1805
1806   Connections[cnum].lastused = smb_last_time;
1807
1808   snum = SNUM(cnum);
1809   
1810   if (do_chdir &&
1811       ChDir(Connections[cnum].connectpath) != 0 &&
1812       ChDir(Connections[cnum].origpath) != 0)
1813     {
1814       DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1815             Connections[cnum].connectpath,cnum));     
1816       return(False);
1817     }
1818
1819   if (cnum == last_cnum)
1820     return(True);
1821
1822   last_cnum = cnum;
1823
1824   case_default = lp_defaultcase(snum);
1825   case_preserve = lp_preservecase(snum);
1826   short_case_preserve = lp_shortpreservecase(snum);
1827   case_mangle = lp_casemangle(snum);
1828   case_sensitive = lp_casesensitive(snum);
1829   magic_char = lp_magicchar(snum);
1830   use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1831   return(True);
1832 }
1833
1834
1835 /****************************************************************************
1836   find a service entry
1837 ****************************************************************************/
1838 int find_service(char *service)
1839 {
1840    int iService;
1841
1842    string_sub(service,"\\","/");
1843
1844    iService = lp_servicenumber(service);
1845
1846    /* now handle the special case of a home directory */
1847    if (iService < 0)
1848    {
1849       char *phome_dir = get_home_dir(service);
1850       DEBUG(3,("checking for home directory %s gave %s\n",service,
1851             phome_dir?phome_dir:"(NULL)"));
1852       if (phome_dir)
1853       {   
1854          int iHomeService;
1855          if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1856          {
1857             lp_add_home(service,iHomeService,phome_dir);
1858             iService = lp_servicenumber(service);
1859          }
1860       }
1861    }
1862
1863    /* If we still don't have a service, attempt to add it as a printer. */
1864    if (iService < 0)
1865    {
1866       int iPrinterService;
1867
1868       if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1869       {
1870          char *pszTemp;
1871
1872          DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1873          pszTemp = PRINTCAP;
1874          if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
1875          {
1876             DEBUG(3,("%s is a valid printer name\n", service));
1877             DEBUG(3,("adding %s as a printer service\n", service));
1878             lp_add_printer(service,iPrinterService);
1879             iService = lp_servicenumber(service);
1880             if (iService < 0)
1881                DEBUG(0,("failed to add %s as a printer service!\n", service));
1882          }
1883          else
1884             DEBUG(3,("%s is not a valid printer name\n", service));
1885       }
1886    }
1887
1888    /* just possibly it's a default service? */
1889    if (iService < 0) 
1890      {
1891        char *defservice = lp_defaultservice();
1892        if (defservice && *defservice && !strequal(defservice,service)) {
1893          iService = find_service(defservice);
1894          if (iService >= 0) {
1895            string_sub(service,"_","/");
1896            iService = lp_add_service(service,iService);
1897          }
1898        }
1899      }
1900
1901    if (iService >= 0)
1902       if (!VALID_SNUM(iService))
1903       {
1904          DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1905          iService = -1;
1906       }
1907
1908    if (iService < 0)
1909       DEBUG(3,("find_service() failed to find service %s\n", service));
1910
1911    return (iService);
1912 }
1913
1914
1915 /****************************************************************************
1916   create an error packet from a cached error.
1917 ****************************************************************************/
1918 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
1919 {
1920   write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
1921
1922   int32 eclass = wbmpx->wr_errclass;
1923   int32 err = wbmpx->wr_error;
1924
1925   /* We can now delete the auxiliary struct */
1926   free((char *)wbmpx);
1927   Files[fnum].wbmpx_ptr = NULL;
1928   return error_packet(inbuf,outbuf,eclass,err,line);
1929 }
1930
1931
1932 struct
1933 {
1934   int unixerror;
1935   int smbclass;
1936   int smbcode;
1937 } unix_smb_errmap[] =
1938 {
1939   {EPERM,ERRDOS,ERRnoaccess},
1940   {EACCES,ERRDOS,ERRnoaccess},
1941   {ENOENT,ERRDOS,ERRbadfile},
1942   {EIO,ERRHRD,ERRgeneral},
1943   {EBADF,ERRSRV,ERRsrverror},
1944   {EINVAL,ERRSRV,ERRsrverror},
1945   {EEXIST,ERRDOS,ERRfilexists},
1946   {ENFILE,ERRDOS,ERRnofids},
1947   {EMFILE,ERRDOS,ERRnofids},
1948   {ENOSPC,ERRHRD,ERRdiskfull},
1949 #ifdef EDQUOT
1950   {EDQUOT,ERRHRD,ERRdiskfull},
1951 #endif
1952 #ifdef ENOTEMPTY
1953   {ENOTEMPTY,ERRDOS,ERRnoaccess},
1954 #endif
1955 #ifdef EXDEV
1956   {EXDEV,ERRDOS,ERRdiffdevice},
1957 #endif
1958   {EROFS,ERRHRD,ERRnowrite},
1959   {0,0,0}
1960 };
1961
1962
1963 /****************************************************************************
1964   create an error packet from errno
1965 ****************************************************************************/
1966 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
1967 {
1968   int eclass=def_class;
1969   int ecode=def_code;
1970   int i=0;
1971
1972   if (unix_ERR_class != SUCCESS)
1973     {
1974       eclass = unix_ERR_class;
1975       ecode = unix_ERR_code;
1976       unix_ERR_class = SUCCESS;
1977       unix_ERR_code = 0;
1978     }
1979   else
1980     {
1981       while (unix_smb_errmap[i].smbclass != 0)
1982         {
1983           if (unix_smb_errmap[i].unixerror == errno)
1984             {
1985               eclass = unix_smb_errmap[i].smbclass;
1986               ecode = unix_smb_errmap[i].smbcode;
1987               break;
1988             }
1989           i++;
1990         }
1991     }
1992
1993   return(error_packet(inbuf,outbuf,eclass,ecode,line));
1994 }
1995
1996
1997 /****************************************************************************
1998   create an error packet. Normally called using the ERROR() macro
1999 ****************************************************************************/
2000 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
2001 {
2002   int outsize = set_message(outbuf,0,0,True);
2003   int cmd;
2004   cmd = CVAL(inbuf,smb_com);
2005   
2006   CVAL(outbuf,smb_rcls) = error_class;
2007   SSVAL(outbuf,smb_err,error_code);  
2008   
2009   DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
2010            timestring(),
2011            line,
2012            (int)CVAL(inbuf,smb_com),
2013            smb_fn_name(CVAL(inbuf,smb_com)),
2014            error_class,
2015            error_code));
2016
2017   if (errno != 0)
2018     DEBUG(3,("error string = %s\n",strerror(errno)));
2019   
2020   return(outsize);
2021 }
2022
2023
2024 #ifndef SIGCLD_IGNORE
2025 /****************************************************************************
2026 this prevents zombie child processes
2027 ****************************************************************************/
2028 static int sig_cld()
2029 {
2030   static int depth = 0;
2031   if (depth != 0)
2032     {
2033       DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
2034       depth=0;
2035       return(0);
2036     }
2037   depth++;
2038
2039   BlockSignals(True,SIGCLD);
2040   DEBUG(5,("got SIGCLD\n"));
2041
2042 #ifdef USE_WAITPID
2043   while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
2044 #endif
2045
2046   /* Stop zombies */
2047   /* Stevens, Adv. Unix Prog. says that on system V you must call
2048      wait before reinstalling the signal handler, because the kernel
2049      calls the handler from within the signal-call when there is a
2050      child that has exited. This would lead to an infinite recursion
2051      if done vice versa. */
2052         
2053 #ifndef DONT_REINSTALL_SIG
2054 #ifdef SIGCLD_IGNORE
2055   signal(SIGCLD, SIG_IGN);  
2056 #else
2057   signal(SIGCLD, SIGNAL_CAST sig_cld);
2058 #endif
2059 #endif
2060
2061 #ifndef USE_WAITPID
2062   while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
2063 #endif
2064   depth--;
2065   BlockSignals(False,SIGCLD);
2066   return 0;
2067 }
2068 #endif
2069
2070 /****************************************************************************
2071   this is called when the client exits abruptly
2072   **************************************************************************/
2073 static int sig_pipe()
2074 {
2075   extern int password_client;
2076   BlockSignals(True,SIGPIPE);
2077
2078   if (password_client != -1) {
2079     DEBUG(3,("lost connection to password server\n"));
2080     close(password_client);
2081     password_client = -1;
2082 #ifndef DONT_REINSTALL_SIG
2083     signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2084 #endif
2085     BlockSignals(False,SIGPIPE);
2086     return 0;
2087   }
2088
2089   exit_server("Got sigpipe\n");
2090   return(0);
2091 }
2092
2093 /****************************************************************************
2094   open the socket communication
2095 ****************************************************************************/
2096 static BOOL open_sockets(BOOL is_daemon,int port)
2097 {
2098   extern int Client;
2099
2100   if (is_daemon)
2101     {
2102       int s;
2103       struct sockaddr addr;
2104       int in_addrlen = sizeof(addr);
2105        
2106       /* Stop zombies */
2107 #ifdef SIGCLD_IGNORE
2108       signal(SIGCLD, SIG_IGN);
2109 #else
2110       signal(SIGCLD, SIGNAL_CAST sig_cld);
2111 #endif
2112
2113       /* open an incoming socket */
2114       s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
2115       if (s == -1)
2116         return(False);
2117
2118       /* ready to listen */
2119       if (listen(s, 5) == -1) 
2120         {
2121           DEBUG(0,("listen: %s\n",strerror(errno)));
2122           close(s);
2123           return False;
2124         }
2125       
2126       if(atexit_set == 0)
2127         atexit(killkids);
2128
2129       /* now accept incoming connections - forking a new process
2130          for each incoming connection */
2131       DEBUG(2,("waiting for a connection\n"));
2132       while (1)
2133         {
2134           Client = accept(s,&addr,&in_addrlen);
2135
2136           if (Client == -1 && errno == EINTR)
2137             continue;
2138
2139           if (Client == -1)
2140             {
2141               DEBUG(0,("accept: %s\n",strerror(errno)));
2142               continue;
2143             }
2144
2145 #ifdef NO_FORK_DEBUG
2146 #ifndef NO_SIGNAL_TEST
2147           signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2148           signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2149 #endif
2150           return True;
2151 #else
2152           if (Client != -1 && fork()==0)
2153             {
2154               /* Child code ... */
2155 #ifndef NO_SIGNAL_TEST
2156               signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2157               signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2158 #endif
2159               /* close the listening socket */
2160               close(s);
2161
2162               /* close our standard file descriptors */
2163               close_low_fds();
2164               am_parent = 0;
2165   
2166               set_socket_options(Client,"SO_KEEPALIVE");
2167               set_socket_options(Client,user_socket_options);
2168
2169               /* Reset global variables in util.c so that
2170                  client substitutions will be done correctly
2171                  in the process.
2172                */
2173               reset_globals_after_fork();
2174               return True; 
2175             }
2176           close(Client); /* The parent doesn't need this socket */
2177 #endif
2178         }
2179     }
2180   else
2181     {
2182       /* We will abort gracefully when the client or remote system 
2183          goes away */
2184 #ifndef NO_SIGNAL_TEST
2185       signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2186 #endif
2187       Client = dup(0);
2188
2189       /* close our standard file descriptors */
2190       close_low_fds();
2191
2192       set_socket_options(Client,"SO_KEEPALIVE");
2193       set_socket_options(Client,user_socket_options);
2194     }
2195
2196   return True;
2197 }
2198
2199
2200 /****************************************************************************
2201 check if a snum is in use
2202 ****************************************************************************/
2203 BOOL snum_used(int snum)
2204 {
2205   int i;
2206   for (i=0;i<MAX_CONNECTIONS;i++)
2207     if (OPEN_CNUM(i) && (SNUM(i) == snum))
2208       return(True);
2209   return(False);
2210 }
2211
2212 /****************************************************************************
2213   reload the services file
2214   **************************************************************************/
2215 BOOL reload_services(BOOL test)
2216 {
2217   BOOL ret;
2218
2219   if (lp_loaded())
2220     {
2221       pstring fname;
2222       strcpy(fname,lp_configfile());
2223       if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
2224         {
2225           strcpy(servicesf,fname);
2226           test = False;
2227         }
2228     }
2229
2230   reopen_logs();
2231
2232   if (test && !lp_file_list_changed())
2233     return(True);
2234
2235   lp_killunused(snum_used);
2236
2237   ret = lp_load(servicesf,False);
2238
2239   /* perhaps the config filename is now set */
2240   if (!test)
2241     reload_services(True);
2242
2243   reopen_logs();
2244
2245   load_interfaces();
2246
2247   {
2248     extern int Client;
2249     if (Client != -1) {      
2250       set_socket_options(Client,"SO_KEEPALIVE");
2251       set_socket_options(Client,user_socket_options);
2252     }
2253   }
2254
2255   create_mangled_stack(lp_mangledstack());
2256
2257   /* this forces service parameters to be flushed */
2258   become_service(-1,True);
2259
2260   return(ret);
2261 }
2262
2263
2264
2265 /****************************************************************************
2266 this prevents zombie child processes
2267 ****************************************************************************/
2268 static int sig_hup()
2269 {
2270   BlockSignals(True,SIGHUP);
2271   DEBUG(0,("Got SIGHUP\n"));
2272   reload_services(False);
2273 #ifndef DONT_REINSTALL_SIG
2274   signal(SIGHUP,SIGNAL_CAST sig_hup);
2275 #endif
2276   BlockSignals(False,SIGHUP);
2277   return(0);
2278 }
2279
2280 /****************************************************************************
2281 Setup the groups a user belongs to.
2282 ****************************************************************************/
2283 int setup_groups(char *user, int uid, int gid, int *p_ngroups, 
2284                  int **p_igroups, gid_t **p_groups)
2285 {
2286   if (-1 == initgroups(user,gid))
2287     {
2288       if (getuid() == 0)
2289         {
2290           DEBUG(0,("Unable to initgroups!\n"));
2291           if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
2292             DEBUG(0,("This is probably a problem with the account %s\n",user));
2293         }
2294     }
2295   else
2296     {
2297       int i,ngroups;
2298       int *igroups;
2299       gid_t grp = 0;
2300       ngroups = getgroups(0,&grp);
2301       if (ngroups <= 0)
2302         ngroups = 32;
2303       igroups = (int *)malloc(sizeof(int)*ngroups);
2304       for (i=0;i<ngroups;i++)
2305         igroups[i] = 0x42424242;
2306       ngroups = getgroups(ngroups,(gid_t *)igroups);
2307
2308       if (igroups[0] == 0x42424242)
2309         ngroups = 0;
2310
2311       *p_ngroups = ngroups;
2312
2313       /* The following bit of code is very strange. It is due to the
2314          fact that some OSes use int* and some use gid_t* for
2315          getgroups, and some (like SunOS) use both, one in prototypes,
2316          and one in man pages and the actual code. Thus we detect it
2317          dynamically using some very ugly code */
2318       if (ngroups > 0)
2319         {
2320           /* does getgroups return ints or gid_t ?? */
2321           static BOOL groups_use_ints = True;
2322
2323           if (groups_use_ints && 
2324               ngroups == 1 && 
2325               SVAL(igroups,2) == 0x4242)
2326             groups_use_ints = False;
2327           
2328           for (i=0;groups_use_ints && i<ngroups;i++)
2329             if (igroups[i] == 0x42424242)
2330               groups_use_ints = False;
2331               
2332           if (groups_use_ints)
2333             {
2334               *p_igroups = igroups;
2335               *p_groups = (gid_t *)igroups;       
2336             }
2337           else
2338             {
2339               gid_t *groups = (gid_t *)igroups;
2340               igroups = (int *)malloc(sizeof(int)*ngroups);
2341               for (i=0;i<ngroups;i++)
2342                 igroups[i] = groups[i];
2343               *p_igroups = igroups;
2344               *p_groups = (gid_t *)groups;
2345             }
2346         }
2347       DEBUG(3,("%s is in %d groups\n",user,ngroups));
2348       for (i=0;i<ngroups;i++)
2349         DEBUG(3,("%d ",igroups[i]));
2350       DEBUG(3,("\n"));
2351     }
2352   return 0;
2353 }
2354
2355 /****************************************************************************
2356   make a connection to a service
2357 ****************************************************************************/
2358 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid)
2359 {
2360   int cnum;
2361   int snum;
2362   struct passwd *pass = NULL;
2363   connection_struct *pcon;
2364   BOOL guest = False;
2365   BOOL force = False;
2366   static BOOL first_connection = True;
2367
2368   strlower(service);
2369
2370   snum = find_service(service);
2371   if (snum < 0)
2372     {
2373       if (strequal(service,"IPC$"))
2374         {         
2375           DEBUG(3,("%s refusing IPC connection\n",timestring()));
2376           return(-3);
2377         }
2378
2379       DEBUG(0,("%s couldn't find service %s\n",timestring(),service));      
2380       return(-2);
2381     }
2382
2383   if (strequal(service,HOMES_NAME))
2384     {
2385       if (*user && Get_Pwnam(user,True))
2386         return(make_connection(user,user,password,pwlen,dev,vuid));
2387
2388       if (validated_username(vuid))
2389         {
2390           strcpy(user,validated_username(vuid));
2391           return(make_connection(user,user,password,pwlen,dev,vuid));
2392         }
2393     }
2394
2395   if (!lp_snum_ok(snum) || !check_access(snum)) {    
2396     return(-4);
2397   }
2398
2399   /* you can only connect to the IPC$ service as an ipc device */
2400   if (strequal(service,"IPC$"))
2401     strcpy(dev,"IPC");
2402
2403   if (*dev == '?' || !*dev)
2404     {
2405       if (lp_print_ok(snum))
2406         strcpy(dev,"LPT1:");
2407       else
2408         strcpy(dev,"A:");
2409     }
2410
2411   /* if the request is as a printer and you can't print then refuse */
2412   strupper(dev);
2413   if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
2414     DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
2415     return(-6);
2416   }
2417
2418   /* lowercase the user name */
2419   strlower(user);
2420
2421   /* add it as a possible user name */
2422   add_session_user(service);
2423
2424   /* shall we let them in? */
2425   if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
2426     {
2427       DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
2428       return(-1);
2429     }
2430   
2431   cnum = find_free_connection(str_checksum(service) + str_checksum(user));
2432   if (cnum < 0)
2433     {
2434       DEBUG(0,("%s couldn't find free connection\n",timestring()));      
2435       return(-1);
2436     }
2437
2438   pcon = &Connections[cnum];
2439   bzero((char *)pcon,sizeof(*pcon));
2440
2441   /* find out some info about the user */
2442   pass = Get_Pwnam(user,True);
2443
2444   if (pass == NULL)
2445     {
2446       DEBUG(0,("%s couldn't find account %s\n",timestring(),user)); 
2447       return(-7);
2448     }
2449
2450   pcon->read_only = lp_readonly(snum);
2451
2452   {
2453     pstring list;
2454     StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
2455     string_sub(list,"%S",service);
2456
2457     if (user_in_list(user,list))
2458       pcon->read_only = True;
2459
2460     StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
2461     string_sub(list,"%S",service);
2462
2463     if (user_in_list(user,list))
2464       pcon->read_only = False;    
2465   }
2466
2467   /* admin user check */
2468   if (user_in_list(user,lp_admin_users(snum)) &&
2469       !pcon->read_only)
2470     {
2471       pcon->admin_user = True;
2472       DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2473     }
2474   else
2475     pcon->admin_user = False;
2476     
2477   pcon->force_user = force;
2478   pcon->vuid = vuid;
2479   pcon->uid = pass->pw_uid;
2480   pcon->gid = pass->pw_gid;
2481   pcon->num_files_open = 0;
2482   pcon->lastused = time(NULL);
2483   pcon->service = snum;
2484   pcon->used = True;
2485   pcon->printer = (strncmp(dev,"LPT",3) == 0);
2486   pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2487   pcon->dirptr = NULL;
2488   pcon->veto_list = NULL;
2489   pcon->hide_list = NULL;
2490   string_set(&pcon->dirpath,"");
2491   string_set(&pcon->user,user);
2492
2493 #if HAVE_GETGRNAM 
2494   if (*lp_force_group(snum))
2495     {
2496       struct group *gptr;
2497       pstring gname;
2498
2499       StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1);
2500       /* default service may be a group name            */
2501       string_sub(gname,"%S",service);
2502       gptr = (struct group *)getgrnam(gname);
2503
2504       if (gptr)
2505         {
2506           pcon->gid = gptr->gr_gid;
2507           DEBUG(3,("Forced group %s\n",gname));
2508         }
2509       else
2510         DEBUG(1,("Couldn't find group %s\n",gname));
2511     }
2512 #endif
2513
2514   if (*lp_force_user(snum))
2515     {
2516       struct passwd *pass2;
2517       fstring fuser;
2518       strcpy(fuser,lp_force_user(snum));
2519       pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2520       if (pass2)
2521         {
2522           pcon->uid = pass2->pw_uid;
2523           string_set(&pcon->user,fuser);
2524           strcpy(user,fuser);
2525           pcon->force_user = True;
2526           DEBUG(3,("Forced user %s\n",fuser));    
2527         }
2528       else
2529         DEBUG(1,("Couldn't find user %s\n",fuser));
2530     }
2531
2532   {
2533     pstring s;
2534     strcpy(s,lp_pathname(snum));
2535     standard_sub(cnum,s);
2536     string_set(&pcon->connectpath,s);
2537     DEBUG(3,("Connect path is %s\n",s));
2538   }
2539
2540   /* groups stuff added by ih */
2541   pcon->ngroups = 0;
2542   pcon->groups = NULL;
2543
2544   /* Find all the groups this uid is in and store them. Used by become_user() */
2545   setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2546       
2547   /* check number of connections */
2548   if (!claim_connection(cnum,
2549                             lp_servicename(SNUM(cnum)),
2550                             lp_max_connections(SNUM(cnum)),False))
2551   {
2552     DEBUG(1,("too many connections - rejected\n"));
2553     return(-8);
2554   }  
2555
2556   if (lp_status(SNUM(cnum)))
2557     claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2558
2559   first_connection = False;
2560
2561   pcon->open = True;
2562
2563   /* execute any "root preexec = " line */
2564   if (*lp_rootpreexec(SNUM(cnum)))
2565     {
2566       pstring cmd;
2567       strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2568       standard_sub(cnum,cmd);
2569       DEBUG(5,("cmd=%s\n",cmd));
2570       smbrun(cmd,NULL,False);
2571     }
2572
2573   if (!become_user(cnum,pcon->vuid))
2574     {
2575       DEBUG(0,("Can't become connected user!\n"));
2576       pcon->open = False;
2577       yield_connection(cnum,
2578                          lp_servicename(SNUM(cnum)),
2579                          lp_max_connections(SNUM(cnum)));
2580       if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2581       {
2582         return(-1);
2583       }
2584     }
2585
2586   if (ChDir(pcon->connectpath) != 0)
2587     {
2588       DEBUG(0,("Can't change directory to %s (%s)\n",
2589                pcon->connectpath,strerror(errno)));
2590       pcon->open = False;
2591       unbecome_user();
2592       yield_connection(cnum,
2593                          lp_servicename(SNUM(cnum)),
2594                          lp_max_connections(SNUM(cnum)));
2595       if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2596       {
2597         return(-5);      
2598       }
2599     }
2600
2601   string_set(&pcon->origpath,pcon->connectpath);
2602
2603 #if SOFTLINK_OPTIMISATION
2604   /* resolve any soft links early */
2605   {
2606     pstring s;
2607     strcpy(s,pcon->connectpath);
2608     GetWd(s);
2609     string_set(&pcon->connectpath,s);
2610     ChDir(pcon->connectpath);
2611   }
2612 #endif
2613
2614   num_connections_open++;
2615   add_session_user(user);
2616   
2617   /* execute any "preexec = " line */
2618   if (*lp_preexec(SNUM(cnum)))
2619     {
2620       pstring cmd;
2621       strcpy(cmd,lp_preexec(SNUM(cnum)));
2622       standard_sub(cnum,cmd);
2623       smbrun(cmd,NULL,False);
2624     }
2625   
2626   /* we've finished with the sensitive stuff */
2627   unbecome_user();
2628
2629   /* Add veto/hide lists */
2630   if (!IS_IPC(cnum) && !IS_PRINT(cnum))
2631   {
2632     set_namearray( &pcon->veto_list, lp_veto_files(SNUM(cnum)));
2633     set_namearray( &pcon->hide_list, lp_hide_files(SNUM(cnum)));
2634   }
2635
2636   {
2637     DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2638                             timestring(),
2639                             remote_machine,
2640                             client_addr(),
2641                             lp_servicename(SNUM(cnum)),user,
2642                             pcon->uid,
2643                             pcon->gid,
2644                             (int)getpid()));
2645   }
2646
2647   return(cnum);
2648 }
2649
2650
2651 /****************************************************************************
2652   find first available file slot
2653 ****************************************************************************/
2654 int find_free_file(void )
2655 {
2656   int i;
2657   /* we start at 1 here for an obscure reason I can't now remember,
2658      but I think is important :-) */
2659   for (i=1;i<MAX_OPEN_FILES;i++)
2660     if (!Files[i].open)
2661       return(i);
2662   DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2663   return(-1);
2664 }
2665
2666 /****************************************************************************
2667   find first available connection slot, starting from a random position.
2668 The randomisation stops problems with the server dieing and clients
2669 thinking the server is still available.
2670 ****************************************************************************/
2671 static int find_free_connection(int hash )
2672 {
2673   int i;
2674   BOOL used=False;
2675   hash = (hash % (MAX_CONNECTIONS-2))+1;
2676
2677  again:
2678
2679   for (i=hash+1;i!=hash;)
2680     {
2681       if (!Connections[i].open && Connections[i].used == used) 
2682         {
2683           DEBUG(3,("found free connection number %d\n",i));
2684           return(i);
2685         }
2686       i++;
2687       if (i == MAX_CONNECTIONS)
2688         i = 1;
2689     }
2690
2691   if (!used)
2692     {
2693       used = !used;
2694       goto again;
2695     }
2696
2697   DEBUG(1,("ERROR! Out of connection structures\n"));
2698   return(-1);
2699 }
2700
2701
2702 /****************************************************************************
2703 reply for the core protocol
2704 ****************************************************************************/
2705 int reply_corep(char *outbuf)
2706 {
2707   int outsize = set_message(outbuf,1,0,True);
2708
2709   Protocol = PROTOCOL_CORE;
2710
2711   return outsize;
2712 }
2713
2714
2715 /****************************************************************************
2716 reply for the coreplus protocol
2717 ****************************************************************************/
2718 int reply_coreplus(char *outbuf)
2719 {
2720   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2721   int outsize = set_message(outbuf,13,0,True);
2722   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2723                                  readbraw and writebraw (possibly) */
2724   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2725   SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */  
2726
2727   Protocol = PROTOCOL_COREPLUS;
2728
2729   return outsize;
2730 }
2731
2732
2733 /****************************************************************************
2734 reply for the lanman 1.0 protocol
2735 ****************************************************************************/
2736 int reply_lanman1(char *outbuf)
2737 {
2738   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2739   int secword=0;
2740   BOOL doencrypt = SMBENCRYPT();
2741   time_t t = time(NULL);
2742   /* We need to save and restore this as it can be destroyed
2743      if we call another server if security=server
2744      Thanks to Paul Nelson @ Thursby for pointing this out.
2745    */
2746   uint16 mid = SVAL(outbuf, smb_mid);
2747
2748   if (lp_security()>=SEC_USER) secword |= 1;
2749   if (doencrypt) secword |= 2;
2750
2751   set_message(outbuf,13,doencrypt?8:0,True);
2752   SSVAL(outbuf,smb_vwv1,secword); 
2753 #ifdef SMB_PASSWD
2754   /* Create a token value and add it to the outgoing packet. */
2755   if (doencrypt) 
2756     generate_next_challenge(smb_buf(outbuf));
2757 #endif
2758
2759   Protocol = PROTOCOL_LANMAN1;
2760
2761   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2762     DEBUG(3,("using password server validation\n"));
2763 #ifdef SMB_PASSWD
2764   if (doencrypt) set_challenge(smb_buf(outbuf));    
2765 #endif
2766   }
2767
2768   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2769   SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2770   SSVAL(outbuf,smb_vwv2,max_recv);
2771   SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2772   SSVAL(outbuf,smb_vwv4,1);
2773   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2774                                  readbraw writebraw (possibly) */
2775   SIVAL(outbuf,smb_vwv6,getpid());
2776   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2777
2778   put_dos_date(outbuf,smb_vwv8,t);
2779
2780   return (smb_len(outbuf)+4);
2781 }
2782
2783
2784 /****************************************************************************
2785 reply for the lanman 2.0 protocol
2786 ****************************************************************************/
2787 int reply_lanman2(char *outbuf)
2788 {
2789   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2790   int secword=0;
2791   BOOL doencrypt = SMBENCRYPT();
2792   time_t t = time(NULL);
2793   /* We need to save and restore this as it can be destroyed
2794      if we call another server if security=server
2795      Thanks to Paul Nelson @ Thursby for pointing this out.
2796    */
2797   uint16 mid = SVAL(outbuf, smb_mid);
2798
2799   if (lp_security()>=SEC_USER) secword |= 1;
2800   if (doencrypt) secword |= 2;
2801
2802   set_message(outbuf,13,doencrypt?8:0,True);
2803   SSVAL(outbuf,smb_vwv1,secword); 
2804 #ifdef SMB_PASSWD
2805   /* Create a token value and add it to the outgoing packet. */
2806   if (doencrypt) 
2807     generate_next_challenge(smb_buf(outbuf));
2808 #endif
2809
2810   SIVAL(outbuf,smb_vwv6,getpid());
2811
2812   Protocol = PROTOCOL_LANMAN2;
2813
2814   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2815     DEBUG(3,("using password server validation\n"));
2816 #ifdef SMB_PASSWD
2817     if (doencrypt) set_challenge(smb_buf(outbuf));    
2818 #endif
2819   }
2820
2821   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2822   SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2823   SSVAL(outbuf,smb_vwv2,max_recv);
2824   SSVAL(outbuf,smb_vwv3,lp_maxmux()); 
2825   SSVAL(outbuf,smb_vwv4,1);
2826   SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2827   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2828   put_dos_date(outbuf,smb_vwv8,t);
2829
2830   return (smb_len(outbuf)+4);
2831 }
2832
2833
2834 /****************************************************************************
2835 reply for the nt protocol
2836 ****************************************************************************/
2837 int reply_nt1(char *outbuf)
2838 {
2839   /* dual names + lock_and_read + nt SMBs + remote API calls */
2840   int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ;
2841 /*
2842   other valid capabilities which we may support at some time...
2843                      CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
2844                      CAP_LARGE_FILES|CAP_LARGE_READX|
2845                      CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
2846  */
2847
2848   int secword=0;
2849   BOOL doencrypt = SMBENCRYPT();
2850   time_t t = time(NULL);
2851   int data_len;
2852   int encrypt_len;
2853   char challenge_len = 8;
2854   /* We need to save and restore this as it can be destroyed
2855      if we call another server if security=server
2856      Thanks to Paul Nelson @ Thursby for pointing this out.
2857    */
2858   uint16 mid = SVAL(outbuf, smb_mid);
2859
2860   if (lp_readraw() && lp_writeraw())
2861   {
2862     capabilities |= CAP_RAW_MODE;
2863   }
2864
2865   if (lp_security()>=SEC_USER) secword |= 1;
2866   if (doencrypt) secword |= 2;
2867
2868   /* decide where (if) to put the encryption challenge, and
2869      follow it with the OEM'd domain name
2870    */
2871   encrypt_len = doencrypt?challenge_len:0;
2872 #if UNICODE
2873   data_len = encrypt_len + 2*(strlen(myworkgroup)+1);
2874 #else
2875   data_len = encrypt_len + strlen(myworkgroup) + 1;
2876 #endif
2877
2878   set_message(outbuf,17,data_len,True);
2879
2880 #if UNICODE
2881   /* put the OEM'd domain name */
2882   PutUniCode(smb_buf(outbuf)+encrypt_len,myworkgroup);
2883 #else
2884   strcpy(smb_buf(outbuf)+encrypt_len, myworkgroup);
2885 #endif
2886
2887   CVAL(outbuf,smb_vwv1) = secword;
2888 #ifdef SMB_PASSWD
2889   /* Create a token value and add it to the outgoing packet. */
2890   if (doencrypt)
2891   {
2892     generate_next_challenge(smb_buf(outbuf));
2893
2894     /* Tell the nt machine how long the challenge is. */
2895     SSVALS(outbuf,smb_vwv16+1,challenge_len);
2896   }
2897 #endif
2898
2899   Protocol = PROTOCOL_NT1;
2900
2901   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2902     DEBUG(3,("using password server validation\n"));
2903 #ifdef SMB_PASSWD
2904     if (doencrypt) set_challenge(smb_buf(outbuf));    
2905 #endif
2906   }
2907
2908   SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2909   SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2910   SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2911   SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
2912   SIVAL(outbuf,smb_vwv5+1,0xffff); /* raw size. LOTS! */
2913   SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2914   SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2915   put_long_date(outbuf+smb_vwv11+1,t);
2916   SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
2917   SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */
2918
2919   return (smb_len(outbuf)+4);
2920 }
2921
2922 /* these are the protocol lists used for auto architecture detection:
2923
2924 WinNT 3.51:
2925 protocol [PC NETWORK PROGRAM 1.0]
2926 protocol [XENIX CORE]
2927 protocol [MICROSOFT NETWORKS 1.03]
2928 protocol [LANMAN1.0]
2929 protocol [Windows for Workgroups 3.1a]
2930 protocol [LM1.2X002]
2931 protocol [LANMAN2.1]
2932 protocol [NT LM 0.12]
2933
2934 Win95:
2935 protocol [PC NETWORK PROGRAM 1.0]
2936 protocol [XENIX CORE]
2937 protocol [MICROSOFT NETWORKS 1.03]
2938 protocol [LANMAN1.0]
2939 protocol [Windows for Workgroups 3.1a]
2940 protocol [LM1.2X002]
2941 protocol [LANMAN2.1]
2942 protocol [NT LM 0.12]
2943
2944 OS/2:
2945 protocol [PC NETWORK PROGRAM 1.0]
2946 protocol [XENIX CORE]
2947 protocol [LANMAN1.0]
2948 protocol [LM1.2X002]
2949 protocol [LANMAN2.1]
2950 */
2951
2952 /*
2953   * Modified to recognize the architecture of the remote machine better.
2954   *
2955   * This appears to be the matrix of which protocol is used by which
2956   * MS product.
2957        Protocol                       WfWg    Win95   WinNT  OS/2
2958        PC NETWORK PROGRAM 1.0          1       1       1      1
2959        XENIX CORE                                      2      2
2960        MICROSOFT NETWORKS 3.0          2       2       
2961        DOS LM1.2X002                   3       3       
2962        MICROSOFT NETWORKS 1.03                         3
2963        DOS LANMAN2.1                   4       4       
2964        LANMAN1.0                                       4      3
2965        Windows for Workgroups 3.1a     5       5       5
2966        LM1.2X002                                       6      4
2967        LANMAN2.1                                       7      5
2968        NT LM 0.12                              6       8
2969   *
2970   *  tim@fsg.com 09/29/95
2971   */
2972   
2973 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
2974 #define ARCH_WIN95    0x2
2975 #define ARCH_OS2      0xC      /* Again OS/2 is like NT */
2976 #define ARCH_WINNT    0x8
2977 #define ARCH_SAMBA    0x10
2978  
2979 #define ARCH_ALL      0x1F
2980  
2981 /* List of supported protocols, most desired first */
2982 struct {
2983   char *proto_name;
2984   char *short_name;
2985   int (*proto_reply_fn)(char *);
2986   int protocol_level;
2987 } supported_protocols[] = {
2988   {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
2989   {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
2990   {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
2991   {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
2992   {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
2993   {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
2994   {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
2995   {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
2996   {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
2997   {NULL,NULL},
2998 };
2999
3000
3001 /****************************************************************************
3002   reply to a negprot
3003 ****************************************************************************/
3004 static int reply_negprot(char *inbuf,char *outbuf)
3005 {
3006   extern fstring remote_arch;
3007   int outsize = set_message(outbuf,1,0,True);
3008   int Index=0;
3009   int choice= -1;
3010   int protocol;
3011   char *p;
3012   int bcc = SVAL(smb_buf(inbuf),-2);
3013   int arch = ARCH_ALL;
3014
3015   p = smb_buf(inbuf)+1;
3016   while (p < (smb_buf(inbuf) + bcc))
3017     { 
3018       Index++;
3019       DEBUG(3,("Requested protocol [%s]\n",p));
3020       if (strcsequal(p,"Windows for Workgroups 3.1a"))
3021         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
3022       else if (strcsequal(p,"DOS LM1.2X002"))
3023         arch &= ( ARCH_WFWG | ARCH_WIN95 );
3024       else if (strcsequal(p,"DOS LANMAN2.1"))
3025         arch &= ( ARCH_WFWG | ARCH_WIN95 );
3026       else if (strcsequal(p,"NT LM 0.12"))
3027         arch &= ( ARCH_WIN95 | ARCH_WINNT );
3028       else if (strcsequal(p,"LANMAN2.1"))
3029         arch &= ( ARCH_WINNT | ARCH_OS2 );
3030       else if (strcsequal(p,"LM1.2X002"))
3031         arch &= ( ARCH_WINNT | ARCH_OS2 );
3032       else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
3033         arch &= ARCH_WINNT;
3034       else if (strcsequal(p,"XENIX CORE"))
3035         arch &= ( ARCH_WINNT | ARCH_OS2 );
3036       else if (strcsequal(p,"Samba")) {
3037         arch = ARCH_SAMBA;
3038         break;
3039       }
3040  
3041       p += strlen(p) + 2;
3042     }
3043     
3044   switch ( arch ) {
3045   case ARCH_SAMBA:
3046     strcpy(remote_arch,"Samba");
3047     break;
3048   case ARCH_WFWG:
3049     strcpy(remote_arch,"WfWg");
3050     break;
3051   case ARCH_WIN95:
3052     strcpy(remote_arch,"Win95");
3053     break;
3054   case ARCH_WINNT:
3055     strcpy(remote_arch,"WinNT");
3056     break;
3057   case ARCH_OS2:
3058     strcpy(remote_arch,"OS2");
3059     break;
3060   default:
3061     strcpy(remote_arch,"UNKNOWN");
3062     break;
3063   }
3064  
3065   /* possibly reload - change of architecture */
3066   reload_services(True);      
3067     
3068   /* a special case to stop password server loops */
3069   if (Index == 1 && strequal(remote_machine,myhostname) && 
3070       lp_security()==SEC_SERVER)
3071     exit_server("Password server loop!");
3072   
3073   /* Check for protocols, most desirable first */
3074   for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
3075     {
3076       p = smb_buf(inbuf)+1;
3077       Index = 0;
3078       if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
3079         while (p < (smb_buf(inbuf) + bcc))
3080           { 
3081             if (strequal(p,supported_protocols[protocol].proto_name))
3082               choice = Index;
3083             Index++;
3084             p += strlen(p) + 2;
3085           }
3086       if(choice != -1)
3087         break;
3088     }
3089   
3090   SSVAL(outbuf,smb_vwv0,choice);
3091   if(choice != -1) {
3092     extern fstring remote_proto;
3093     strcpy(remote_proto,supported_protocols[protocol].short_name);
3094     reload_services(True);          
3095     outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
3096     DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
3097   }
3098   else {
3099     DEBUG(0,("No protocol supported !\n"));
3100   }
3101   SSVAL(outbuf,smb_vwv0,choice);
3102   
3103   DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
3104
3105   return(outsize);
3106 }
3107
3108
3109 /****************************************************************************
3110 close all open files for a connection
3111 ****************************************************************************/
3112 static void close_open_files(int cnum)
3113 {
3114   int i;
3115   for (i=0;i<MAX_OPEN_FILES;i++)
3116     if( Files[i].cnum == cnum && Files[i].open) {
3117       close_file(i);
3118     }
3119 }
3120
3121
3122
3123 /****************************************************************************
3124 close a cnum
3125 ****************************************************************************/
3126 void close_cnum(int cnum, uint16 vuid)
3127 {
3128   DirCacheFlush(SNUM(cnum));
3129
3130   unbecome_user();
3131
3132   if (!OPEN_CNUM(cnum))
3133     {
3134       DEBUG(0,("Can't close cnum %d\n",cnum));
3135       return;
3136     }
3137
3138   DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
3139                           timestring(),
3140                           remote_machine,client_addr(),
3141                           lp_servicename(SNUM(cnum))));
3142
3143   yield_connection(cnum,
3144                    lp_servicename(SNUM(cnum)),
3145                    lp_max_connections(SNUM(cnum)));
3146
3147   if (lp_status(SNUM(cnum)))
3148     yield_connection(cnum,"STATUS.",MAXSTATUS);
3149
3150   close_open_files(cnum);
3151   dptr_closecnum(cnum);
3152
3153   /* execute any "postexec = " line */
3154   if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid))
3155     {
3156       pstring cmd;
3157       strcpy(cmd,lp_postexec(SNUM(cnum)));
3158       standard_sub(cnum,cmd);
3159       smbrun(cmd,NULL,False);
3160       unbecome_user();
3161     }
3162
3163   unbecome_user();
3164   /* execute any "root postexec = " line */
3165   if (*lp_rootpostexec(SNUM(cnum)))
3166     {
3167       pstring cmd;
3168       strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
3169       standard_sub(cnum,cmd);
3170       smbrun(cmd,NULL,False);
3171     }
3172
3173   Connections[cnum].open = False;
3174   num_connections_open--;
3175   if (Connections[cnum].ngroups && Connections[cnum].groups)
3176     {
3177       if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
3178         free(Connections[cnum].groups);
3179       free(Connections[cnum].igroups);
3180       Connections[cnum].groups = NULL;
3181       Connections[cnum].igroups = NULL;
3182       Connections[cnum].ngroups = 0;
3183     }
3184
3185   free_namearray(Connections[cnum].veto_list);
3186   free_namearray(Connections[cnum].hide_list);
3187
3188   string_set(&Connections[cnum].user,"");
3189   string_set(&Connections[cnum].dirpath,"");
3190   string_set(&Connections[cnum].connectpath,"");
3191 }
3192
3193
3194 /****************************************************************************
3195 simple routines to do connection counting
3196 ****************************************************************************/
3197 BOOL yield_connection(int cnum,char *name,int max_connections)
3198 {
3199   struct connect_record crec;
3200   pstring fname;
3201   FILE *f;
3202   int mypid = getpid();
3203   int i;
3204
3205   DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
3206
3207   if (max_connections <= 0)
3208     return(True);
3209
3210   bzero(&crec,sizeof(crec));
3211
3212   strcpy(fname,lp_lockdir());
3213   standard_sub(cnum,fname);
3214   trim_string(fname,"","/");
3215
3216   strcat(fname,"/");
3217   strcat(fname,name);
3218   strcat(fname,".LCK");
3219
3220   f = fopen(fname,"r+");
3221   if (!f)
3222     {
3223       DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno)));
3224       return(False);
3225     }
3226
3227   fseek(f,0,SEEK_SET);
3228
3229   /* find a free spot */
3230   for (i=0;i<max_connections;i++)
3231     {
3232       if (fread(&crec,sizeof(crec),1,f) != 1)
3233         {
3234           DEBUG(2,("Entry not found in lock file %s\n",fname));
3235           fclose(f);
3236           return(False);
3237         }
3238       if (crec.pid == mypid && crec.cnum == cnum)
3239         break;
3240     }
3241
3242   if (crec.pid != mypid || crec.cnum != cnum)
3243     {
3244       fclose(f);
3245       DEBUG(2,("Entry not found in lock file %s\n",fname));
3246       return(False);
3247     }
3248
3249   bzero((void *)&crec,sizeof(crec));
3250   
3251   /* remove our mark */
3252   if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3253       fwrite(&crec,sizeof(crec),1,f) != 1)
3254     {
3255       DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
3256       fclose(f);
3257       return(False);
3258     }
3259
3260   DEBUG(3,("Yield successful\n"));
3261
3262   fclose(f);
3263   return(True);
3264 }
3265
3266
3267 /****************************************************************************
3268 simple routines to do connection counting
3269 ****************************************************************************/
3270 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
3271 {
3272   struct connect_record crec;
3273   pstring fname;
3274   FILE *f;
3275   int snum = SNUM(cnum);
3276   int i,foundi= -1;
3277   int total_recs;
3278
3279   if (max_connections <= 0)
3280     return(True);
3281
3282   DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
3283
3284   strcpy(fname,lp_lockdir());
3285   standard_sub(cnum,fname);
3286   trim_string(fname,"","/");
3287
3288   if (!directory_exist(fname,NULL))
3289     mkdir(fname,0755);
3290
3291   strcat(fname,"/");
3292   strcat(fname,name);
3293   strcat(fname,".LCK");
3294
3295   if (!file_exist(fname,NULL))
3296     {
3297       int oldmask = umask(022);
3298       f = fopen(fname,"w");
3299       if (f) fclose(f);
3300       umask(oldmask);
3301     }
3302
3303   total_recs = file_size(fname) / sizeof(crec);
3304
3305   f = fopen(fname,"r+");
3306
3307   if (!f)
3308     {
3309       DEBUG(1,("couldn't open lock file %s\n",fname));
3310       return(False);
3311     }
3312
3313   /* find a free spot */
3314   for (i=0;i<max_connections;i++)
3315     {
3316
3317       if (i>=total_recs || 
3318           fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3319           fread(&crec,sizeof(crec),1,f) != 1)
3320         {
3321           if (foundi < 0) foundi = i;
3322           break;
3323         }
3324
3325       if (Clear && crec.pid && !process_exists(crec.pid))
3326         {
3327           fseek(f,i*sizeof(crec),SEEK_SET);
3328           bzero((void *)&crec,sizeof(crec));
3329           fwrite(&crec,sizeof(crec),1,f);
3330           if (foundi < 0) foundi = i;
3331           continue;
3332         }
3333       if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
3334         {
3335           foundi=i;
3336           if (!Clear) break;
3337         }
3338     }  
3339
3340   if (foundi < 0)
3341     {
3342       DEBUG(3,("no free locks in %s\n",fname));
3343       fclose(f);
3344       return(False);
3345     }      
3346
3347   /* fill in the crec */
3348   bzero((void *)&crec,sizeof(crec));
3349   crec.magic = 0x280267;
3350   crec.pid = getpid();
3351   crec.cnum = cnum;
3352   crec.uid = Connections[cnum].uid;
3353   crec.gid = Connections[cnum].gid;
3354   StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
3355   crec.start = time(NULL);
3356
3357   StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
3358   StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1);
3359   
3360   /* make our mark */
3361   if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
3362       fwrite(&crec,sizeof(crec),1,f) != 1)
3363     {
3364       fclose(f);
3365       return(False);
3366     }
3367
3368   fclose(f);
3369   return(True);
3370 }
3371
3372 #if DUMP_CORE
3373 /*******************************************************************
3374 prepare to dump a core file - carefully!
3375 ********************************************************************/
3376 static BOOL dump_core(void)
3377 {
3378   char *p;
3379   pstring dname;
3380   strcpy(dname,debugf);
3381   if ((p=strrchr(dname,'/'))) *p=0;
3382   strcat(dname,"/corefiles");
3383   mkdir(dname,0700);
3384   sys_chown(dname,getuid(),getgid());
3385   chmod(dname,0700);
3386   if (chdir(dname)) return(False);
3387   umask(~(0700));
3388
3389 #ifndef NO_GETRLIMIT
3390 #ifdef RLIMIT_CORE
3391   {
3392     struct rlimit rlp;
3393     getrlimit(RLIMIT_CORE, &rlp);
3394     rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
3395     setrlimit(RLIMIT_CORE, &rlp);
3396     getrlimit(RLIMIT_CORE, &rlp);
3397     DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
3398   }
3399 #endif
3400 #endif
3401
3402
3403   DEBUG(0,("Dumping core in %s\n",dname));
3404   return(True);
3405 }
3406 #endif
3407
3408 /****************************************************************************
3409 exit the server
3410 ****************************************************************************/
3411 void exit_server(char *reason)
3412 {
3413   static int firsttime=1;
3414   int i;
3415
3416   if (!firsttime) exit(0);
3417   firsttime = 0;
3418
3419   unbecome_user();
3420   DEBUG(2,("Closing connections\n"));
3421   for (i=0;i<MAX_CONNECTIONS;i++)
3422     if (Connections[i].open)
3423       close_cnum(i,-1);
3424 #ifdef DFS_AUTH
3425   if (dcelogin_atmost_once)
3426     dfs_unlogin();
3427 #endif
3428   if (!reason) {   
3429     int oldlevel = DEBUGLEVEL;
3430     DEBUGLEVEL = 10;
3431     DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
3432     if (last_inbuf)
3433       show_msg(last_inbuf);
3434     DEBUGLEVEL = oldlevel;
3435     DEBUG(0,("===============================================================\n"));
3436 #if DUMP_CORE
3437     if (dump_core()) return;
3438 #endif
3439   }    
3440
3441 #ifdef FAST_SHARE_MODES
3442   stop_share_mode_mgmt();
3443 #endif /* FAST_SHARE_MODES */
3444
3445   DEBUG(3,("%s Server exit  (%s)\n",timestring(),reason?reason:""));
3446   exit(0);
3447 }
3448
3449 /****************************************************************************
3450 do some standard substitutions in a string
3451 ****************************************************************************/
3452 void standard_sub(int cnum,char *string)
3453 {
3454   if (VALID_CNUM(cnum)) {
3455     char *p, *s, *home;
3456
3457     for ( s=string ; (p=strchr(s, '%')) != NULL ; s=p ) {
3458       switch (*(p+1)) {
3459         case 'H' : if ((home = get_home_dir(Connections[cnum].user))!=NULL)
3460                      string_sub(p,"%H",home);
3461                    else
3462                      p += 2;
3463                    break;
3464         case 'P' : string_sub(p,"%P",Connections[cnum].connectpath); break;
3465         case 'S' : string_sub(p,"%S",lp_servicename(Connections[cnum].service)); break;
3466         case 'g' : string_sub(p,"%g",gidtoname(Connections[cnum].gid)); break;
3467         case 'u' : string_sub(p,"%u",Connections[cnum].user); break;
3468         case '\0' : p++; break; /* don't run off the end of the string */
3469         default  : p+=2; break;
3470       }
3471     }
3472   }
3473   standard_sub_basic(string);
3474 }
3475
3476 /*
3477 These flags determine some of the permissions required to do an operation 
3478
3479 Note that I don't set NEED_WRITE on some write operations because they
3480 are used by some brain-dead clients when printing, and I don't want to
3481 force write permissions on print services.
3482 */
3483 #define AS_USER (1<<0)
3484 #define NEED_WRITE (1<<1)
3485 #define TIME_INIT (1<<2)
3486 #define CAN_IPC (1<<3)
3487 #define AS_GUEST (1<<5)
3488
3489
3490 /* 
3491    define a list of possible SMB messages and their corresponding
3492    functions. Any message that has a NULL function is unimplemented -
3493    please feel free to contribute implementations!
3494 */
3495 struct smb_message_struct
3496 {
3497   int code;
3498   char *name;
3499   int (*fn)();
3500   int flags;
3501 #if PROFILING
3502   unsigned long time;
3503 #endif
3504 }
3505  smb_messages[] = {
3506
3507     /* CORE PROTOCOL */
3508
3509    {SMBnegprot,"SMBnegprot",reply_negprot,0},
3510    {SMBtcon,"SMBtcon",reply_tcon,0},
3511    {SMBtdis,"SMBtdis",reply_tdis,0},
3512    {SMBexit,"SMBexit",reply_exit,0},
3513    {SMBioctl,"SMBioctl",reply_ioctl,0},
3514    {SMBecho,"SMBecho",reply_echo,0},
3515    {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
3516    {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
3517    {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
3518    {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3519    {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3520    {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3521    {SMBsearch,"SMBsearch",reply_search,AS_USER},
3522    {SMBopen,"SMBopen",reply_open,AS_USER},
3523
3524    /* note that SMBmknew and SMBcreate are deliberately overloaded */   
3525    {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3526    {SMBmknew,"SMBmknew",reply_mknew,AS_USER}, 
3527
3528    {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3529    {SMBread,"SMBread",reply_read,AS_USER},
3530    {SMBwrite,"SMBwrite",reply_write,AS_USER},
3531    {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
3532    {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3533    {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3534    {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3535    {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3536
3537    /* this is a Pathworks specific call, allowing the 
3538       changing of the root path */
3539    {pSETDIR,"pSETDIR",reply_setdir,AS_USER}, 
3540
3541    {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3542    {SMBflush,"SMBflush",reply_flush,AS_USER},
3543    {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3544    {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3545    {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3546    {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST},
3547    {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3548    {SMBlock,"SMBlock",reply_lock,AS_USER},
3549    {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3550    
3551    /* CORE+ PROTOCOL FOLLOWS */
3552    
3553    {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3554    {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3555    {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3556    {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3557    {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3558    
3559    /* LANMAN1.0 PROTOCOL FOLLOWS */
3560    
3561    {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3562    {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3563    {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3564    {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3565    {SMBwritec,"SMBwritec",NULL,AS_USER},
3566    {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3567    {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3568    {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3569    {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3570    {SMBioctls,"SMBioctls",NULL,AS_USER},
3571    {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3572    {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3573    
3574    {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC},
3575    {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3576    {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3577    {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3578    
3579    {SMBffirst,"SMBffirst",reply_search,AS_USER},
3580    {SMBfunique,"SMBfunique",reply_search,AS_USER},
3581    {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3582
3583    /* LANMAN2.0 PROTOCOL FOLLOWS */
3584    {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3585    {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3586    {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3587    {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3588
3589    /* messaging routines */
3590    {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3591    {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3592    {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3593    {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3594
3595    /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3596    
3597    {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3598    {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3599    {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3600    {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3601  };
3602
3603 /****************************************************************************
3604 return a string containing the function name of a SMB command
3605 ****************************************************************************/
3606 char *smb_fn_name(int type)
3607 {
3608   static char *unknown_name = "SMBunknown";
3609   static int num_smb_messages = 
3610     sizeof(smb_messages) / sizeof(struct smb_message_struct);
3611   int match;
3612
3613   for (match=0;match<num_smb_messages;match++)
3614     if (smb_messages[match].code == type)
3615       break;
3616
3617   if (match == num_smb_messages)
3618     return(unknown_name);
3619
3620   return(smb_messages[match].name);
3621 }
3622
3623
3624 /****************************************************************************
3625 do a switch on the message type, and return the response size
3626 ****************************************************************************/
3627 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3628 {
3629   static int pid= -1;
3630   int outsize = 0;
3631   static int num_smb_messages = 
3632     sizeof(smb_messages) / sizeof(struct smb_message_struct);
3633   int match;
3634
3635 #if PROFILING
3636   struct timeval msg_start_time;
3637   struct timeval msg_end_time;
3638   static unsigned long total_time = 0;
3639
3640   GetTimeOfDay(&msg_start_time);
3641 #endif
3642
3643   if (pid == -1)
3644     pid = getpid();
3645
3646   errno = 0;
3647   last_message = type;
3648
3649   /* make sure this is an SMB packet */
3650   if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3651     {
3652       DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3653       return(-1);
3654     }
3655
3656   for (match=0;match<num_smb_messages;match++)
3657     if (smb_messages[match].code == type)
3658       break;
3659
3660   if (match == num_smb_messages)
3661     {
3662       DEBUG(0,("Unknown message type %d!\n",type));
3663       outsize = reply_unknown(inbuf,outbuf);
3664     }
3665   else
3666     {
3667       DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3668       if (smb_messages[match].fn)
3669         {
3670           int cnum = SVAL(inbuf,smb_tid);
3671           int flags = smb_messages[match].flags;
3672           uint16 session_tag = SVAL(inbuf,smb_uid);
3673
3674           /* does this protocol need to be run as root? */
3675           if (!(flags & AS_USER))
3676             unbecome_user();
3677
3678           /* does this protocol need to be run as the connected user? */
3679           if ((flags & AS_USER) && !become_user(cnum,session_tag)) {
3680             if (flags & AS_GUEST) 
3681               flags &= ~AS_USER;
3682             else
3683               return(ERROR(ERRSRV,ERRinvnid));
3684           }
3685           /* this code is to work around a bug is MS client 3 without
3686              introducing a security hole - it needs to be able to do
3687              print queue checks as guest if it isn't logged in properly */
3688           if (flags & AS_USER)
3689             flags &= ~AS_GUEST;
3690
3691           /* does it need write permission? */
3692           if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3693             return(ERROR(ERRSRV,ERRaccess));
3694
3695           /* ipc services are limited */
3696           if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3697             return(ERROR(ERRSRV,ERRaccess));        
3698
3699           /* load service specific parameters */
3700           if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3701             return(ERROR(ERRSRV,ERRaccess));
3702
3703           /* does this protocol need to be run as guest? */
3704           if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3705             return(ERROR(ERRSRV,ERRaccess));
3706
3707           last_inbuf = inbuf;
3708
3709           outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3710         }
3711       else
3712         {
3713           outsize = reply_unknown(inbuf,outbuf);
3714         }
3715     }
3716
3717 #if PROFILING
3718   GetTimeOfDay(&msg_end_time);
3719   if (!(smb_messages[match].flags & TIME_INIT))
3720     {
3721       smb_messages[match].time = 0;
3722       smb_messages[match].flags |= TIME_INIT;
3723     }
3724   {
3725     unsigned long this_time =     
3726       (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3727         (msg_end_time.tv_usec - msg_start_time.tv_usec);
3728     smb_messages[match].time += this_time;
3729     total_time += this_time;
3730   }
3731   DEBUG(2,("TIME %s  %d usecs   %g pct\n",
3732            smb_fn_name(type),smb_messages[match].time,
3733         (100.0*smb_messages[match].time) / total_time));
3734 #endif
3735
3736   return(outsize);
3737 }
3738
3739
3740 /****************************************************************************
3741   construct a chained reply and add it to the already made reply
3742   **************************************************************************/
3743 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
3744 {
3745   static char *orig_inbuf;
3746   static char *orig_outbuf;
3747   int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
3748   unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
3749   char *inbuf2, *outbuf2;
3750   int outsize2;
3751   char inbuf_saved[smb_wct];
3752   char outbuf_saved[smb_wct];
3753   extern int chain_size;
3754   int wct = CVAL(outbuf,smb_wct);
3755   int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
3756
3757   /* maybe its not chained */
3758   if (smb_com2 == 0xFF) {
3759     CVAL(outbuf,smb_vwv0) = 0xFF;
3760     return outsize;
3761   }
3762
3763   if (chain_size == 0) {
3764     /* this is the first part of the chain */
3765     orig_inbuf = inbuf;
3766     orig_outbuf = outbuf;
3767   }
3768
3769   /* we need to tell the client where the next part of the reply will be */
3770   SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
3771   CVAL(outbuf,smb_vwv0) = smb_com2;
3772
3773   /* remember how much the caller added to the chain, only counting stuff
3774      after the parameter words */
3775   chain_size += outsize - smb_wct;
3776
3777   /* work out pointers into the original packets. The
3778      headers on these need to be filled in */
3779   inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
3780   outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
3781
3782   /* remember the original command type */
3783   smb_com1 = CVAL(orig_inbuf,smb_com);
3784
3785   /* save the data which will be overwritten by the new headers */
3786   memcpy(inbuf_saved,inbuf2,smb_wct);
3787   memcpy(outbuf_saved,outbuf2,smb_wct);
3788
3789   /* give the new packet the same header as the last part of the SMB */
3790   memmove(inbuf2,inbuf,smb_wct);
3791
3792   /* create the in buffer */
3793   CVAL(inbuf2,smb_com) = smb_com2;
3794
3795   /* create the out buffer */
3796   bzero(outbuf2,smb_size);
3797   set_message(outbuf2,0,0,True);
3798   CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com);
3799   
3800   memcpy(outbuf2+4,inbuf2+4,4);
3801   CVAL(outbuf2,smb_rcls) = SUCCESS;
3802   CVAL(outbuf2,smb_reh) = 0;
3803   CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set 
3804                                                                   means a reply */
3805   SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */
3806   SSVAL(outbuf2,smb_err,SUCCESS);
3807   SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid));
3808   SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid));
3809   SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid));
3810   SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid));
3811
3812   DEBUG(3,("Chained message\n"));
3813   show_msg(inbuf2);
3814
3815   /* process the request */
3816   outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
3817                             bufsize-chain_size);
3818
3819   /* copy the new reply and request headers over the old ones, but
3820      preserve the smb_com field */
3821   memmove(orig_outbuf,outbuf2,smb_wct);
3822   CVAL(orig_outbuf,smb_com) = smb_com1;
3823
3824   /* restore the saved data, being careful not to overwrite any
3825    data from the reply header */
3826   memcpy(inbuf2,inbuf_saved,smb_wct);
3827   {
3828     int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
3829     if (ofs < 0) ofs = 0;
3830     memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
3831   }
3832
3833   return outsize2;
3834 }
3835
3836
3837
3838 /****************************************************************************
3839   construct a reply to the incoming packet
3840 ****************************************************************************/
3841 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3842 {
3843   int type = CVAL(inbuf,smb_com);
3844   int outsize = 0;
3845   int msg_type = CVAL(inbuf,0);
3846   extern int chain_size;
3847
3848   smb_last_time = time(NULL);
3849
3850   chain_size = 0;
3851   chain_fnum = -1;
3852
3853   bzero(outbuf,smb_size);
3854
3855   if (msg_type != 0)
3856     return(reply_special(inbuf,outbuf));  
3857
3858   CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3859   set_message(outbuf,0,0,True);
3860   
3861   memcpy(outbuf+4,inbuf+4,4);
3862   CVAL(outbuf,smb_rcls) = SUCCESS;
3863   CVAL(outbuf,smb_reh) = 0;
3864   CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set 
3865                                                              means a reply */
3866   SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3867   SSVAL(outbuf,smb_err,SUCCESS);
3868   SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3869   SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3870   SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3871   SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3872
3873   outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3874
3875   outsize += chain_size;
3876
3877   if(outsize > 4)
3878     smb_setlen(outbuf,outsize - 4);
3879   return(outsize);
3880 }
3881
3882
3883 /****************************************************************************
3884   process commands from the client
3885 ****************************************************************************/
3886 static void process(void)
3887 {
3888   static int trans_num = 0;
3889   int nread;
3890   extern int Client;
3891
3892   InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3893   OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3894   if ((InBuffer == NULL) || (OutBuffer == NULL)) 
3895     return;
3896
3897   InBuffer += SMB_ALIGNMENT;
3898   OutBuffer += SMB_ALIGNMENT;
3899
3900 #if PRIME_NMBD
3901   DEBUG(3,("priming nmbd\n"));
3902   {
3903     struct in_addr ip;
3904     ip = *interpret_addr2("localhost");
3905     if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3906     *OutBuffer = 0;
3907     send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
3908   }
3909 #endif    
3910
3911   while (True)
3912     {
3913       int32 len;      
3914       int msg_type;
3915       int msg_flags;
3916       int type;
3917       int deadtime = lp_deadtime()*60;
3918       int counter;
3919       int last_keepalive=0;
3920       int service_load_counter = 0;
3921
3922       if (deadtime <= 0)
3923         deadtime = DEFAULT_SMBD_TIMEOUT;
3924
3925       if (lp_readprediction())
3926         do_read_prediction();
3927
3928       errno = 0;      
3929
3930       for (counter=SMBD_SELECT_LOOP; 
3931            !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000); 
3932            counter += SMBD_SELECT_LOOP)
3933         {
3934           int i;
3935           time_t t;
3936           BOOL allidle = True;
3937           extern int keepalive;
3938
3939       if (counter > 365 * 3600) /* big number of seconds. */
3940       {
3941         counter = 0;
3942         service_load_counter = 0;
3943       }
3944
3945           if (smb_read_error == READ_EOF) {
3946             DEBUG(3,("end of file from client\n"));
3947             return;
3948           }
3949
3950           if (smb_read_error == READ_ERROR) {
3951             DEBUG(3,("receive_smb error (%s) exiting\n",
3952                      strerror(errno)));
3953             return;
3954           }
3955
3956           t = time(NULL);
3957
3958           /* become root again if waiting */
3959           unbecome_user();
3960
3961           /* check for smb.conf reload */
3962           if (counter >= service_load_counter + SMBD_RELOAD_CHECK)
3963       {
3964         service_load_counter = counter;
3965
3966         /* reload services, if files have changed. */
3967             reload_services(True);
3968       }
3969
3970           /* automatic timeout if all connections are closed */      
3971           if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3972             DEBUG(2,("%s Closing idle connection\n",timestring()));
3973             return;
3974           }
3975
3976           if (keepalive && (counter-last_keepalive)>keepalive) {
3977             extern int password_client;
3978             if (!send_keepalive(Client)) {
3979               DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3980               return;
3981             }       
3982             /* also send a keepalive to the password server if its still
3983                connected */
3984             if (password_client != -1)
3985               send_keepalive(password_client);
3986             last_keepalive = counter;
3987           }
3988
3989           /* check for connection timeouts */
3990           for (i=0;i<MAX_CONNECTIONS;i++)
3991             if (Connections[i].open)
3992               {
3993                 /* close dirptrs on connections that are idle */
3994                 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
3995                   dptr_idlecnum(i);
3996
3997                 if (Connections[i].num_files_open > 0 ||
3998                     (t-Connections[i].lastused)<deadtime)
3999                   allidle = False;
4000               }
4001
4002           if (allidle && num_connections_open>0) {
4003             DEBUG(2,("%s Closing idle connection 2\n",timestring()));
4004             return;
4005           }
4006         }
4007
4008       msg_type = CVAL(InBuffer,0);
4009       msg_flags = CVAL(InBuffer,1);
4010       type = CVAL(InBuffer,smb_com);
4011
4012       len = smb_len(InBuffer);
4013
4014       DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
4015
4016       nread = len + 4;
4017       
4018       DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
4019
4020 #ifdef WITH_VTP
4021       if(trans_num == 1 && VT_Check(InBuffer)) {
4022         VT_Process();
4023         return;
4024       }
4025 #endif
4026
4027
4028       if (msg_type == 0)
4029         show_msg(InBuffer);
4030
4031       nread = construct_reply(InBuffer,OutBuffer,nread,max_send);
4032       
4033       if(nread > 0) {
4034         if (CVAL(OutBuffer,0) == 0)
4035           show_msg(OutBuffer);
4036         
4037         if (nread != smb_len(OutBuffer) + 4) 
4038           {
4039             DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
4040                      nread,
4041                      smb_len(OutBuffer)));
4042           }
4043         else
4044           send_smb(Client,OutBuffer);
4045       }
4046       trans_num++;
4047     }
4048 }
4049
4050
4051 /****************************************************************************
4052   initialise connect, service and file structs
4053 ****************************************************************************/
4054 static void init_structs(void )
4055 {
4056   int i;
4057   get_myname(myhostname,NULL);
4058
4059   for (i=0;i<MAX_CONNECTIONS;i++)
4060     {
4061       Connections[i].open = False;
4062       Connections[i].num_files_open=0;
4063       Connections[i].lastused=0;
4064       Connections[i].used=False;
4065       string_init(&Connections[i].user,"");
4066       string_init(&Connections[i].dirpath,"");
4067       string_init(&Connections[i].connectpath,"");
4068       string_init(&Connections[i].origpath,"");
4069     }
4070
4071   for (i=0;i<MAX_OPEN_FILES;i++)
4072     {
4073       Files[i].open = False;
4074       string_init(&Files[i].name,"");
4075
4076     }
4077
4078   for (i=0;i<MAX_OPEN_FILES;i++)
4079     {
4080       file_fd_struct *fd_ptr = &FileFd[i];
4081       fd_ptr->ref_count = 0;
4082       fd_ptr->dev = (int32)-1;
4083       fd_ptr->inode = (int32)-1;
4084       fd_ptr->fd = -1;
4085       fd_ptr->fd_readonly = -1;
4086       fd_ptr->fd_writeonly = -1;
4087       fd_ptr->real_open_flags = -1;
4088     }
4089
4090   init_dptrs();
4091 }
4092
4093 /****************************************************************************
4094 usage on the program
4095 ****************************************************************************/
4096 static void usage(char *pname)
4097 {
4098   DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
4099
4100   printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
4101   printf("Version %s\n",VERSION);
4102   printf("\t-D                    become a daemon\n");
4103   printf("\t-p port               listen on the specified port\n");
4104   printf("\t-d debuglevel         set the debuglevel\n");
4105   printf("\t-l log basename.      Basename for log/debug files\n");
4106   printf("\t-s services file.     Filename of services file\n");
4107   printf("\t-P                    passive only\n");
4108   printf("\t-a                    overwrite log file, don't append\n");
4109   printf("\n");
4110 }
4111
4112
4113 /****************************************************************************
4114   main program
4115 ****************************************************************************/
4116  int main(int argc,char *argv[])
4117 {
4118   extern BOOL append_log;
4119   /* shall I run as a daemon */
4120   BOOL is_daemon = False;
4121   int port = SMB_PORT;
4122   int opt;
4123   extern char *optarg;
4124   char pidFile[100] = { 0 };
4125
4126 #ifdef NEED_AUTH_PARAMETERS
4127   set_auth_parameters(argc,argv);
4128 #endif
4129
4130 #ifdef SecureWare
4131   setluid(0);
4132 #endif
4133
4134   append_log = True;
4135
4136   TimeInit();
4137
4138   strcpy(debugf,SMBLOGFILE);  
4139
4140   setup_logging(argv[0],False);
4141
4142   charset_initialise();
4143
4144   /* make absolutely sure we run as root - to handle cases whre people
4145      are crazy enough to have it setuid */
4146 #ifdef USE_SETRES
4147   setresuid(0,0,0);
4148 #else
4149   setuid(0);
4150   seteuid(0);
4151   setuid(0);
4152   seteuid(0);
4153 #endif
4154
4155   fault_setup(exit_server);
4156   signal(SIGTERM , SIGNAL_CAST dflt_sig);
4157
4158   /* we want total control over the permissions on created files,
4159      so set our umask to 0 */
4160   umask(0);
4161
4162   GetWd(OriginalDir);
4163
4164   init_uid();
4165
4166   /* this is for people who can't start the program correctly */
4167   while (argc > 1 && (*argv[1] != '-'))
4168     {
4169       argv++;
4170       argc--;
4171     }
4172
4173   while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF)
4174     switch (opt)
4175       {
4176       case 'f':
4177         strncpy(pidFile, optarg, sizeof(pidFile));
4178         break;
4179       case 'O':
4180         strcpy(user_socket_options,optarg);
4181         break;
4182       case 'i':
4183         strcpy(scope,optarg);
4184         break;
4185       case 'P':
4186         {
4187           extern BOOL passive;
4188           passive = True;
4189         }
4190         break;  
4191       case 's':
4192         strcpy(servicesf,optarg);
4193         break;
4194       case 'l':
4195         strcpy(debugf,optarg);
4196         break;
4197       case 'a':
4198         {
4199           extern BOOL append_log;
4200           append_log = !append_log;
4201         }
4202         break;
4203       case 'D':
4204         is_daemon = True;
4205         break;
4206       case 'd':
4207         if (*optarg == 'A')
4208           DEBUGLEVEL = 10000;
4209         else
4210           DEBUGLEVEL = atoi(optarg);
4211         break;
4212       case 'p':
4213         port = atoi(optarg);
4214         break;
4215       case 'h':
4216         usage(argv[0]);
4217         exit(0);
4218         break;
4219       default:
4220         usage(argv[0]);
4221         exit(1);
4222       }
4223
4224   reopen_logs();
4225
4226   DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
4227   DEBUG(2,("Copyright Andrew Tridgell 1992-1997\n"));
4228
4229 #ifndef NO_GETRLIMIT
4230 #ifdef RLIMIT_NOFILE
4231   {
4232     struct rlimit rlp;
4233     getrlimit(RLIMIT_NOFILE, &rlp);
4234     rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
4235     setrlimit(RLIMIT_NOFILE, &rlp);
4236     getrlimit(RLIMIT_NOFILE, &rlp);
4237     DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
4238   }
4239 #endif
4240 #endif
4241
4242   
4243   DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4244         getuid(),getgid(),geteuid(),getegid()));
4245
4246   if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
4247     {
4248       DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
4249       exit(1);
4250     }
4251
4252   init_structs();
4253
4254   if (!reload_services(False))
4255     return(-1); 
4256
4257   codepage_initialise(lp_client_code_page());
4258
4259   strcpy(myworkgroup, lp_workgroup());
4260
4261 #ifndef NO_SIGNAL_TEST
4262   signal(SIGHUP,SIGNAL_CAST sig_hup);
4263 #endif
4264   
4265   DEBUG(3,("%s loaded services\n",timestring()));
4266
4267   if (!is_daemon && !is_a_socket(0))
4268     {
4269       DEBUG(0,("standard input is not a socket, assuming -D option\n"));
4270       is_daemon = True;
4271     }
4272
4273   if (is_daemon)
4274     {
4275       DEBUG(3,("%s becoming a daemon\n",timestring()));
4276       become_daemon();
4277     }
4278
4279   if (*pidFile)
4280     {
4281       int     fd;
4282       char    buf[20];
4283
4284       if ((fd = open(pidFile,
4285 #ifdef O_NONBLOCK
4286          O_NONBLOCK | 
4287 #endif
4288          O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
4289         {
4290            DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
4291            exit(1);
4292         }
4293       if(fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
4294         {
4295           DEBUG(0,("ERROR: smbd is already running\n"));
4296           exit(1);
4297         }
4298       sprintf(buf, "%u\n", (unsigned int) getpid());
4299       if (write(fd, buf, strlen(buf)) < 0)
4300         {
4301           DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
4302           exit(1);
4303         }
4304       /* Leave pid file open & locked for the duration... */
4305     }
4306
4307   if (!open_sockets(is_daemon,port))
4308     exit(1);
4309
4310 #ifdef FAST_SHARE_MODES
4311   if (!start_share_mode_mgmt())
4312     exit(1);
4313 #endif /* FAST_SHARE_MODES */
4314
4315   /* possibly reload the services file. */
4316   reload_services(True);
4317
4318   max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
4319
4320   if (*lp_rootdir())
4321     {
4322       if (sys_chroot(lp_rootdir()) == 0)
4323         DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4324     }
4325
4326   process();
4327   close_sockets();
4328
4329   exit_server("normal exit");
4330   return(0);
4331 }
4332
4333