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