a710aef69bbfecf61e1c0dece17923649e215f68
[kai/samba.git] / source3 / smbd / server.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Main SMB server routines
5    Copyright (C) Andrew Tridgell 1992-1995
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23 #include "trans2.h"
24
25 pstring servicesf = CONFIGFILE;
26 extern pstring debugf;
27 extern pstring sesssetup_user;
28
29 char *InBuffer = NULL;
30 char *OutBuffer = NULL;
31 char *last_inbuf = NULL;
32
33 BOOL share_mode_pending = False;
34
35 /* the last message the was processed */
36 int last_message = -1;
37
38 /* a useful macro to debug the last message processed */
39 #define LAST_MESSAGE() smb_fn_name(last_message)
40
41 extern pstring scope;
42 extern int DEBUGLEVEL;
43 extern int case_default;
44 extern BOOL case_sensitive;
45 extern BOOL case_preserve;
46 extern BOOL use_mangled_map;
47 extern BOOL short_case_preserve;
48 extern BOOL case_mangle;
49 extern time_t smb_last_time;
50
51 extern int smb_read_error;
52
53 extern pstring user_socket_options;
54
55 connection_struct Connections[MAX_CONNECTIONS];
56 files_struct Files[MAX_OPEN_FILES];
57
58 extern int Protocol;
59
60 int maxxmit = BUFFER_SIZE;
61
62 /* a fnum to use when chaining */
63 int chain_fnum = -1;
64
65 /* number of open connections */
66 static int num_connections_open = 0;
67
68 extern fstring remote_machine;
69
70
71 /* these can be set by some functions to override the error codes */
72 int unix_ERR_class=SUCCESS;
73 int unix_ERR_code=0;
74
75
76 extern int extra_time_offset;
77
78 extern pstring myhostname;
79
80 static int find_free_connection(int hash);
81
82 /* for readability... */
83 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
84 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
85 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
86 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
87 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
88
89
90
91 /****************************************************************************
92   change a dos mode to a unix mode
93     base permission for files:
94          everybody gets read bit set
95          dos readonly is represented in unix by removing everyone's write bit
96          dos archive is represented in unix by the user's execute bit
97          dos system is represented in unix by the group's execute bit
98          dos hidden is represented in unix by the other's execute bit
99     base permission for directories:
100          dos directory is represented in unix by unix's dir bit and the exec bit
101 ****************************************************************************/
102 mode_t unix_mode(int cnum,int dosmode)
103 {
104   mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
105
106   if ( !IS_DOS_READONLY(dosmode) )
107     result |= (S_IWUSR | S_IWGRP | S_IWOTH);
108  
109   if (IS_DOS_DIR(dosmode))
110     result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
111  
112   if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
113     result |= S_IXUSR;
114
115   if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
116     result |= S_IXGRP;
117  
118   if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
119     result |= S_IXOTH;  
120  
121   result &= CREATE_MODE(cnum);
122   return(result);
123 }
124
125
126 /****************************************************************************
127   change a unix mode to a dos mode
128 ****************************************************************************/
129 int dos_mode(int cnum,char *path,struct stat *sbuf)
130 {
131   int result = 0;
132   extern struct current_user current_user;
133
134   if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
135     if (!((sbuf->st_mode & S_IWOTH) ||
136           Connections[cnum].admin_user ||
137           ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) ||
138           ((sbuf->st_mode & S_IWGRP) && 
139            in_group(sbuf->st_gid,current_user.gid,
140                     current_user.ngroups,current_user.igroups))))
141       result |= aRONLY;
142   } else {
143     if ((sbuf->st_mode & S_IWUSR) == 0)
144       result |= aRONLY;
145   }
146
147   if ((sbuf->st_mode & S_IXUSR) != 0)
148     result |= aARCH;
149
150   if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
151     result |= aSYSTEM;
152
153   if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
154     result |= aHIDDEN;   
155   
156   if (S_ISDIR(sbuf->st_mode))
157     result = aDIR | (result & aRONLY);
158
159 #if LINKS_READ_ONLY
160   if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
161     result |= aRONLY;
162 #endif
163
164   /* hide files with a name starting with a . */
165   if (lp_hide_dot_files(SNUM(cnum)))
166     {
167       char *p = strrchr(path,'/');
168       if (p)
169         p++;
170       else
171         p = path;
172       
173       if (p[0] == '.' && p[1] != '.' && p[1] != 0)
174         result |= aHIDDEN;
175     }
176
177   return(result);
178 }
179
180
181 /*******************************************************************
182 chmod a file - but preserve some bits
183 ********************************************************************/
184 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
185 {
186   struct stat st1;
187   int mask=0;
188   int tmp;
189   int unixmode;
190
191   if (!st) {
192     st = &st1;
193     if (sys_stat(fname,st)) return(-1);
194   }
195
196   if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
197
198   if (dos_mode(cnum,fname,st) == dosmode) return(0);
199
200   unixmode = unix_mode(cnum,dosmode);
201
202   /* preserve the s bits */
203   mask |= (S_ISUID | S_ISGID);
204
205   /* preserve the t bit */
206 #ifdef S_ISVTX
207   mask |= S_ISVTX;
208 #endif
209
210   /* possibly preserve the x bits */
211   if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
212   if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
213   if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
214
215   unixmode |= (st->st_mode & mask);
216
217   /* if we previously had any r bits set then leave them alone */
218   if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
219     unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
220     unixmode |= tmp;
221   }
222
223   /* if we previously had any w bits set then leave them alone 
224    if the new mode is not rdonly */
225   if (!IS_DOS_READONLY(dosmode) &&
226       (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
227     unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
228     unixmode |= tmp;
229   }
230
231   return(sys_chmod(fname,unixmode));
232 }
233
234
235 /****************************************************************************
236 check if two filenames are equal
237
238 this needs to be careful about whether we are case sensitive
239 ****************************************************************************/
240 static BOOL fname_equal(char *name1, char *name2)
241 {
242   int l1 = strlen(name1);
243   int l2 = strlen(name2);
244
245   /* handle filenames ending in a single dot */
246   if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
247     {
248       BOOL ret;
249       name1[l1-1] = 0;
250       ret = fname_equal(name1,name2);
251       name1[l1-1] = '.';
252       return(ret);
253     }
254
255   if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
256     {
257       BOOL ret;
258       name2[l2-1] = 0;
259       ret = fname_equal(name1,name2);
260       name2[l2-1] = '.';
261       return(ret);
262     }
263
264   /* now normal filename handling */
265   if (case_sensitive)
266     return(strcmp(name1,name2) == 0);
267
268   return(strequal(name1,name2));
269 }
270
271
272 /****************************************************************************
273 mangle the 2nd name and check if it is then equal to the first name
274 ****************************************************************************/
275 static BOOL mangled_equal(char *name1, char *name2)
276 {
277   pstring tmpname;
278
279   if (is_8_3(name2))
280     return(False);
281
282   strcpy(tmpname,name2);
283   mangle_name_83(tmpname);
284
285   return(strequal(name1,tmpname));
286 }
287
288
289 /****************************************************************************
290 scan a directory to find a filename, matching without case sensitivity
291
292 If the name looks like a mangled name then try via the mangling functions
293 ****************************************************************************/
294 static BOOL scan_directory(char *path, char *name,int snum,BOOL docache)
295 {
296   void *cur_dir;
297   char *dname;
298   BOOL mangled;
299   pstring name2;
300
301   mangled = is_mangled(name);
302
303   /* handle null paths */
304   if (*path == 0)
305     path = ".";
306
307   if (docache && (dname = DirCacheCheck(path,name,snum))) {
308     strcpy(name, dname);        
309     return(True);
310   }      
311
312   if (mangled)
313     check_mangled_stack(name);
314
315   /* open the directory */
316   if (!(cur_dir = OpenDir(path))) 
317     {
318       DEBUG(3,("scan dir didn't open dir [%s]\n",path));
319       return(False);
320     }
321
322   /* now scan for matching names */
323   while ((dname = ReadDirName(cur_dir))) 
324     {
325       if (*dname == '.' &&
326           (strequal(dname,".") || strequal(dname,"..")))
327         continue;
328
329       strcpy(name2,dname);
330       if (!name_map_mangle(name2,False,snum)) continue;
331
332       if ((mangled && mangled_equal(name,name2))
333           || fname_equal(name, name2))
334         {
335           /* we've found the file, change it's name and return */
336           if (docache) DirCacheAdd(path,name,dname,snum);
337           strcpy(name, dname);
338           CloseDir(cur_dir);
339           return(True);
340         }
341     }
342
343   CloseDir(cur_dir);
344   return(False);
345 }
346
347 /****************************************************************************
348 This routine is called to convert names from the dos namespace to unix
349 namespace. It needs to handle any case conversions, mangling, format
350 changes etc.
351
352 We assume that we have already done a chdir() to the right "root" directory
353 for this service.
354
355 The function will return False if some part of the name except for the last
356 part cannot be resolved
357 ****************************************************************************/
358 BOOL unix_convert(char *name,int cnum)
359 {
360   struct stat st;
361   char *start, *end;
362   pstring dirpath;
363
364   *dirpath = 0;
365
366   /* convert to basic unix format - removing \ chars and cleaning it up */
367   unix_format(name);
368   unix_clean_name(name);
369
370   if (!case_sensitive && 
371       (!case_preserve || (is_8_3(name) && !short_case_preserve)))
372     strnorm(name);
373
374   /* names must be relative to the root of the service - trim any leading /.
375    also trim trailing /'s */
376   trim_string(name,"/","/");
377
378   /* check if it's a printer file */
379   if (Connections[cnum].printer)
380     {
381       if ((! *name) || strchr(name,'/') || !is_8_3(name))
382         {
383           char *s;
384           fstring name2;
385           sprintf(name2,"%.6s.XXXXXX",remote_machine);
386           /* sanitise the name */
387           for (s=name2 ; *s ; s++)
388             if (!issafe(*s)) *s = '_';
389           strcpy(name,(char *)mktemp(name2));     
390         }      
391       return(True);
392     }
393
394   /* stat the name - if it exists then we are all done! */
395   if (sys_stat(name,&st) == 0)
396     return(True);
397
398   DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
399
400   /* a special case - if we don't have any mangling chars and are case
401      sensitive then searching won't help */
402   if (case_sensitive && !is_mangled(name) && 
403       !lp_strip_dot() && !use_mangled_map)
404     return(False);
405
406   /* now we need to recursively match the name against the real 
407      directory structure */
408
409   start = name;
410   while (strncmp(start,"./",2) == 0)
411     start += 2;
412
413   /* now match each part of the path name separately, trying the names
414      as is first, then trying to scan the directory for matching names */
415   for (;start;start = (end?end+1:(char *)NULL)) 
416     {
417       /* pinpoint the end of this section of the filename */
418       end = strchr(start, '/');
419
420       /* chop the name at this point */
421       if (end) *end = 0;
422
423       /* check if the name exists up to this point */
424       if (sys_stat(name, &st) == 0) 
425         {
426           /* it exists. it must either be a directory or this must be
427              the last part of the path for it to be OK */
428           if (end && !(st.st_mode & S_IFDIR)) 
429             {
430               /* an intermediate part of the name isn't a directory */
431               DEBUG(5,("Not a dir %s\n",start));
432               *end = '/';
433               return(False);
434             }
435         }
436       else 
437         {
438           pstring rest;
439
440           *rest = 0;
441
442           /* remember the rest of the pathname so it can be restored
443              later */
444           if (end) strcpy(rest,end+1);
445
446
447           /* try to find this part of the path in the directory */
448           if (strchr(start,'?') || strchr(start,'*') ||
449               !scan_directory(dirpath, start, SNUM(cnum), end?True:False))
450             {
451               if (end) 
452                 {
453                   /* an intermediate part of the name can't be found */
454                   DEBUG(5,("Intermediate not found %s\n",start));
455                   *end = '/';
456                   return(False);
457                 }
458               
459               /* just the last part of the name doesn't exist */
460               /* we may need to strupper() or strlower() it in case
461                  this conversion is being used for file creation 
462                  purposes */
463               /* if the filename is of mixed case then don't normalise it */
464               if (!case_preserve && 
465                   (!strhasupper(start) || !strhaslower(start)))         
466                 strnorm(start);
467
468               /* check on the mangled stack to see if we can recover the 
469                  base of the filename */
470               if (is_mangled(start))
471                 check_mangled_stack(start);
472
473               DEBUG(5,("New file %s\n",start));
474               return(True); 
475             }
476
477           /* restore the rest of the string */
478           if (end) 
479             {
480               strcpy(start+strlen(start)+1,rest);
481               end = start + strlen(start);
482             }
483         }
484
485       /* add to the dirpath that we have resolved so far */
486       if (*dirpath) strcat(dirpath,"/");
487       strcat(dirpath,start);
488
489       /* restore the / that we wiped out earlier */
490       if (end) *end = '/';
491     }
492   
493   /* the name has been resolved */
494   DEBUG(5,("conversion finished %s\n",name));
495   return(True);
496 }
497
498
499 /****************************************************************************
500 normalise for DOS usage 
501 ****************************************************************************/
502 static void disk_norm(int *bsize,int *dfree,int *dsize)
503 {
504   /* check if the disk is beyond the max disk size */
505   int maxdisksize = lp_maxdisksize();
506   if (maxdisksize) {
507     /* convert to blocks - and don't overflow */
508     maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
509     if (*dsize > maxdisksize) *dsize = maxdisksize;
510     if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop 
511                                                          applications getting 
512                                                          div by 0 errors */
513   }  
514
515   while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512) 
516     {
517       *dfree /= 2;
518       *dsize /= 2;
519       *bsize *= 2;
520       if (*bsize > WORDMAX )
521         {
522           *bsize = WORDMAX;
523           if (*dsize > WORDMAX)
524             *dsize = WORDMAX;
525           if (*dfree >  WORDMAX)
526             *dfree = WORDMAX;
527           break;
528         }
529     }
530 }
531
532 /****************************************************************************
533   return number of 1K blocks available on a path and total number 
534 ****************************************************************************/
535 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
536 {
537   char *df_command = lp_dfree_command();
538 #ifndef NO_STATFS
539 #ifdef USE_STATVFS
540   struct statvfs fs;
541 #else
542 #ifdef ULTRIX
543   struct fs_data fs;
544 #else
545   struct statfs fs;
546 #endif
547 #endif
548 #endif
549
550 #ifdef QUOTAS
551   if (disk_quotas(path, bsize, dfree, dsize))
552     {
553       disk_norm(bsize,dfree,dsize);
554       return(((*bsize)/1024)*(*dfree));
555     }
556 #endif
557
558
559   /* possibly use system() to get the result */
560   if (df_command && *df_command)
561     {
562       int ret;
563       pstring syscmd;
564       pstring outfile;
565           
566       sprintf(outfile,"/tmp/dfree.smb.%d",(int)getpid());
567       sprintf(syscmd,"%s %s",df_command,path);
568       standard_sub_basic(syscmd);
569
570       ret = smbrun(syscmd,outfile,False);
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,False);
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,False);
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,False);
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,False);
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,False);
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       int oldmask = umask(022);
2768       f = fopen(fname,"w");
2769       if (f) fclose(f);
2770       umask(oldmask);
2771     }
2772
2773   total_recs = file_size(fname) / sizeof(crec);
2774
2775   f = fopen(fname,"r+");
2776
2777   if (!f)
2778     {
2779       DEBUG(1,("couldn't open lock file %s\n",fname));
2780       return(False);
2781     }
2782
2783   /* find a free spot */
2784   for (i=0;i<max_connections;i++)
2785     {
2786
2787       if (i>=total_recs || 
2788           fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
2789           fread(&crec,sizeof(crec),1,f) != 1)
2790         {
2791           if (foundi < 0) foundi = i;
2792           break;
2793         }
2794
2795       if (Clear && crec.pid && !process_exists(crec.pid))
2796         {
2797           fseek(f,i*sizeof(crec),SEEK_SET);
2798           bzero((void *)&crec,sizeof(crec));
2799           fwrite(&crec,sizeof(crec),1,f);
2800           if (foundi < 0) foundi = i;
2801           continue;
2802         }
2803       if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
2804         {
2805           foundi=i;
2806           if (!Clear) break;
2807         }
2808     }  
2809
2810   if (foundi < 0)
2811     {
2812       DEBUG(3,("no free locks in %s\n",fname));
2813       fclose(f);
2814       return(False);
2815     }      
2816
2817   /* fill in the crec */
2818   bzero((void *)&crec,sizeof(crec));
2819   crec.magic = 0x280267;
2820   crec.pid = getpid();
2821   crec.cnum = cnum;
2822   crec.uid = Connections[cnum].uid;
2823   crec.gid = Connections[cnum].gid;
2824   StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
2825   crec.start = time(NULL);
2826
2827   {
2828     extern struct from_host Client_info;
2829     StrnCpy(crec.machine,Client_info.name,sizeof(crec.machine)-1);
2830     StrnCpy(crec.addr,Client_info.addr,sizeof(crec.addr)-1);
2831   }
2832   
2833   /* make our mark */
2834   if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
2835       fwrite(&crec,sizeof(crec),1,f) != 1)
2836     {
2837       fclose(f);
2838       return(False);
2839     }
2840
2841   fclose(f);
2842   return(True);
2843 }
2844
2845 #if DUMP_CORE
2846 /*******************************************************************
2847 prepare to dump a core file - carefully!
2848 ********************************************************************/
2849 static BOOL dump_core(void)
2850 {
2851   char *p;
2852   pstring dname;
2853   strcpy(dname,debugf);
2854   if ((p=strrchr(dname,'/'))) *p=0;
2855   strcat(dname,"/corefiles");
2856   mkdir(dname,0700);
2857   sys_chown(dname,getuid(),getgid());
2858   chmod(dname,0700);
2859   if (chdir(dname)) return(False);
2860   umask(~(0700));
2861
2862 #ifndef NO_GETRLIMIT
2863 #ifdef RLIMIT_CORE
2864   {
2865     struct rlimit rlp;
2866     getrlimit(RLIMIT_CORE, &rlp);
2867     rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
2868     setrlimit(RLIMIT_CORE, &rlp);
2869     getrlimit(RLIMIT_CORE, &rlp);
2870     DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
2871   }
2872 #endif
2873 #endif
2874
2875
2876   DEBUG(0,("Dumping core in %s\n",dname));
2877   return(True);
2878 }
2879 #endif
2880
2881 /****************************************************************************
2882 exit the server
2883 ****************************************************************************/
2884 void exit_server(char *reason)
2885 {
2886   static int firsttime=1;
2887   int i;
2888
2889   if (!firsttime) exit(0);
2890   firsttime = 0;
2891
2892   unbecome_user();
2893   DEBUG(2,("Closing connections\n"));
2894   for (i=0;i<MAX_CONNECTIONS;i++)
2895     if (Connections[i].open)
2896       close_cnum(i,-1);
2897 #ifdef DFS_AUTH
2898   if (dcelogin_atmost_once)
2899     dfs_unlogin();
2900 #endif
2901   if (!reason) {   
2902     int oldlevel = DEBUGLEVEL;
2903     DEBUGLEVEL = 10;
2904     DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
2905     if (last_inbuf)
2906       show_msg(last_inbuf);
2907     DEBUGLEVEL = oldlevel;
2908     DEBUG(0,("===============================================================\n"));
2909 #if DUMP_CORE
2910     if (dump_core()) return;
2911 #endif
2912   }    
2913   DEBUG(3,("%s Server exit  (%s)\n",timestring(),reason?reason:""));
2914   exit(0);
2915 }
2916
2917 /****************************************************************************
2918 do some standard substitutions in a string
2919 ****************************************************************************/
2920 void standard_sub(int cnum,char *s)
2921 {
2922   if (!strchr(s,'%')) return;
2923
2924   if (VALID_CNUM(cnum))
2925     {
2926       string_sub(s,"%S",lp_servicename(Connections[cnum].service));
2927       string_sub(s,"%P",Connections[cnum].connectpath);
2928       string_sub(s,"%u",Connections[cnum].user);
2929       if (strstr(s,"%H")) {
2930         char *home = get_home_dir(Connections[cnum].user);
2931         if (home) string_sub(s,"%H",home);
2932       }
2933       string_sub(s,"%g",gidtoname(Connections[cnum].gid));
2934     }
2935   standard_sub_basic(s);
2936 }
2937
2938 /*
2939 These flags determine some of the permissions required to do an operation 
2940
2941 Note that I don't set NEED_WRITE on some write operations because they
2942 are used by some brain-dead clients when printing, and I don't want to
2943 force write permissions on print services.
2944 */
2945 #define AS_USER (1<<0)
2946 #define NEED_WRITE (1<<1)
2947 #define TIME_INIT (1<<2)
2948 #define CAN_IPC (1<<3)
2949 #define AS_GUEST (1<<5)
2950
2951
2952 /* 
2953    define a list of possible SMB messages and their corresponding
2954    functions. Any message that has a NULL function is unimplemented -
2955    please feel free to contribute implementations!
2956 */
2957 struct smb_message_struct
2958 {
2959   int code;
2960   char *name;
2961   int (*fn)();
2962   int flags;
2963 #if PROFILING
2964   unsigned long time;
2965 #endif
2966 }
2967  smb_messages[] = {
2968
2969     /* CORE PROTOCOL */
2970
2971    {SMBnegprot,"SMBnegprot",reply_negprot,0},
2972    {SMBtcon,"SMBtcon",reply_tcon,0},
2973    {SMBtdis,"SMBtdis",reply_tdis,0},
2974    {SMBexit,"SMBexit",reply_exit,0},
2975    {SMBioctl,"SMBioctl",reply_ioctl,0},
2976    {SMBecho,"SMBecho",reply_echo,0},
2977    {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
2978    {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
2979    {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, 
2980    {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
2981    {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
2982    {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
2983    {SMBsearch,"SMBsearch",reply_search,AS_USER},
2984    {SMBopen,"SMBopen",reply_open,AS_USER},
2985
2986    /* note that SMBmknew and SMBcreate are deliberately overloaded */   
2987    {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
2988    {SMBmknew,"SMBmknew",reply_mknew,AS_USER}, 
2989
2990    {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
2991    {SMBread,"SMBread",reply_read,AS_USER},
2992    {SMBwrite,"SMBwrite",reply_write,AS_USER},
2993    {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
2994    {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
2995    {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
2996    {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
2997    {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
2998
2999    /* this is a Pathworks specific call, allowing the 
3000       changing of the root path */
3001    {pSETDIR,"pSETDIR",reply_setdir,AS_USER}, 
3002
3003    {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3004    {SMBflush,"SMBflush",reply_flush,AS_USER},
3005    {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3006    {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3007    {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3008    {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST},
3009    {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3010    {SMBlock,"SMBlock",reply_lock,AS_USER},
3011    {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3012    
3013    /* CORE+ PROTOCOL FOLLOWS */
3014    
3015    {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3016    {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3017    {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3018    {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3019    {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3020    
3021    /* LANMAN1.0 PROTOCOL FOLLOWS */
3022    
3023    {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3024    {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3025    {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3026    {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3027    {SMBwritec,"SMBwritec",NULL,AS_USER},
3028    {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3029    {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3030    {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3031    {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3032    {SMBioctls,"SMBioctls",NULL,AS_USER},
3033    {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3034    {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3035    
3036    {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC},
3037    {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3038    {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3039    {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3040    
3041    {SMBffirst,"SMBffirst",reply_search,AS_USER},
3042    {SMBfunique,"SMBfunique",reply_search,AS_USER},
3043    {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3044
3045    /* LANMAN2.0 PROTOCOL FOLLOWS */
3046    {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3047    {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3048    {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3049    {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3050
3051    /* messaging routines */
3052    {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3053    {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3054    {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3055    {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3056
3057    /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3058    
3059    {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3060    {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3061    {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3062    {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3063  };
3064
3065 /****************************************************************************
3066 return a string containing the function name of a SMB command
3067 ****************************************************************************/
3068 char *smb_fn_name(int type)
3069 {
3070   static char *unknown_name = "SMBunknown";
3071   static int num_smb_messages = 
3072     sizeof(smb_messages) / sizeof(struct smb_message_struct);
3073   int match;
3074
3075   for (match=0;match<num_smb_messages;match++)
3076     if (smb_messages[match].code == type)
3077       break;
3078
3079   if (match == num_smb_messages)
3080     return(unknown_name);
3081
3082   return(smb_messages[match].name);
3083 }
3084
3085
3086 /****************************************************************************
3087 do a switch on the message type, and return the response size
3088 ****************************************************************************/
3089 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3090 {
3091   static int pid= -1;
3092   int outsize = 0;
3093   static int num_smb_messages = 
3094     sizeof(smb_messages) / sizeof(struct smb_message_struct);
3095   int match;
3096
3097 #if PROFILING
3098   struct timeval msg_start_time;
3099   struct timeval msg_end_time;
3100   static unsigned long total_time = 0;
3101
3102   GetTimeOfDay(&msg_start_time);
3103 #endif
3104
3105   if (pid == -1)
3106     pid = getpid();
3107
3108   errno = 0;
3109   last_message = type;
3110
3111   /* make sure this is an SMB packet */
3112   if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3113     {
3114       DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3115       return(-1);
3116     }
3117
3118   for (match=0;match<num_smb_messages;match++)
3119     if (smb_messages[match].code == type)
3120       break;
3121
3122   if (match == num_smb_messages)
3123     {
3124       DEBUG(0,("Unknown message type %d!\n",type));
3125       outsize = reply_unknown(inbuf,outbuf);
3126     }
3127   else
3128     {
3129       DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3130       if (smb_messages[match].fn)
3131         {
3132           int cnum = SVAL(inbuf,smb_tid);
3133           int flags = smb_messages[match].flags;
3134           int uid = SVAL(inbuf,smb_uid);
3135
3136           /* does this protocol need to be run as root? */
3137           if (!(flags & AS_USER))
3138             unbecome_user();
3139
3140           /* does this protocol need to be run as the connected user? */
3141           if ((flags & AS_USER) && !become_user(cnum,uid)) {
3142             if (flags & AS_GUEST) 
3143               flags &= ~AS_USER;
3144             else
3145               return(ERROR(ERRSRV,ERRinvnid));
3146           }
3147           /* this code is to work around a bug is MS client 3 without
3148              introducing a security hole - it needs to be able to do
3149              print queue checks as guest if it isn't logged in properly */
3150           if (flags & AS_USER)
3151             flags &= ~AS_GUEST;
3152
3153           /* does it need write permission? */
3154           if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3155             return(ERROR(ERRSRV,ERRaccess));
3156
3157           /* ipc services are limited */
3158           if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3159             return(ERROR(ERRSRV,ERRaccess));        
3160
3161           /* load service specific parameters */
3162           if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3163             return(ERROR(ERRSRV,ERRaccess));
3164
3165           /* does this protocol need to be run as guest? */
3166           if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3167             return(ERROR(ERRSRV,ERRaccess));
3168
3169           last_inbuf = inbuf;
3170
3171           outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3172         }
3173       else
3174         {
3175           outsize = reply_unknown(inbuf,outbuf);
3176         }
3177     }
3178
3179 #if PROFILING
3180   GetTimeOfDay(&msg_end_time);
3181   if (!(smb_messages[match].flags & TIME_INIT))
3182     {
3183       smb_messages[match].time = 0;
3184       smb_messages[match].flags |= TIME_INIT;
3185     }
3186   {
3187     unsigned long this_time =     
3188       (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3189         (msg_end_time.tv_usec - msg_start_time.tv_usec);
3190     smb_messages[match].time += this_time;
3191     total_time += this_time;
3192   }
3193   DEBUG(2,("TIME %s  %d usecs   %g pct\n",
3194            smb_fn_name(type),smb_messages[match].time,
3195         (100.0*smb_messages[match].time) / total_time));
3196 #endif
3197
3198   return(outsize);
3199 }
3200
3201
3202 /****************************************************************************
3203   construct a chained reply and add it to the already made reply
3204   **************************************************************************/
3205 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
3206 {
3207   static char *orig_inbuf;
3208   static char *orig_outbuf;
3209   int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
3210   unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
3211   char *inbuf2, *outbuf2;
3212   int outsize2;
3213   char inbuf_saved[smb_wct];
3214   char outbuf_saved[smb_wct];
3215   extern int chain_size;
3216   int wct = CVAL(outbuf,smb_wct);
3217   int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
3218
3219   /* maybe its not chained */
3220   if (smb_com2 == 0xFF) {
3221     CVAL(outbuf,smb_vwv0) = 0xFF;
3222     return outsize;
3223   }
3224
3225   if (chain_size == 0) {
3226     /* this is the first part of the chain */
3227     orig_inbuf = inbuf;
3228     orig_outbuf = outbuf;
3229   }
3230
3231   /* we need to tell the client where the next part of the reply will be */
3232   SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
3233   CVAL(outbuf,smb_vwv0) = smb_com2;
3234
3235   /* remember how much the caller added to the chain, only counting stuff
3236      after the parameter words */
3237   chain_size += outsize - smb_wct;
3238
3239   /* work out pointers into the original packets. The
3240      headers on these need to be filled in */
3241   inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
3242   outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
3243
3244   /* remember the original command type */
3245   smb_com1 = CVAL(orig_inbuf,smb_com);
3246
3247   /* save the data which will be overwritten by the new headers */
3248   memcpy(inbuf_saved,inbuf2,smb_wct);
3249   memcpy(outbuf_saved,outbuf2,smb_wct);
3250
3251   /* give the new packet the same header as the last part of the SMB */
3252   memmove(inbuf2,inbuf,smb_wct);
3253
3254   /* create the in buffer */
3255   CVAL(inbuf2,smb_com) = smb_com2;
3256
3257   /* create the out buffer */
3258   bzero(outbuf2,smb_size);
3259   set_message(outbuf2,0,0,True);
3260   CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com);
3261   
3262   memcpy(outbuf2+4,inbuf2+4,4);
3263   CVAL(outbuf2,smb_rcls) = SUCCESS;
3264   CVAL(outbuf2,smb_reh) = 0;
3265   CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set 
3266                                                                   means a reply */
3267   SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */
3268   SSVAL(outbuf2,smb_err,SUCCESS);
3269   SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid));
3270   SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid));
3271   SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid));
3272   SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid));
3273
3274   DEBUG(3,("Chained message\n"));
3275   show_msg(inbuf2);
3276
3277   /* process the request */
3278   outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
3279                             bufsize-chain_size);
3280
3281   /* copy the new reply and request headers over the old ones, but
3282      preserve the smb_com field */
3283   memmove(orig_outbuf,outbuf2,smb_wct);
3284   CVAL(orig_outbuf,smb_com) = smb_com1;
3285
3286   /* restore the saved data, being careful not to overwrite any
3287    data from the reply header */
3288   memcpy(inbuf2,inbuf_saved,smb_wct);
3289   {
3290     int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
3291     if (ofs < 0) ofs = 0;
3292     memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
3293   }
3294
3295   return outsize2;
3296 }
3297
3298
3299
3300 /****************************************************************************
3301   construct a reply to the incoming packet
3302 ****************************************************************************/
3303 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3304 {
3305   int type = CVAL(inbuf,smb_com);
3306   int outsize = 0;
3307   int msg_type = CVAL(inbuf,0);
3308   extern int chain_size;
3309
3310   smb_last_time = time(NULL);
3311
3312   chain_size = 0;
3313   chain_fnum = -1;
3314
3315   bzero(outbuf,smb_size);
3316
3317   if (msg_type != 0)
3318     return(reply_special(inbuf,outbuf));  
3319
3320   CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3321   set_message(outbuf,0,0,True);
3322   
3323   memcpy(outbuf+4,inbuf+4,4);
3324   CVAL(outbuf,smb_rcls) = SUCCESS;
3325   CVAL(outbuf,smb_reh) = 0;
3326   CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set 
3327                                                              means a reply */
3328   SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3329   SSVAL(outbuf,smb_err,SUCCESS);
3330   SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3331   SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3332   SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3333   SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3334
3335   outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3336
3337   outsize += chain_size;
3338
3339   if(outsize > 4)
3340     smb_setlen(outbuf,outsize - 4);
3341   return(outsize);
3342 }
3343
3344
3345 /****************************************************************************
3346   process commands from the client
3347 ****************************************************************************/
3348 static void process(void)
3349 {
3350   static int trans_num = 0;
3351   int nread;
3352   extern struct from_host Client_info;
3353   extern int Client;
3354
3355   fromhost(Client,&Client_info);
3356   
3357   InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3358   OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3359   if ((InBuffer == NULL) || (OutBuffer == NULL)) 
3360     return;
3361
3362   InBuffer += SMB_ALIGNMENT;
3363   OutBuffer += SMB_ALIGNMENT;
3364
3365 #if PRIME_NMBD
3366   DEBUG(3,("priming nmbd\n"));
3367   {
3368     struct in_addr ip;
3369     ip = *interpret_addr2("localhost");
3370     if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3371     *OutBuffer = 0;
3372     send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
3373   }
3374 #endif    
3375
3376   while (True)
3377     {
3378       int32 len;      
3379       int msg_type;
3380       int msg_flags;
3381       int type;
3382       int deadtime = lp_deadtime()*60;
3383       int counter;
3384       int last_keepalive=0;
3385
3386       if (deadtime <= 0)
3387         deadtime = DEFAULT_SMBD_TIMEOUT;
3388
3389       if (lp_readprediction())
3390         do_read_prediction();
3391
3392       {
3393         extern pstring share_del_pending;
3394         if (*share_del_pending) {
3395           unbecome_user();
3396           if (!unlink(share_del_pending))
3397             DEBUG(3,("Share file deleted %s\n",share_del_pending));
3398           else
3399             DEBUG(2,("Share del failed of %s\n",share_del_pending));
3400           share_del_pending[0] = 0;
3401         }
3402       }
3403
3404       if (share_mode_pending) {
3405         unbecome_user();
3406         check_share_modes();
3407         share_mode_pending=False;
3408       }
3409
3410       errno = 0;      
3411
3412       for (counter=SMBD_SELECT_LOOP; 
3413            !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000); 
3414            counter += SMBD_SELECT_LOOP)
3415         {
3416           int i;
3417           time_t t;
3418           BOOL allidle = True;
3419           extern int keepalive;
3420
3421           if (smb_read_error == READ_EOF) {
3422             DEBUG(3,("end of file from client\n"));
3423             return;
3424           }
3425
3426           if (smb_read_error == READ_ERROR) {
3427             DEBUG(3,("receive_smb error (%s) exiting\n",
3428                      strerror(errno)));
3429             return;
3430           }
3431
3432           t = time(NULL);
3433
3434           /* become root again if waiting */
3435           unbecome_user();
3436
3437           /* check for smb.conf reload */
3438           if (!(counter%SMBD_RELOAD_CHECK))
3439             reload_services(True);
3440
3441           /* check the share modes every 10 secs */
3442           if (!(counter%SHARE_MODES_CHECK))
3443             check_share_modes();
3444
3445           /* clean the share modes every 5 minutes */
3446           if (!(counter%SHARE_MODES_CLEAN))
3447             clean_share_modes();
3448
3449           /* automatic timeout if all connections are closed */      
3450           if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3451             DEBUG(2,("%s Closing idle connection\n",timestring()));
3452             return;
3453           }
3454
3455           if (keepalive && (counter-last_keepalive)>keepalive) {
3456             extern int password_client;
3457             if (!send_keepalive(Client)) {
3458               DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3459               return;
3460             }       
3461             /* also send a keepalive to the password server if its still
3462                connected */
3463             if (password_client != -1)
3464               send_keepalive(password_client);
3465             last_keepalive = counter;
3466           }
3467
3468           /* check for connection timeouts */
3469           for (i=0;i<MAX_CONNECTIONS;i++)
3470             if (Connections[i].open)
3471               {
3472                 /* close dirptrs on connections that are idle */
3473                 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
3474                   dptr_idlecnum(i);
3475
3476                 if (Connections[i].num_files_open > 0 ||
3477                     (t-Connections[i].lastused)<deadtime)
3478                   allidle = False;
3479               }
3480
3481           if (allidle && num_connections_open>0) {
3482             DEBUG(2,("%s Closing idle connection 2\n",timestring()));
3483             return;
3484           }
3485         }
3486
3487       msg_type = CVAL(InBuffer,0);
3488       msg_flags = CVAL(InBuffer,1);
3489       type = CVAL(InBuffer,smb_com);
3490
3491       len = smb_len(InBuffer);
3492
3493       DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
3494
3495       nread = len + 4;
3496       
3497       DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
3498
3499 #ifdef WITH_VTP
3500       if(trans_num == 1 && VT_Check(InBuffer)) {
3501         VT_Process();
3502         return;
3503       }
3504 #endif
3505
3506
3507       if (msg_type == 0)
3508         show_msg(InBuffer);
3509
3510       nread = construct_reply(InBuffer,OutBuffer,nread,maxxmit);
3511       
3512       if(nread > 0) {
3513         if (CVAL(OutBuffer,0) == 0)
3514           show_msg(OutBuffer);
3515         
3516         if (nread != smb_len(OutBuffer) + 4) 
3517           {
3518             DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
3519                      nread,
3520                      smb_len(OutBuffer)));
3521           }
3522         else
3523           send_smb(Client,OutBuffer);
3524       }
3525       trans_num++;
3526     }
3527 }
3528
3529
3530 /****************************************************************************
3531   initialise connect, service and file structs
3532 ****************************************************************************/
3533 static void init_structs(void )
3534 {
3535   int i;
3536   get_myname(myhostname,NULL);
3537
3538   for (i=0;i<MAX_CONNECTIONS;i++)
3539     {
3540       Connections[i].open = False;
3541       Connections[i].num_files_open=0;
3542       Connections[i].lastused=0;
3543       Connections[i].used=False;
3544       string_init(&Connections[i].user,"");
3545       string_init(&Connections[i].dirpath,"");
3546       string_init(&Connections[i].connectpath,"");
3547       string_init(&Connections[i].origpath,"");
3548     }
3549
3550   for (i=0;i<MAX_OPEN_FILES;i++)
3551     {
3552       Files[i].open = False;
3553       string_init(&Files[i].name,"");
3554     }
3555
3556   init_dptrs();
3557 }
3558
3559 /****************************************************************************
3560 usage on the program
3561 ****************************************************************************/
3562 static void usage(char *pname)
3563 {
3564   DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
3565
3566   printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
3567   printf("Version %s\n",VERSION);
3568   printf("\t-D                    become a daemon\n");
3569   printf("\t-p port               listen on the specified port\n");
3570   printf("\t-d debuglevel         set the debuglevel\n");
3571   printf("\t-l log basename.      Basename for log/debug files\n");
3572   printf("\t-s services file.     Filename of services file\n");
3573   printf("\t-P                    passive only\n");
3574   printf("\t-a                    overwrite log file, don't append\n");
3575   printf("\n");
3576 }
3577
3578
3579 /****************************************************************************
3580   main program
3581 ****************************************************************************/
3582  int main(int argc,char *argv[])
3583 {
3584   extern BOOL append_log;
3585   /* shall I run as a daemon */
3586   BOOL is_daemon = False;
3587   int port = SMB_PORT;
3588   int opt;
3589   extern char *optarg;
3590
3591 #ifdef NEED_AUTH_PARAMETERS
3592   set_auth_parameters(argc,argv);
3593 #endif
3594
3595 #ifdef SecureWare
3596   setluid(0);
3597 #endif
3598
3599   append_log = True;
3600
3601   TimeInit();
3602
3603   strcpy(debugf,SMBLOGFILE);  
3604
3605   setup_logging(argv[0],False);
3606
3607   charset_initialise();
3608
3609   /* make absolutely sure we run as root - to handle cases whre people
3610      are crazy enough to have it setuid */
3611 #ifdef USE_SETRES
3612   setresuid(0,0,0);
3613 #else
3614   setuid(0);
3615   seteuid(0);
3616   setuid(0);
3617   seteuid(0);
3618 #endif
3619
3620   fault_setup(exit_server);
3621
3622   /* we want total control over the permissions on created files,
3623      so set our umask to 0 */
3624   umask(0);
3625
3626   init_uid();
3627
3628   /* this is for people who can't start the program correctly */
3629   while (argc > 1 && (*argv[1] != '-'))
3630     {
3631       argv++;
3632       argc--;
3633     }
3634
3635   while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPa")) != EOF)
3636     switch (opt)
3637       {
3638       case 'O':
3639         strcpy(user_socket_options,optarg);
3640         break;
3641       case 'i':
3642         strcpy(scope,optarg);
3643         break;
3644       case 'P':
3645         {
3646           extern BOOL passive;
3647           passive = True;
3648         }
3649         break;  
3650       case 's':
3651         strcpy(servicesf,optarg);
3652         break;
3653       case 'l':
3654         strcpy(debugf,optarg);
3655         break;
3656       case 'a':
3657         {
3658           extern BOOL append_log;
3659           append_log = !append_log;
3660         }
3661         break;
3662       case 'D':
3663         is_daemon = True;
3664         break;
3665       case 'd':
3666         if (*optarg == 'A')
3667           DEBUGLEVEL = 10000;
3668         else
3669           DEBUGLEVEL = atoi(optarg);
3670         break;
3671       case 'p':
3672         port = atoi(optarg);
3673         break;
3674       case 'h':
3675         usage(argv[0]);
3676         exit(0);
3677         break;
3678       default:
3679         usage(argv[0]);
3680         exit(1);
3681       }
3682
3683   reopen_logs();
3684
3685   DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
3686   DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
3687
3688 #ifndef NO_GETRLIMIT
3689 #ifdef RLIMIT_NOFILE
3690   {
3691     struct rlimit rlp;
3692     getrlimit(RLIMIT_NOFILE, &rlp);
3693     rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
3694     setrlimit(RLIMIT_NOFILE, &rlp);
3695     getrlimit(RLIMIT_NOFILE, &rlp);
3696     DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
3697   }
3698 #endif
3699 #endif
3700
3701   
3702   DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
3703         getuid(),getgid(),geteuid(),getegid()));
3704
3705   if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
3706     {
3707       DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
3708       exit(1);
3709     }
3710
3711   init_structs();
3712
3713   if (!reload_services(False))
3714     return(-1); 
3715
3716 #ifndef NO_SIGNAL_TEST
3717   signal(SIGHUP,SIGNAL_CAST sig_hup);
3718 #endif
3719   
3720   DEBUG(3,("%s loaded services\n",timestring()));
3721
3722   if (!is_daemon && !is_a_socket(0))
3723     {
3724       DEBUG(0,("standard input is not a socket, assuming -D option\n"));
3725       is_daemon = True;
3726     }
3727
3728   if (is_daemon)
3729     {
3730       DEBUG(3,("%s becoming a daemon\n",timestring()));
3731       become_daemon();
3732     }
3733
3734   if (!open_sockets(is_daemon,port))
3735     exit(1);
3736
3737 #if FAST_SHARE_MODES
3738   if (!start_share_mode_mgmt())
3739     exit(1);
3740 #endif
3741
3742   /* possibly reload the services file. */
3743   reload_services(True);
3744
3745   maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE);
3746
3747   if (*lp_rootdir())
3748     {
3749       if (sys_chroot(lp_rootdir()) == 0)
3750         DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
3751     }
3752
3753   process();
3754   close_sockets();
3755
3756 #if FAST_SHARE_MODES
3757   stop_share_mode_mgmt();
3758 #endif
3759
3760   exit_server("normal exit");
3761   return(0);
3762 }
3763
3764