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