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