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