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