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