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