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