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