- a huge pile of changes from Luke which implement the browse.conf
[kai/samba.git] / source / smbd / server.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Main SMB server routines
5    Copyright (C) Andrew Tridgell 1992-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   extern int password_client;
1622   BlockSignals(True,SIGPIPE);
1623
1624   if (password_client != -1) {
1625     DEBUG(3,("lost connection to password server\n"));
1626     close(password_client);
1627     password_client = -1;
1628 #ifndef DONT_REINSTALL_SIG
1629     signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1630 #endif
1631     BlockSignals(False,SIGPIPE);
1632     return 0;
1633   }
1634
1635   exit_server("Got sigpipe\n");
1636   return(0);
1637 }
1638
1639 /****************************************************************************
1640   open the socket communication
1641 ****************************************************************************/
1642 static BOOL open_sockets(BOOL is_daemon,int port)
1643 {
1644   extern int Client;
1645
1646   if (is_daemon)
1647     {
1648       int s;
1649       struct sockaddr addr;
1650       int in_addrlen = sizeof(addr);
1651        
1652       /* Stop zombies */
1653 #ifdef SIGCLD_IGNORE
1654       signal(SIGCLD, SIG_IGN);
1655 #else
1656       signal(SIGCLD, SIGNAL_CAST sig_cld);
1657 #endif
1658
1659       /* open an incoming socket */
1660       s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
1661       if (s == -1)
1662         return(False);
1663
1664       /* ready to listen */
1665       if (listen(s, 5) == -1) 
1666         {
1667           DEBUG(0,("listen: %s",strerror(errno)));
1668           close(s);
1669           return False;
1670         }
1671       
1672       /* now accept incoming connections - forking a new process
1673          for each incoming connection */
1674       DEBUG(2,("waiting for a connection\n"));
1675       while (1)
1676         {
1677           Client = accept(s,&addr,&in_addrlen);
1678
1679           if (Client == -1 && errno == EINTR)
1680             continue;
1681
1682           if (Client == -1)
1683             {
1684               DEBUG(0,("accept: %s",strerror(errno)));
1685               continue;
1686             }
1687
1688 #ifdef NO_FORK_DEBUG
1689 #ifndef NO_SIGNAL_TEST
1690           signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1691           signal(SIGCLD, SIGNAL_CAST SIG_DFL);
1692 #endif
1693           return True;
1694 #else
1695           if (Client != -1 && fork()==0)
1696             {
1697 #ifndef NO_SIGNAL_TEST
1698               signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1699               signal(SIGCLD, SIGNAL_CAST SIG_DFL);
1700 #endif
1701               /* close the listening socket */
1702               close(s);
1703
1704               /* close our standard file descriptors */
1705               close_low_fds();
1706   
1707               set_socket_options(Client,"SO_KEEPALIVE");
1708               set_socket_options(Client,user_socket_options);
1709
1710               return True; 
1711             }
1712           close(Client); /* The parent doesn't need this socket */
1713 #endif
1714         }
1715     }
1716   else
1717     {
1718       /* We will abort gracefully when the client or remote system 
1719          goes away */
1720 #ifndef NO_SIGNAL_TEST
1721       signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1722 #endif
1723       Client = dup(0);
1724
1725       /* close our standard file descriptors */
1726       close_low_fds();
1727
1728       set_socket_options(Client,"SO_KEEPALIVE");
1729       set_socket_options(Client,user_socket_options);
1730     }
1731
1732   return True;
1733 }
1734
1735
1736 /****************************************************************************
1737 check if a snum is in use
1738 ****************************************************************************/
1739 BOOL snum_used(int snum)
1740 {
1741   int i;
1742   for (i=0;i<MAX_CONNECTIONS;i++)
1743     if (OPEN_CNUM(i) && (SNUM(i) == snum))
1744       return(True);
1745   return(False);
1746 }
1747
1748 /****************************************************************************
1749   reload the services file
1750   **************************************************************************/
1751 BOOL reload_services(BOOL test)
1752 {
1753   BOOL ret;
1754
1755   if (lp_loaded())
1756     {
1757       pstring fname;
1758       strcpy(fname,lp_configfile());
1759       if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
1760         {
1761           strcpy(servicesf,fname);
1762           test = False;
1763         }
1764     }
1765
1766   reopen_logs();
1767
1768   if (test && !lp_file_list_changed())
1769     return(True);
1770
1771   lp_killunused(snum_used);
1772
1773   ret = lp_load(servicesf,False);
1774
1775   /* perhaps the config filename is now set */
1776   if (!test)
1777     reload_services(True);
1778
1779   reopen_logs();
1780
1781   load_interfaces();
1782
1783   {
1784     extern int Client;
1785     if (Client != -1) {      
1786       set_socket_options(Client,"SO_KEEPALIVE");
1787       set_socket_options(Client,user_socket_options);
1788     }
1789   }
1790
1791   create_mangled_stack(lp_mangledstack());
1792
1793   /* this forces service parameters to be flushed */
1794   become_service(-1,True);
1795
1796   return(ret);
1797 }
1798
1799
1800
1801 /****************************************************************************
1802 this prevents zombie child processes
1803 ****************************************************************************/
1804 static int sig_hup()
1805 {
1806   BlockSignals(True,SIGHUP);
1807   DEBUG(0,("Got SIGHUP\n"));
1808   reload_services(False);
1809 #ifndef DONT_REINSTALL_SIG
1810   signal(SIGHUP,SIGNAL_CAST sig_hup);
1811 #endif
1812   BlockSignals(False,SIGHUP);
1813   return(0);
1814 }
1815
1816 /****************************************************************************
1817 Setup the groups a user belongs to.
1818 ****************************************************************************/
1819 int setup_groups(char *user, int uid, int gid, int *p_ngroups, 
1820                  int **p_igroups, gid_t **p_groups)
1821 {
1822   if (-1 == initgroups(user,gid))
1823     {
1824       if (getuid() == 0)
1825         {
1826           DEBUG(0,("Unable to initgroups!\n"));
1827           if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
1828             DEBUG(0,("This is probably a problem with the account %s\n",user));
1829         }
1830     }
1831   else
1832     {
1833       int i,ngroups;
1834       int *igroups;
1835       gid_t grp = 0;
1836       ngroups = getgroups(0,&grp);
1837       if (ngroups <= 0)
1838         ngroups = 32;
1839       igroups = (int *)malloc(sizeof(int)*ngroups);
1840       for (i=0;i<ngroups;i++)
1841         igroups[i] = 0x42424242;
1842       ngroups = getgroups(ngroups,(gid_t *)igroups);
1843
1844       if (igroups[0] == 0x42424242)
1845         ngroups = 0;
1846
1847       *p_ngroups = ngroups;
1848
1849       /* The following bit of code is very strange. It is due to the
1850          fact that some OSes use int* and some use gid_t* for
1851          getgroups, and some (like SunOS) use both, one in prototypes,
1852          and one in man pages and the actual code. Thus we detect it
1853          dynamically using some very ugly code */
1854       if (ngroups > 0)
1855         {
1856           /* does getgroups return ints or gid_t ?? */
1857           static BOOL groups_use_ints = True;
1858
1859           if (groups_use_ints && 
1860               ngroups == 1 && 
1861               SVAL(igroups,2) == 0x4242)
1862             groups_use_ints = False;
1863           
1864           for (i=0;groups_use_ints && i<ngroups;i++)
1865             if (igroups[i] == 0x42424242)
1866               groups_use_ints = False;
1867               
1868           if (groups_use_ints)
1869             {
1870               *p_igroups = igroups;
1871               *p_groups = (gid_t *)igroups;       
1872             }
1873           else
1874             {
1875               gid_t *groups = (gid_t *)igroups;
1876               igroups = (int *)malloc(sizeof(int)*ngroups);
1877               for (i=0;i<ngroups;i++)
1878                 igroups[i] = groups[i];
1879               *p_igroups = igroups;
1880               *p_groups = (gid_t *)groups;
1881             }
1882         }
1883       DEBUG(3,("%s is in %d groups\n",user,ngroups));
1884       for (i=0;i<ngroups;i++)
1885         DEBUG(3,("%d ",igroups[i]));
1886       DEBUG(3,("\n"));
1887     }
1888   return 0;
1889 }
1890
1891 /****************************************************************************
1892   make a connection to a service
1893 ****************************************************************************/
1894 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,int vuid)
1895 {
1896   int cnum;
1897   int snum;
1898   struct passwd *pass = NULL;
1899   connection_struct *pcon;
1900   BOOL guest = False;
1901   BOOL force = False;
1902   static BOOL first_connection = True;
1903
1904   strlower(service);
1905
1906   snum = find_service(service);
1907   if (snum < 0)
1908     {
1909       if (strequal(service,"IPC$"))
1910         {         
1911           DEBUG(3,("%s refusing IPC connection\n",timestring()));
1912           return(-3);
1913         }
1914
1915       DEBUG(0,("%s couldn't find service %s\n",timestring(),service));      
1916       return(-2);
1917     }
1918
1919   if (strequal(service,HOMES_NAME))
1920     {
1921       if (*user && Get_Pwnam(user,True))
1922         return(make_connection(user,user,password,pwlen,dev,vuid));
1923
1924       if (validated_username(vuid))
1925         {
1926           strcpy(user,validated_username(vuid));
1927           return(make_connection(user,user,password,pwlen,dev,vuid));
1928         }
1929     }
1930
1931   if (!lp_snum_ok(snum) || !check_access(snum)) {    
1932     return(-4);
1933   }
1934
1935   /* you can only connect to the IPC$ service as an ipc device */
1936   if (strequal(service,"IPC$"))
1937     strcpy(dev,"IPC");
1938
1939   if (*dev == '?' || !*dev)
1940     {
1941       if (lp_print_ok(snum))
1942         strcpy(dev,"LPT1:");
1943       else
1944         strcpy(dev,"A:");
1945     }
1946
1947   /* if the request is as a printer and you can't print then refuse */
1948   strupper(dev);
1949   if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
1950     DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
1951     return(-6);
1952   }
1953
1954   /* lowercase the user name */
1955   strlower(user);
1956
1957   /* add it as a possible user name */
1958   add_session_user(service);
1959
1960   /* shall we let them in? */
1961   if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
1962     {
1963       DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
1964       return(-1);
1965     }
1966   
1967   cnum = find_free_connection(str_checksum(service) + str_checksum(user));
1968   if (cnum < 0)
1969     {
1970       DEBUG(0,("%s couldn't find free connection\n",timestring()));      
1971       return(-1);
1972     }
1973
1974   pcon = &Connections[cnum];
1975   bzero((char *)pcon,sizeof(*pcon));
1976
1977   /* find out some info about the user */
1978   pass = Get_Pwnam(user,True);
1979
1980   if (pass == NULL)
1981     {
1982       DEBUG(0,("%s couldn't find account %s\n",timestring(),user)); 
1983       return(-7);
1984     }
1985
1986   pcon->read_only = lp_readonly(snum);
1987
1988   {
1989     pstring list;
1990     StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
1991     string_sub(list,"%S",service);
1992
1993     if (user_in_list(user,list))
1994       pcon->read_only = True;
1995
1996     StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
1997     string_sub(list,"%S",service);
1998
1999     if (user_in_list(user,list))
2000       pcon->read_only = False;    
2001   }
2002
2003   /* admin user check */
2004   if (user_in_list(user,lp_admin_users(snum)) &&
2005       !pcon->read_only)
2006     {
2007       pcon->admin_user = True;
2008       DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2009     }
2010   else
2011     pcon->admin_user = False;
2012     
2013   pcon->force_user = force;
2014   pcon->uid = pass->pw_uid;
2015   pcon->gid = pass->pw_gid;
2016   pcon->num_files_open = 0;
2017   pcon->lastused = time(NULL);
2018   pcon->service = snum;
2019   pcon->used = True;
2020   pcon->printer = (strncmp(dev,"LPT",3) == 0);
2021   pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2022   pcon->dirptr = NULL;
2023   string_set(&pcon->dirpath,"");
2024   string_set(&pcon->user,user);
2025
2026 #if HAVE_GETGRNAM 
2027   if (*lp_force_group(snum))
2028     {
2029       struct group *gptr = (struct group *)getgrnam(lp_force_group(snum));
2030       if (gptr)
2031         {
2032           pcon->gid = gptr->gr_gid;
2033           DEBUG(3,("Forced group %s\n",lp_force_group(snum)));
2034         }
2035       else
2036         DEBUG(1,("Couldn't find group %s\n",lp_force_group(snum)));
2037     }
2038 #endif
2039
2040   if (*lp_force_user(snum))
2041     {
2042       struct passwd *pass2;
2043       fstring fuser;
2044       strcpy(fuser,lp_force_user(snum));
2045       pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2046       if (pass2)
2047         {
2048           pcon->uid = pass2->pw_uid;
2049           string_set(&pcon->user,fuser);
2050           strcpy(user,fuser);
2051           pcon->force_user = True;
2052           DEBUG(3,("Forced user %s\n",fuser));    
2053         }
2054       else
2055         DEBUG(1,("Couldn't find user %s\n",fuser));
2056     }
2057
2058   {
2059     pstring s;
2060     strcpy(s,lp_pathname(snum));
2061     standard_sub(cnum,s);
2062     string_set(&pcon->connectpath,s);
2063     DEBUG(3,("Connect path is %s\n",s));
2064   }
2065
2066   /* groups stuff added by ih */
2067   pcon->ngroups = 0;
2068   pcon->groups = NULL;
2069
2070   if (!IS_IPC(cnum))
2071     {
2072       /* Find all the groups this uid is in and store them. Used by become_user() */
2073       setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2074       
2075       /* check number of connections */
2076       if (!claim_connection(cnum,
2077                             lp_servicename(SNUM(cnum)),
2078                             lp_max_connections(SNUM(cnum)),False))
2079         {
2080           DEBUG(1,("too many connections - rejected\n"));
2081           return(-8);
2082         }  
2083
2084       if (lp_status(SNUM(cnum)))
2085         claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2086
2087       first_connection = False;
2088     } /* IS_IPC */
2089
2090   pcon->open = True;
2091
2092   /* execute any "root preexec = " line */
2093   if (*lp_rootpreexec(SNUM(cnum)))
2094     {
2095       pstring cmd;
2096       strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2097       standard_sub(cnum,cmd);
2098       DEBUG(5,("cmd=%s\n",cmd));
2099       smbrun(cmd,NULL);
2100     }
2101
2102   if (!become_user(cnum,pcon->uid))
2103     {
2104       DEBUG(0,("Can't become connected user!\n"));
2105       pcon->open = False;
2106       if (!IS_IPC(cnum)) {
2107         yield_connection(cnum,
2108                          lp_servicename(SNUM(cnum)),
2109                          lp_max_connections(SNUM(cnum)));
2110         if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2111       }
2112       return(-1);
2113     }
2114
2115   if (ChDir(pcon->connectpath) != 0)
2116     {
2117       DEBUG(0,("Can't change directory to %s (%s)\n",
2118                pcon->connectpath,strerror(errno)));
2119       pcon->open = False;
2120       unbecome_user();
2121       if (!IS_IPC(cnum)) {
2122         yield_connection(cnum,
2123                          lp_servicename(SNUM(cnum)),
2124                          lp_max_connections(SNUM(cnum)));
2125         if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2126       }
2127       return(-5);      
2128     }
2129
2130   string_set(&pcon->origpath,pcon->connectpath);
2131
2132 #if SOFTLINK_OPTIMISATION
2133   /* resolve any soft links early */
2134   {
2135     pstring s;
2136     strcpy(s,pcon->connectpath);
2137     GetWd(s);
2138     string_set(&pcon->connectpath,s);
2139     ChDir(pcon->connectpath);
2140   }
2141 #endif
2142
2143   num_connections_open++;
2144   add_session_user(user);
2145   
2146   /* execute any "preexec = " line */
2147   if (*lp_preexec(SNUM(cnum)))
2148     {
2149       pstring cmd;
2150       strcpy(cmd,lp_preexec(SNUM(cnum)));
2151       standard_sub(cnum,cmd);
2152       smbrun(cmd,NULL);
2153     }
2154   
2155   /* we've finished with the sensitive stuff */
2156   unbecome_user();
2157
2158   {
2159     extern struct from_host Client_info;
2160     DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2161                             timestring(),
2162                             Client_info.name,Client_info.addr,
2163                             lp_servicename(SNUM(cnum)),user,
2164                             pcon->uid,
2165                             pcon->gid,
2166                             (int)getpid()));
2167   }
2168
2169   return(cnum);
2170 }
2171
2172
2173 /****************************************************************************
2174   find first available file slot
2175 ****************************************************************************/
2176 int find_free_file(void )
2177 {
2178   int i;
2179   /* we start at 1 here for an obscure reason I can't now remember,
2180      but I think is important :-) */
2181   for (i=1;i<MAX_OPEN_FILES;i++)
2182     if (!Files[i].open)
2183       return(i);
2184   DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2185   return(-1);
2186 }
2187
2188 /****************************************************************************
2189   find first available connection slot, starting from a random position.
2190 The randomisation stops problems with the server dieing and clients
2191 thinking the server is still available.
2192 ****************************************************************************/
2193 static int find_free_connection(int hash )
2194 {
2195   int i;
2196   BOOL used=False;
2197   hash = (hash % (MAX_CONNECTIONS-2))+1;
2198
2199  again:
2200
2201   for (i=hash+1;i!=hash;)
2202     {
2203       if (!Connections[i].open && Connections[i].used == used) 
2204         {
2205           DEBUG(3,("found free connection number %d\n",i));
2206           return(i);
2207         }
2208       i++;
2209       if (i == MAX_CONNECTIONS)
2210         i = 1;
2211     }
2212
2213   if (!used)
2214     {
2215       used = !used;
2216       goto again;
2217     }
2218
2219   DEBUG(1,("ERROR! Out of connection structures\n"));
2220   return(-1);
2221 }
2222
2223
2224 /****************************************************************************
2225 reply for the core protocol
2226 ****************************************************************************/
2227 int reply_corep(char *outbuf)
2228 {
2229   int outsize = set_message(outbuf,1,0,True);
2230
2231   Protocol = PROTOCOL_CORE;
2232
2233   return outsize;
2234 }
2235
2236
2237 /****************************************************************************
2238 reply for the coreplus protocol
2239 ****************************************************************************/
2240 int reply_coreplus(char *outbuf)
2241 {
2242   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2243   int outsize = set_message(outbuf,13,0,True);
2244   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2245                                  readbraw and writebraw (possibly) */
2246   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2247   SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */  
2248
2249   Protocol = PROTOCOL_COREPLUS;
2250
2251   return outsize;
2252 }
2253
2254
2255 /****************************************************************************
2256 reply for the lanman 1.0 protocol
2257 ****************************************************************************/
2258 int reply_lanman1(char *outbuf)
2259 {
2260   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2261   int secword=0;
2262   BOOL doencrypt = SMBENCRYPT();
2263   time_t t = time(NULL);
2264
2265   if (lp_security()>=SEC_USER) secword |= 1;
2266   if (doencrypt) secword |= 2;
2267
2268   set_message(outbuf,13,doencrypt?8:0,True);
2269   SSVAL(outbuf,smb_vwv1,secword); 
2270 #ifdef SMB_PASSWD
2271   /* Create a token value and add it to the outgoing packet. */
2272   if (doencrypt) 
2273     generate_next_challenge(smb_buf(outbuf));
2274 #endif
2275
2276   Protocol = PROTOCOL_LANMAN1;
2277
2278   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2279     DEBUG(3,("using password server validation\n"));
2280 #ifdef SMB_PASSWD
2281   if (doencrypt) set_challenge(smb_buf(outbuf));    
2282 #endif
2283   }
2284
2285   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2286   SSVAL(outbuf,smb_vwv2,maxxmit);
2287   SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2288   SSVAL(outbuf,smb_vwv4,1);
2289   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2290                                  readbraw writebraw (possibly) */
2291   SIVAL(outbuf,smb_vwv6,getpid());
2292   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2293
2294   put_dos_date(outbuf,smb_vwv8,t);
2295
2296   return (smb_len(outbuf)+4);
2297 }
2298
2299
2300 /****************************************************************************
2301 reply for the lanman 2.0 protocol
2302 ****************************************************************************/
2303 int reply_lanman2(char *outbuf)
2304 {
2305   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2306   int secword=0;
2307   BOOL doencrypt = SMBENCRYPT();
2308   time_t t = time(NULL);
2309
2310   if (lp_security()>=SEC_USER) secword |= 1;
2311   if (doencrypt) secword |= 2;
2312
2313   set_message(outbuf,13,doencrypt?8:0,True);
2314   SSVAL(outbuf,smb_vwv1,secword); 
2315 #ifdef SMB_PASSWD
2316   /* Create a token value and add it to the outgoing packet. */
2317   if (doencrypt) 
2318     generate_next_challenge(smb_buf(outbuf));
2319 #endif
2320
2321   SIVAL(outbuf,smb_vwv6,getpid());
2322
2323   Protocol = PROTOCOL_LANMAN2;
2324
2325   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2326     DEBUG(3,("using password server validation\n"));
2327 #ifdef SMB_PASSWD
2328     if (doencrypt) set_challenge(smb_buf(outbuf));    
2329 #endif
2330   }
2331
2332   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2333   SSVAL(outbuf,smb_vwv2,maxxmit);
2334   SSVAL(outbuf,smb_vwv3,lp_maxmux()); 
2335   SSVAL(outbuf,smb_vwv4,1);
2336   SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2337   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2338   put_dos_date(outbuf,smb_vwv8,t);
2339
2340   return (smb_len(outbuf)+4);
2341 }
2342
2343 /****************************************************************************
2344 reply for the nt protocol
2345 ****************************************************************************/
2346 int reply_nt1(char *outbuf)
2347 {
2348   int capabilities=0x300; /* has dual names + lock_and_read */
2349   int secword=0;
2350   BOOL doencrypt = SMBENCRYPT();
2351   time_t t = time(NULL);
2352
2353   if (lp_security()>=SEC_USER) secword |= 1;
2354   if (doencrypt) secword |= 2;
2355
2356   set_message(outbuf,17,doencrypt?8:0,True);
2357   CVAL(outbuf,smb_vwv1) = secword;
2358 #ifdef SMB_PASSWD
2359   /* Create a token value and add it to the outgoing packet. */
2360   if (doencrypt) {
2361     generate_next_challenge(smb_buf(outbuf));
2362     /* Tell the nt machine how long the challenge is. */
2363     SSVALS(outbuf,smb_vwv16+1,8);
2364   }
2365 #endif
2366
2367   SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2368
2369   Protocol = PROTOCOL_NT1;
2370
2371   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2372     DEBUG(3,("using password server validation\n"));
2373 #ifdef SMB_PASSWD
2374     if (doencrypt) set_challenge(smb_buf(outbuf));    
2375 #endif
2376   }
2377
2378   if (lp_readraw() && lp_writeraw())
2379     capabilities |= 1;
2380
2381   SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2382   SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2383   SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */
2384   SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */
2385   SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2386   put_long_date(outbuf+smb_vwv11+1,t);
2387   SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
2388
2389   return (smb_len(outbuf)+4);
2390 }
2391
2392
2393 /* these are the protocol lists used for auto architecture detection:
2394
2395 WinNT 3.51:
2396 protocol [PC NETWORK PROGRAM 1.0]
2397 protocol [XENIX CORE]
2398 protocol [MICROSOFT NETWORKS 1.03]
2399 protocol [LANMAN1.0]
2400 protocol [Windows for Workgroups 3.1a]
2401 protocol [LM1.2X002]
2402 protocol [LANMAN2.1]
2403 protocol [NT LM 0.12]
2404
2405 Win95:
2406 protocol [PC NETWORK PROGRAM 1.0]
2407 protocol [XENIX CORE]
2408 protocol [MICROSOFT NETWORKS 1.03]
2409 protocol [LANMAN1.0]
2410 protocol [Windows for Workgroups 3.1a]
2411 protocol [LM1.2X002]
2412 protocol [LANMAN2.1]
2413 protocol [NT LM 0.12]
2414
2415 OS/2:
2416 protocol [PC NETWORK PROGRAM 1.0]
2417 protocol [XENIX CORE]
2418 protocol [LANMAN1.0]
2419 protocol [LM1.2X002]
2420 protocol [LANMAN2.1]
2421 */
2422
2423 /*
2424   * Modified to recognize the architecture of the remote machine better.
2425   *
2426   * This appears to be the matrix of which protocol is used by which
2427   * MS product.
2428        Protocol                       WfWg    Win95   WinNT  OS/2
2429        PC NETWORK PROGRAM 1.0          1       1       1      1
2430        XENIX CORE                                      2      2
2431        MICROSOFT NETWORKS 3.0          2       2       
2432        DOS LM1.2X002                   3       3       
2433        MICROSOFT NETWORKS 1.03                         3
2434        DOS LANMAN2.1                   4       4       
2435        LANMAN1.0                                       4      3
2436        Windows for Workgroups 3.1a     5       5       5
2437        LM1.2X002                                       6      4
2438        LANMAN2.1                                       7      5
2439        NT LM 0.12                              6       8
2440   *
2441   *  tim@fsg.com 09/29/95
2442   */
2443   
2444 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
2445 #define ARCH_WIN95    0x2
2446 #define ARCH_OS2      0xC      /* Again OS/2 is like NT */
2447 #define ARCH_WINNT    0x8
2448 #define ARCH_SAMBA    0x10
2449  
2450 #define ARCH_ALL      0x1F
2451  
2452 /* List of supported protocols, most desired first */
2453 struct {
2454   char *proto_name;
2455   char *short_name;
2456   int (*proto_reply_fn)(char *);
2457   int protocol_level;
2458 } supported_protocols[] = {
2459   {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
2460   {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
2461   {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
2462   {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
2463   {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
2464   {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
2465   {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
2466   {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
2467   {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
2468   {NULL,NULL},
2469 };
2470
2471
2472 /****************************************************************************
2473   reply to a negprot
2474 ****************************************************************************/
2475 static int reply_negprot(char *inbuf,char *outbuf)
2476 {
2477   extern fstring remote_arch;
2478   int outsize = set_message(outbuf,1,0,True);
2479   int Index=0;
2480   int choice= -1;
2481   int protocol;
2482   char *p;
2483   int bcc = SVAL(smb_buf(inbuf),-2);
2484   int arch = ARCH_ALL;
2485
2486   p = smb_buf(inbuf)+1;
2487   while (p < (smb_buf(inbuf) + bcc))
2488     { 
2489       Index++;
2490       DEBUG(3,("Requested protocol [%s]\n",p));
2491       if (strcsequal(p,"Windows for Workgroups 3.1a"))
2492         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
2493       else if (strcsequal(p,"DOS LM1.2X002"))
2494         arch &= ( ARCH_WFWG | ARCH_WIN95 );
2495       else if (strcsequal(p,"DOS LANMAN2.1"))
2496         arch &= ( ARCH_WFWG | ARCH_WIN95 );
2497       else if (strcsequal(p,"NT LM 0.12"))
2498         arch &= ( ARCH_WIN95 | ARCH_WINNT );
2499       else if (strcsequal(p,"LANMAN2.1"))
2500         arch &= ( ARCH_WINNT | ARCH_OS2 );
2501       else if (strcsequal(p,"LM1.2X002"))
2502         arch &= ( ARCH_WINNT | ARCH_OS2 );
2503       else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
2504         arch &= ARCH_WINNT;
2505       else if (strcsequal(p,"XENIX CORE"))
2506         arch &= ( ARCH_WINNT | ARCH_OS2 );
2507       else if (strcsequal(p,"Samba")) {
2508         arch = ARCH_SAMBA;
2509         break;
2510       }
2511  
2512       p += strlen(p) + 2;
2513     }
2514     
2515   switch ( arch ) {
2516   case ARCH_SAMBA:
2517     strcpy(remote_arch,"Samba");
2518     break;
2519   case ARCH_WFWG:
2520     strcpy(remote_arch,"WfWg");
2521     break;
2522   case ARCH_WIN95:
2523     strcpy(remote_arch,"Win95");
2524     break;
2525   case ARCH_WINNT:
2526     strcpy(remote_arch,"WinNT");
2527     break;
2528   case ARCH_OS2:
2529     strcpy(remote_arch,"OS2");
2530     break;
2531   default:
2532     strcpy(remote_arch,"UNKNOWN");
2533     break;
2534   }
2535  
2536   /* possibly reload - change of architecture */
2537   reload_services(True);      
2538     
2539   /* a special case to stop password server loops */
2540   if (Index == 1 && strequal(remote_machine,myhostname) && 
2541       lp_security()==SEC_SERVER)
2542     exit_server("Password server loop!");
2543   
2544   /* Check for protocols, most desirable first */
2545   for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
2546     {
2547       p = smb_buf(inbuf)+1;
2548       Index = 0;
2549       if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
2550         while (p < (smb_buf(inbuf) + bcc))
2551           { 
2552             if (strequal(p,supported_protocols[protocol].proto_name))
2553               choice = Index;
2554             Index++;
2555             p += strlen(p) + 2;
2556           }
2557       if(choice != -1)
2558         break;
2559     }
2560   
2561   SSVAL(outbuf,smb_vwv0,choice);
2562   if(choice != -1) {
2563     extern fstring remote_proto;
2564     strcpy(remote_proto,supported_protocols[protocol].short_name);
2565     reload_services(True);          
2566     outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
2567     DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
2568   }
2569   else {
2570     DEBUG(0,("No protocol supported !\n"));
2571   }
2572   SSVAL(outbuf,smb_vwv0,choice);
2573   
2574   DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
2575
2576   return(outsize);
2577 }
2578
2579
2580 /****************************************************************************
2581 close all open files for a connection
2582 ****************************************************************************/
2583 static void close_open_files(int cnum)
2584 {
2585   int i;
2586   for (i=0;i<MAX_OPEN_FILES;i++)
2587     if( Files[i].cnum == cnum && Files[i].open) {
2588       close_file(i);
2589     }
2590 }
2591
2592
2593
2594 /****************************************************************************
2595 close a cnum
2596 ****************************************************************************/
2597 void close_cnum(int cnum, int uid)
2598 {
2599   extern struct from_host Client_info;
2600
2601   DirCacheFlush(SNUM(cnum));
2602
2603   unbecome_user();
2604
2605   if (!OPEN_CNUM(cnum))
2606     {
2607       DEBUG(0,("Can't close cnum %d\n",cnum));
2608       return;
2609     }
2610
2611   DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
2612                           timestring(),
2613                           Client_info.name,Client_info.addr,
2614                           lp_servicename(SNUM(cnum))));
2615
2616   yield_connection(cnum,
2617                    lp_servicename(SNUM(cnum)),
2618                    lp_max_connections(SNUM(cnum)));
2619
2620   if (lp_status(SNUM(cnum)))
2621     yield_connection(cnum,"STATUS.",MAXSTATUS);
2622
2623   close_open_files(cnum);
2624   dptr_closecnum(cnum);
2625
2626   /* execute any "postexec = " line */
2627   if (*lp_postexec(SNUM(cnum)) && become_user(cnum,uid))
2628     {
2629       pstring cmd;
2630       strcpy(cmd,lp_postexec(SNUM(cnum)));
2631       standard_sub(cnum,cmd);
2632       smbrun(cmd,NULL);
2633       unbecome_user();
2634     }
2635
2636   unbecome_user();
2637   /* execute any "root postexec = " line */
2638   if (*lp_rootpostexec(SNUM(cnum)))
2639     {
2640       pstring cmd;
2641       strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
2642       standard_sub(cnum,cmd);
2643       smbrun(cmd,NULL);
2644     }
2645
2646   Connections[cnum].open = False;
2647   num_connections_open--;
2648   if (Connections[cnum].ngroups && Connections[cnum].groups)
2649     {
2650       if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
2651         free(Connections[cnum].groups);
2652       free(Connections[cnum].igroups);
2653       Connections[cnum].groups = NULL;
2654       Connections[cnum].igroups = NULL;
2655       Connections[cnum].ngroups = 0;
2656     }
2657
2658   string_set(&Connections[cnum].user,"");
2659   string_set(&Connections[cnum].dirpath,"");
2660   string_set(&Connections[cnum].connectpath,"");
2661 }
2662
2663
2664 /****************************************************************************
2665 simple routines to do connection counting
2666 ****************************************************************************/
2667 BOOL yield_connection(int cnum,char *name,int max_connections)
2668 {
2669   struct connect_record crec;
2670   pstring fname;
2671   FILE *f;
2672   int mypid = getpid();
2673   int i;
2674
2675   DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
2676
2677   if (max_connections <= 0)
2678     return(True);
2679
2680   bzero(&crec,sizeof(crec));
2681
2682   strcpy(fname,lp_lockdir());
2683   standard_sub(cnum,fname);
2684   trim_string(fname,"","/");
2685
2686   strcat(fname,"/");
2687   strcat(fname,name);
2688   strcat(fname,".LCK");
2689
2690   f = fopen(fname,"r+");
2691   if (!f)
2692     {
2693       DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
2694       return(False);
2695     }
2696
2697   fseek(f,0,SEEK_SET);
2698
2699   /* find a free spot */
2700   for (i=0;i<max_connections;i++)
2701     {
2702       if (fread(&crec,sizeof(crec),1,f) != 1)
2703         {
2704           DEBUG(2,("Entry not found in lock file %s\n",fname));
2705           fclose(f);
2706           return(False);
2707         }
2708       if (crec.pid == mypid && crec.cnum == cnum)
2709         break;
2710     }
2711
2712   if (crec.pid != mypid || crec.cnum != cnum)
2713     {
2714       fclose(f);
2715       DEBUG(2,("Entry not found in lock file %s\n",fname));
2716       return(False);
2717     }
2718
2719   bzero((void *)&crec,sizeof(crec));
2720   
2721   /* remove our mark */
2722   if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
2723       fwrite(&crec,sizeof(crec),1,f) != 1)
2724     {
2725       DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
2726       fclose(f);
2727       return(False);
2728     }
2729
2730   DEBUG(3,("Yield successful\n"));
2731
2732   fclose(f);
2733   return(True);
2734 }
2735
2736
2737 /****************************************************************************
2738 simple routines to do connection counting
2739 ****************************************************************************/
2740 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
2741 {
2742   struct connect_record crec;
2743   pstring fname;
2744   FILE *f;
2745   int snum = SNUM(cnum);
2746   int i,foundi= -1;
2747   int total_recs;
2748
2749   if (max_connections <= 0)
2750     return(True);
2751
2752   DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
2753
2754   strcpy(fname,lp_lockdir());
2755   standard_sub(cnum,fname);
2756   trim_string(fname,"","/");
2757
2758   if (!directory_exist(fname,NULL))
2759     mkdir(fname,0755);
2760
2761   strcat(fname,"/");
2762   strcat(fname,name);
2763   strcat(fname,".LCK");
2764
2765   if (!file_exist(fname,NULL))
2766     {
2767       f = fopen(fname,"w");
2768       if (f) fclose(f);
2769     }
2770
2771   total_recs = file_size(fname) / sizeof(crec);
2772
2773   f = fopen(fname,"r+");
2774
2775   if (!f)
2776     {
2777       DEBUG(1,("couldn't open lock file %s\n",fname));
2778       return(False);
2779     }
2780
2781   /* find a free spot */
2782   for (i=0;i<max_connections;i++)
2783     {
2784
2785       if (i>=total_recs || 
2786           fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
2787           fread(&crec,sizeof(crec),1,f) != 1)
2788         {
2789           if (foundi < 0) foundi = i;
2790           break;
2791         }
2792
2793       if (Clear && crec.pid && !process_exists(crec.pid))
2794         {
2795           fseek(f,i*sizeof(crec),SEEK_SET);
2796           bzero((void *)&crec,sizeof(crec));
2797           fwrite(&crec,sizeof(crec),1,f);
2798           if (foundi < 0) foundi = i;
2799           continue;
2800         }
2801       if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
2802         {
2803           foundi=i;
2804           if (!Clear) break;
2805         }
2806     }  
2807
2808   if (foundi < 0)
2809     {
2810       DEBUG(3,("no free locks in %s\n",fname));
2811       fclose(f);
2812       return(False);
2813     }      
2814
2815   /* fill in the crec */
2816   bzero((void *)&crec,sizeof(crec));
2817   crec.magic = 0x280267;
2818   crec.pid = getpid();
2819   crec.cnum = cnum;
2820   crec.uid = Connections[cnum].uid;
2821   crec.gid = Connections[cnum].gid;
2822   StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
2823   crec.start = time(NULL);
2824
2825   {
2826     extern struct from_host Client_info;
2827     StrnCpy(crec.machine,Client_info.name,sizeof(crec.machine)-1);
2828     StrnCpy(crec.addr,Client_info.addr,sizeof(crec.addr)-1);
2829   }
2830   
2831   /* make our mark */
2832   if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
2833       fwrite(&crec,sizeof(crec),1,f) != 1)
2834     {
2835       fclose(f);
2836       return(False);
2837     }
2838
2839   fclose(f);
2840   return(True);
2841 }
2842
2843 #if DUMP_CORE
2844 /*******************************************************************
2845 prepare to dump a core file - carefully!
2846 ********************************************************************/
2847 static BOOL dump_core(void)
2848 {
2849   char *p;
2850   pstring dname;
2851   strcpy(dname,debugf);
2852   if ((p=strrchr(dname,'/'))) *p=0;
2853   strcat(dname,"/corefiles");
2854   mkdir(dname,0700);
2855   sys_chown(dname,getuid(),getgid());
2856   chmod(dname,0700);
2857   if (chdir(dname)) return(False);
2858   umask(~(0700));
2859
2860 #ifndef NO_GETRLIMIT
2861 #ifdef RLIMIT_CORE
2862   {
2863     struct rlimit rlp;
2864     getrlimit(RLIMIT_CORE, &rlp);
2865     rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
2866     setrlimit(RLIMIT_CORE, &rlp);
2867     getrlimit(RLIMIT_CORE, &rlp);
2868     DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
2869   }
2870 #endif
2871 #endif
2872
2873
2874   DEBUG(0,("Dumping core in %s\n",dname));
2875   return(True);
2876 }
2877 #endif
2878
2879 /****************************************************************************
2880 exit the server
2881 ****************************************************************************/
2882 void exit_server(char *reason)
2883 {
2884   static int firsttime=1;
2885   int i;
2886
2887   if (!firsttime) exit(0);
2888   firsttime = 0;
2889
2890   unbecome_user();
2891   DEBUG(2,("Closing connections\n"));
2892   for (i=0;i<MAX_CONNECTIONS;i++)
2893     if (Connections[i].open)
2894       close_cnum(i,-1);
2895 #ifdef DFS_AUTH
2896   if (dcelogin_atmost_once)
2897     dfs_unlogin();
2898 #endif
2899   if (!reason) {   
2900     int oldlevel = DEBUGLEVEL;
2901     DEBUGLEVEL = 10;
2902     DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
2903     if (last_inbuf)
2904       show_msg(last_inbuf);
2905     DEBUGLEVEL = oldlevel;
2906     DEBUG(0,("===============================================================\n"));
2907 #if DUMP_CORE
2908     if (dump_core()) return;
2909 #endif
2910   }    
2911   DEBUG(3,("%s Server exit  (%s)\n",timestring(),reason?reason:""));
2912   exit(0);
2913 }
2914
2915 /****************************************************************************
2916 do some standard substitutions in a string
2917 ****************************************************************************/
2918 void standard_sub(int cnum,char *s)
2919 {
2920   if (!strchr(s,'%')) return;
2921
2922   if (VALID_CNUM(cnum))
2923     {
2924       string_sub(s,"%S",lp_servicename(Connections[cnum].service));
2925       string_sub(s,"%P",Connections[cnum].connectpath);
2926       string_sub(s,"%u",Connections[cnum].user);
2927       if (strstr(s,"%H")) {
2928         char *home = get_home_dir(Connections[cnum].user);
2929         if (home) string_sub(s,"%H",home);
2930       }
2931       string_sub(s,"%g",gidtoname(Connections[cnum].gid));
2932     }
2933   standard_sub_basic(s);
2934 }
2935
2936 /*
2937 These flags determine some of the permissions required to do an operation 
2938
2939 Note that I don't set NEED_WRITE on some write operations because they
2940 are used by some brain-dead clients when printing, and I don't want to
2941 force write permissions on print services.
2942 */
2943 #define AS_USER (1<<0)
2944 #define NEED_WRITE (1<<1)
2945 #define TIME_INIT (1<<2)
2946 #define CAN_IPC (1<<3)
2947 #define AS_GUEST (1<<5)
2948
2949
2950 /* 
2951    define a list of possible SMB messages and their corresponding
2952    functions. Any message that has a NULL function is unimplemented -
2953    please feel free to contribute implementations!
2954 */
2955 struct smb_message_struct
2956 {
2957   int code;
2958   char *name;
2959   int (*fn)();
2960   int flags;
2961 #if PROFILING
2962   unsigned long time;
2963 #endif
2964 }
2965  smb_messages[] = {
2966
2967     /* CORE PROTOCOL */
2968
2969    {SMBnegprot,"SMBnegprot",reply_negprot,0},
2970    {SMBtcon,"SMBtcon",reply_tcon,0},
2971    {SMBtdis,"SMBtdis",reply_tdis,0},
2972    {SMBexit,"SMBexit",reply_exit,0},
2973    {SMBioctl,"SMBioctl",reply_ioctl,0},
2974    {SMBecho,"SMBecho",reply_echo,0},
2975    {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
2976    {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
2977    {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, 
2978    {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
2979    {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
2980    {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
2981    {SMBsearch,"SMBsearch",reply_search,AS_USER},
2982    {SMBopen,"SMBopen",reply_open,AS_USER},
2983
2984    /* note that SMBmknew and SMBcreate are deliberately overloaded */   
2985    {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
2986    {SMBmknew,"SMBmknew",reply_mknew,AS_USER}, 
2987
2988    {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
2989    {SMBread,"SMBread",reply_read,AS_USER},
2990    {SMBwrite,"SMBwrite",reply_write,AS_USER},
2991    {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
2992    {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
2993    {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
2994    {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
2995    {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
2996
2997    /* this is a Pathworks specific call, allowing the 
2998       changing of the root path */
2999    {pSETDIR,"pSETDIR",reply_setdir,AS_USER}, 
3000
3001    {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3002    {SMBflush,"SMBflush",reply_flush,AS_USER},
3003    {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3004    {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3005    {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3006    {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST},
3007    {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3008    {SMBlock,"SMBlock",reply_lock,AS_USER},
3009    {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3010    
3011    /* CORE+ PROTOCOL FOLLOWS */
3012    
3013    {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3014    {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3015    {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3016    {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3017    {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3018    
3019    /* LANMAN1.0 PROTOCOL FOLLOWS */
3020    
3021    {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3022    {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3023    {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3024    {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3025    {SMBwritec,"SMBwritec",NULL,AS_USER},
3026    {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3027    {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3028    {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3029    {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3030    {SMBioctls,"SMBioctls",NULL,AS_USER},
3031    {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3032    {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3033    
3034    {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC},
3035    {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3036    {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3037    {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3038    
3039    {SMBffirst,"SMBffirst",reply_search,AS_USER},
3040    {SMBfunique,"SMBfunique",reply_search,AS_USER},
3041    {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3042
3043    /* LANMAN2.0 PROTOCOL FOLLOWS */
3044    {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3045    {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3046    {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3047    {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3048
3049    /* messaging routines */
3050    {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3051    {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3052    {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3053    {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3054
3055    /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3056    
3057    {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3058    {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3059    {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3060    {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3061  };
3062
3063 /****************************************************************************
3064 return a string containing the function name of a SMB command
3065 ****************************************************************************/
3066 char *smb_fn_name(int type)
3067 {
3068   static char *unknown_name = "SMBunknown";
3069   static int num_smb_messages = 
3070     sizeof(smb_messages) / sizeof(struct smb_message_struct);
3071   int match;
3072
3073   for (match=0;match<num_smb_messages;match++)
3074     if (smb_messages[match].code == type)
3075       break;
3076
3077   if (match == num_smb_messages)
3078     return(unknown_name);
3079
3080   return(smb_messages[match].name);
3081 }
3082
3083
3084 /****************************************************************************
3085 do a switch on the message type, and return the response size
3086 ****************************************************************************/
3087 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3088 {
3089   static int pid= -1;
3090   int outsize = 0;
3091   static int num_smb_messages = 
3092     sizeof(smb_messages) / sizeof(struct smb_message_struct);
3093   int match;
3094
3095 #if PROFILING
3096   struct timeval msg_start_time;
3097   struct timeval msg_end_time;
3098   static unsigned long total_time = 0;
3099
3100   GetTimeOfDay(&msg_start_time);
3101 #endif
3102
3103   if (pid == -1)
3104     pid = getpid();
3105
3106   errno = 0;
3107   last_message = type;
3108
3109   /* make sure this is an SMB packet */
3110   if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3111     {
3112       DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3113       return(-1);
3114     }
3115
3116   for (match=0;match<num_smb_messages;match++)
3117     if (smb_messages[match].code == type)
3118       break;
3119
3120   if (match == num_smb_messages)
3121     {
3122       DEBUG(0,("Unknown message type %d!\n",type));
3123       outsize = reply_unknown(inbuf,outbuf);
3124     }
3125   else
3126     {
3127       DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3128       if (smb_messages[match].fn)
3129         {
3130           int cnum = SVAL(inbuf,smb_tid);
3131           int flags = smb_messages[match].flags;
3132           int uid = SVAL(inbuf,smb_uid);
3133
3134           /* does this protocol need to be run as root? */
3135           if (!(flags & AS_USER))
3136             unbecome_user();
3137
3138           /* does this protocol need to be run as the connected user? */
3139           if ((flags & AS_USER) && !become_user(cnum,uid)) {
3140             if (flags & AS_GUEST) 
3141               flags &= ~AS_USER;
3142             else
3143               return(ERROR(ERRSRV,ERRinvnid));
3144           }
3145           /* this code is to work around a bug is MS client 3 without
3146              introducing a security hole - it needs to be able to do
3147              print queue checks as guest if it isn't logged in properly */
3148           if (flags & AS_USER)
3149             flags &= ~AS_GUEST;
3150
3151           /* does it need write permission? */
3152           if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3153             return(ERROR(ERRSRV,ERRaccess));
3154
3155           /* ipc services are limited */
3156           if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3157             return(ERROR(ERRSRV,ERRaccess));        
3158
3159           /* load service specific parameters */
3160           if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3161             return(ERROR(ERRSRV,ERRaccess));
3162
3163           /* does this protocol need to be run as guest? */
3164           if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3165             return(ERROR(ERRSRV,ERRaccess));
3166
3167           last_inbuf = inbuf;
3168
3169           outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3170         }
3171       else
3172         {
3173           outsize = reply_unknown(inbuf,outbuf);
3174         }
3175     }
3176
3177 #if PROFILING
3178   GetTimeOfDay(&msg_end_time);
3179   if (!(smb_messages[match].flags & TIME_INIT))
3180     {
3181       smb_messages[match].time = 0;
3182       smb_messages[match].flags |= TIME_INIT;
3183     }
3184   {
3185     unsigned long this_time =     
3186       (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3187         (msg_end_time.tv_usec - msg_start_time.tv_usec);
3188     smb_messages[match].time += this_time;
3189     total_time += this_time;
3190   }
3191   DEBUG(2,("TIME %s  %d usecs   %g pct\n",
3192            smb_fn_name(type),smb_messages[match].time,
3193         (100.0*smb_messages[match].time) / total_time));
3194 #endif
3195
3196   return(outsize);
3197 }
3198
3199
3200 /****************************************************************************
3201   construct a chained reply and add it to the already made reply
3202   **************************************************************************/
3203 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
3204 {
3205   static char *orig_inbuf;
3206   static char *orig_outbuf;
3207   int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
3208   unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
3209   char *inbuf2, *outbuf2;
3210   int outsize2;
3211   char inbuf_saved[smb_wct];
3212   char outbuf_saved[smb_wct];
3213   extern int chain_size;
3214   int wct = CVAL(outbuf,smb_wct);
3215   int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
3216
3217   /* maybe its not chained */
3218   if (smb_com2 == 0xFF) {
3219     CVAL(outbuf,smb_vwv0) = 0xFF;
3220     return outsize;
3221   }
3222
3223   if (chain_size == 0) {
3224     /* this is the first part of the chain */
3225     orig_inbuf = inbuf;
3226     orig_outbuf = outbuf;
3227   }
3228
3229   /* we need to tell the client where the next part of the reply will be */
3230   SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
3231   CVAL(outbuf,smb_vwv0) = smb_com2;
3232
3233   /* remember how much the caller added to the chain, only counting stuff
3234      after the parameter words */
3235   chain_size += outsize - smb_wct;
3236
3237   /* work out pointers into the original packets. The
3238      headers on these need to be filled in */
3239   inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
3240   outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
3241
3242   /* remember the original command type */
3243   smb_com1 = CVAL(orig_inbuf,smb_com);
3244
3245   /* save the data which will be overwritten by the new headers */
3246   memcpy(inbuf_saved,inbuf2,smb_wct);
3247   memcpy(outbuf_saved,outbuf2,smb_wct);
3248
3249   /* give the new packet the same header as the last part of the SMB */
3250   memmove(inbuf2,inbuf,smb_wct);
3251
3252   /* create the in buffer */
3253   CVAL(inbuf2,smb_com) = smb_com2;
3254
3255   /* create the out buffer */
3256   bzero(outbuf2,smb_size);
3257   set_message(outbuf2,0,0,True);
3258   CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com);
3259   
3260   memcpy(outbuf2+4,inbuf2+4,4);
3261   CVAL(outbuf2,smb_rcls) = SUCCESS;
3262   CVAL(outbuf2,smb_reh) = 0;
3263   CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set 
3264                                                                   means a reply */
3265   SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */
3266   SSVAL(outbuf2,smb_err,SUCCESS);
3267   SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid));
3268   SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid));
3269   SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid));
3270   SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid));
3271
3272   DEBUG(3,("Chained message\n"));
3273   show_msg(inbuf2);
3274
3275   /* process the request */
3276   outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
3277                             bufsize-chain_size);
3278
3279   /* copy the new reply and request headers over the old ones, but
3280      preserve the smb_com field */
3281   memmove(orig_outbuf,outbuf2,smb_wct);
3282   CVAL(orig_outbuf,smb_com) = smb_com1;
3283
3284   /* restore the saved data, being careful not to overwrite any
3285    data from the reply header */
3286   memcpy(inbuf2,inbuf_saved,smb_wct);
3287   {
3288     int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
3289     if (ofs < 0) ofs = 0;
3290     memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
3291   }
3292
3293   return outsize2;
3294 }
3295
3296
3297
3298 /****************************************************************************
3299   construct a reply to the incoming packet
3300 ****************************************************************************/
3301 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3302 {
3303   int type = CVAL(inbuf,smb_com);
3304   int outsize = 0;
3305   int msg_type = CVAL(inbuf,0);
3306   extern int chain_size;
3307
3308   smb_last_time = time(NULL);
3309
3310   chain_size = 0;
3311   chain_fnum = -1;
3312
3313   bzero(outbuf,smb_size);
3314
3315   if (msg_type != 0)
3316     return(reply_special(inbuf,outbuf));  
3317
3318   CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3319   set_message(outbuf,0,0,True);
3320   
3321   memcpy(outbuf+4,inbuf+4,4);
3322   CVAL(outbuf,smb_rcls) = SUCCESS;
3323   CVAL(outbuf,smb_reh) = 0;
3324   CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set 
3325                                                              means a reply */
3326   SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3327   SSVAL(outbuf,smb_err,SUCCESS);
3328   SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3329   SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3330   SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3331   SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3332
3333   outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3334
3335   outsize += chain_size;
3336
3337   if(outsize > 4)
3338     smb_setlen(outbuf,outsize - 4);
3339   return(outsize);
3340 }
3341
3342
3343 /****************************************************************************
3344   process commands from the client
3345 ****************************************************************************/
3346 static void process(void)
3347 {
3348   static int trans_num = 0;
3349   int nread;
3350   extern struct from_host Client_info;
3351   extern int Client;
3352
3353   fromhost(Client,&Client_info);
3354   
3355   InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3356   OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3357   if ((InBuffer == NULL) || (OutBuffer == NULL)) 
3358     return;
3359
3360   InBuffer += SMB_ALIGNMENT;
3361   OutBuffer += SMB_ALIGNMENT;
3362
3363 #if PRIME_NMBD
3364   DEBUG(3,("priming nmbd\n"));
3365   {
3366     struct in_addr ip;
3367     ip = *interpret_addr2("localhost");
3368     if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3369     *OutBuffer = 0;
3370     send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
3371   }
3372 #endif    
3373
3374   while (True)
3375     {
3376       int32 len;      
3377       int msg_type;
3378       int msg_flags;
3379       int type;
3380       int deadtime = lp_deadtime()*60;
3381       int counter;
3382       int last_keepalive=0;
3383
3384       if (deadtime <= 0)
3385         deadtime = DEFAULT_SMBD_TIMEOUT;
3386
3387       if (lp_readprediction())
3388         do_read_prediction();
3389
3390       {
3391         extern pstring share_del_pending;
3392         if (*share_del_pending) {
3393           unbecome_user();
3394           if (!unlink(share_del_pending))
3395             DEBUG(3,("Share file deleted %s\n",share_del_pending));
3396           else
3397             DEBUG(2,("Share del failed of %s\n",share_del_pending));
3398           share_del_pending[0] = 0;
3399         }
3400       }
3401
3402       if (share_mode_pending) {
3403         unbecome_user();
3404         check_share_modes();
3405         share_mode_pending=False;
3406       }
3407
3408       errno = 0;      
3409
3410       for (counter=SMBD_SELECT_LOOP; 
3411            !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000); 
3412            counter += SMBD_SELECT_LOOP)
3413         {
3414           int i;
3415           time_t t;
3416           BOOL allidle = True;
3417           extern int keepalive;
3418
3419           if (smb_read_error == READ_EOF) {
3420             DEBUG(3,("end of file from client\n"));
3421             return;
3422           }
3423
3424           if (smb_read_error == READ_ERROR) {
3425             DEBUG(3,("receive_smb error (%s) exiting\n",
3426                      strerror(errno)));
3427             return;
3428           }
3429
3430           t = time(NULL);
3431
3432           /* become root again if waiting */
3433           unbecome_user();
3434
3435           /* check for smb.conf reload */
3436           if (!(counter%SMBD_RELOAD_CHECK))
3437             reload_services(True);
3438
3439           /* check the share modes every 10 secs */
3440           if (!(counter%SHARE_MODES_CHECK))
3441             check_share_modes();
3442
3443           /* clean the share modes every 5 minutes */
3444           if (!(counter%SHARE_MODES_CLEAN))
3445             clean_share_modes();
3446
3447           /* automatic timeout if all connections are closed */      
3448           if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3449             DEBUG(2,("%s Closing idle connection\n",timestring()));
3450             return;
3451           }
3452
3453           if (keepalive && (counter-last_keepalive)>keepalive) {
3454             extern int password_client;
3455             if (!send_keepalive(Client)) {
3456               DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3457               return;
3458             }       
3459             /* also send a keepalive to the password server if its still
3460                connected */
3461             if (password_client != -1)
3462               send_keepalive(password_client);
3463             last_keepalive = counter;
3464           }
3465
3466           /* check for connection timeouts */
3467           for (i=0;i<MAX_CONNECTIONS;i++)
3468             if (Connections[i].open)
3469               {
3470                 /* close dirptrs on connections that are idle */
3471                 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
3472                   dptr_idlecnum(i);
3473
3474                 if (Connections[i].num_files_open > 0 ||
3475                     (t-Connections[i].lastused)<deadtime)
3476                   allidle = False;
3477               }
3478
3479           if (allidle && num_connections_open>0) {
3480             DEBUG(2,("%s Closing idle connection 2\n",timestring()));
3481             return;
3482           }
3483         }
3484
3485       msg_type = CVAL(InBuffer,0);
3486       msg_flags = CVAL(InBuffer,1);
3487       type = CVAL(InBuffer,smb_com);
3488
3489       len = smb_len(InBuffer);
3490
3491       DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
3492
3493       nread = len + 4;
3494       
3495       DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
3496
3497 #ifdef WITH_VTP
3498       if(trans_num == 1 && VT_Check(InBuffer)) {
3499         VT_Process();
3500         return;
3501       }
3502 #endif
3503
3504
3505       if (msg_type == 0)
3506         show_msg(InBuffer);
3507
3508       nread = construct_reply(InBuffer,OutBuffer,nread,maxxmit);
3509       
3510       if(nread > 0) {
3511         if (CVAL(OutBuffer,0) == 0)
3512           show_msg(OutBuffer);
3513         
3514         if (nread != smb_len(OutBuffer) + 4) 
3515           {
3516             DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
3517                      nread,
3518                      smb_len(OutBuffer)));
3519           }
3520         else
3521           send_smb(Client,OutBuffer);
3522       }
3523       trans_num++;
3524     }
3525 }
3526
3527
3528 /****************************************************************************
3529   initialise connect, service and file structs
3530 ****************************************************************************/
3531 static void init_structs(void )
3532 {
3533   int i;
3534   get_myname(myhostname,NULL);
3535
3536   for (i=0;i<MAX_CONNECTIONS;i++)
3537     {
3538       Connections[i].open = False;
3539       Connections[i].num_files_open=0;
3540       Connections[i].lastused=0;
3541       Connections[i].used=False;
3542       string_init(&Connections[i].user,"");
3543       string_init(&Connections[i].dirpath,"");
3544       string_init(&Connections[i].connectpath,"");
3545       string_init(&Connections[i].origpath,"");
3546     }
3547
3548   for (i=0;i<MAX_OPEN_FILES;i++)
3549     {
3550       Files[i].open = False;
3551       string_init(&Files[i].name,"");
3552     }
3553
3554   init_dptrs();
3555 }
3556
3557 /****************************************************************************
3558 usage on the program
3559 ****************************************************************************/
3560 static void usage(char *pname)
3561 {
3562   DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
3563
3564   printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
3565   printf("Version %s\n",VERSION);
3566   printf("\t-D                    become a daemon\n");
3567   printf("\t-p port               listen on the specified port\n");
3568   printf("\t-d debuglevel         set the debuglevel\n");
3569   printf("\t-l log basename.      Basename for log/debug files\n");
3570   printf("\t-s services file.     Filename of services file\n");
3571   printf("\t-P                    passive only\n");
3572   printf("\t-a                    overwrite log file, don't append\n");
3573   printf("\n");
3574 }
3575
3576
3577 /****************************************************************************
3578   main program
3579 ****************************************************************************/
3580  int main(int argc,char *argv[])
3581 {
3582   extern BOOL append_log;
3583   /* shall I run as a daemon */
3584   BOOL is_daemon = False;
3585   int port = SMB_PORT;
3586   int opt;
3587   extern char *optarg;
3588
3589 #ifdef NEED_AUTH_PARAMETERS
3590   set_auth_parameters(argc,argv);
3591 #endif
3592
3593 #ifdef SecureWare
3594   setluid(0);
3595 #endif
3596
3597   append_log = True;
3598
3599   TimeInit();
3600
3601   strcpy(debugf,SMBLOGFILE);  
3602
3603   setup_logging(argv[0],False);
3604
3605   charset_initialise();
3606
3607   /* make absolutely sure we run as root - to handle cases whre people
3608      are crazy enough to have it setuid */
3609 #ifdef USE_SETRES
3610   setresuid(0,0,0);
3611 #else
3612   setuid(0);
3613   seteuid(0);
3614   setuid(0);
3615   seteuid(0);
3616 #endif
3617
3618   fault_setup(exit_server);
3619
3620   umask(0777 & ~DEF_CREATE_MASK);
3621
3622   init_uid();
3623
3624   /* this is for people who can't start the program correctly */
3625   while (argc > 1 && (*argv[1] != '-'))
3626     {
3627       argv++;
3628       argc--;
3629     }
3630
3631   while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPa")) != EOF)
3632     switch (opt)
3633       {
3634       case 'O':
3635         strcpy(user_socket_options,optarg);
3636         break;
3637       case 'i':
3638         strcpy(scope,optarg);
3639         break;
3640       case 'P':
3641         {
3642           extern BOOL passive;
3643           passive = True;
3644         }
3645         break;  
3646       case 's':
3647         strcpy(servicesf,optarg);
3648         break;
3649       case 'l':
3650         strcpy(debugf,optarg);
3651         break;
3652       case 'a':
3653         {
3654           extern BOOL append_log;
3655           append_log = !append_log;
3656         }
3657         break;
3658       case 'D':
3659         is_daemon = True;
3660         break;
3661       case 'd':
3662         if (*optarg == 'A')
3663           DEBUGLEVEL = 10000;
3664         else
3665           DEBUGLEVEL = atoi(optarg);
3666         break;
3667       case 'p':
3668         port = atoi(optarg);
3669         break;
3670       case 'h':
3671         usage(argv[0]);
3672         exit(0);
3673         break;
3674       default:
3675         usage(argv[0]);
3676         exit(1);
3677       }
3678
3679   reopen_logs();
3680
3681   DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
3682   DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
3683
3684 #ifndef NO_GETRLIMIT
3685 #ifdef RLIMIT_NOFILE
3686   {
3687     struct rlimit rlp;
3688     getrlimit(RLIMIT_NOFILE, &rlp);
3689     rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
3690     setrlimit(RLIMIT_NOFILE, &rlp);
3691     getrlimit(RLIMIT_NOFILE, &rlp);
3692     DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
3693   }
3694 #endif
3695 #endif
3696
3697   
3698   DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
3699         getuid(),getgid(),geteuid(),getegid()));
3700
3701   if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
3702     {
3703       DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
3704       exit(1);
3705     }
3706
3707   init_structs();
3708
3709   if (!reload_services(False))
3710     return(-1); 
3711
3712 #ifndef NO_SIGNAL_TEST
3713   signal(SIGHUP,SIGNAL_CAST sig_hup);
3714 #endif
3715   
3716   DEBUG(3,("%s loaded services\n",timestring()));
3717
3718   if (!is_daemon && !is_a_socket(0))
3719     {
3720       DEBUG(0,("standard input is not a socket, assuming -D option\n"));
3721       is_daemon = True;
3722     }
3723
3724   if (is_daemon)
3725     {
3726       DEBUG(3,("%s becoming a daemon\n",timestring()));
3727       become_daemon();
3728     }
3729
3730   if (!open_sockets(is_daemon,port))
3731     exit(1);
3732
3733 #if FAST_SHARE_MODES
3734   if (!start_share_mode_mgmt())
3735     exit(1);
3736 #endif
3737
3738   /* possibly reload the services file. */
3739   reload_services(True);
3740
3741   maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE);
3742
3743   if (*lp_rootdir())
3744     {
3745       if (sys_chroot(lp_rootdir()) == 0)
3746         DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
3747     }
3748
3749   read_smbbrowse_conf(myhostname);
3750
3751   process();
3752   close_sockets();
3753
3754 #if FAST_SHARE_MODES
3755   stop_share_mode_mgmt();
3756 #endif
3757
3758   exit_server("normal exit");
3759   return(0);
3760 }
3761
3762