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