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