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