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