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