'The mother of all checkins' :-). Jeremy Allison (jallison@whistle.com)
[jra/samba/.git] / source3 / smbd / server.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Main SMB server routines
5    Copyright (C) Andrew Tridgell 1992-1997
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23 #include "trans2.h"
24
25 pstring servicesf = CONFIGFILE;
26 extern pstring debugf;
27 extern pstring sesssetup_user;
28
29 char *InBuffer = NULL;
30 char *OutBuffer = NULL;
31 char *last_inbuf = NULL;
32
33 int am_parent = 1;
34 int atexit_set = 0;
35
36 BOOL share_mode_pending = False;
37
38 /* the last message the was processed */
39 int last_message = -1;
40
41 /* a useful macro to debug the last message processed */
42 #define LAST_MESSAGE() smb_fn_name(last_message)
43
44 extern pstring scope;
45 extern int DEBUGLEVEL;
46 extern int case_default;
47 extern BOOL case_sensitive;
48 extern BOOL case_preserve;
49 extern BOOL use_mangled_map;
50 extern BOOL short_case_preserve;
51 extern BOOL case_mangle;
52 extern time_t smb_last_time;
53
54 extern int smb_read_error;
55
56 extern pstring user_socket_options;
57
58 connection_struct Connections[MAX_CONNECTIONS];
59 files_struct Files[MAX_OPEN_FILES];
60
61 /*
62  * Indirection for file fd's. Needed as POSIX locking
63  * is based on file/process, not fd/process.
64  */
65 file_fd_struct FileFd[MAX_OPEN_FILES];
66 int max_file_fd_used = 0;
67
68 extern int Protocol;
69
70 /* 
71  * Size of data we can send to client. Set
72  *  by the client for all protocols above CORE.
73  *  Set by us for CORE protocol.
74  */
75 int max_send = BUFFER_SIZE;
76 /*
77  * Size of the data we can receive. Set by us.
78  * Can be modified by the max xmit parameter.
79  */
80 int max_recv = BUFFER_SIZE;
81
82 /* a fnum to use when chaining */
83 int chain_fnum = -1;
84
85 /* number of open connections */
86 static int num_connections_open = 0;
87
88 extern fstring remote_machine;
89
90 pstring OriginalDir;
91
92 /* these can be set by some functions to override the error codes */
93 int unix_ERR_class=SUCCESS;
94 int unix_ERR_code=0;
95
96
97 extern int extra_time_offset;
98
99 extern pstring myhostname;
100
101 static int find_free_connection(int hash);
102
103 /* for readability... */
104 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
105 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
106 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
107 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
108 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
109
110 /****************************************************************************
111   when exiting, take the whole family
112 ****************************************************************************/
113 void  *dflt_sig(void)
114 {
115   exit_server("caught signal");
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        (((int32)sbuf->st_dev) == fd_ptr->dev) &&
841        (((int32)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 = (int32)-1;
865       fd_ptr->inode = (int32)-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 = -1;
931       fd_ptr->inode = -1;
932     }
933   } 
934  return fd_ptr->ref_count;
935 }
936
937 /****************************************************************************
938 open a file
939 ****************************************************************************/
940 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     /* 
1037      * If O_TRUNC was set, ensure we truncate the file.
1038      * open_file_shared explicitly clears this flag before
1039      * calling open_file, so we can safely do this here.
1040      */
1041     if(flags & O_TRUNC)
1042       ftruncate(fd_ptr->fd, 0);
1043       
1044   } else {
1045     int open_flags;
1046     /* We need to allocate a new file_fd_struct (this increments the
1047        ref_count). */
1048     if((fd_ptr = fd_get_new()) == 0)
1049       return;
1050     /*
1051      * Whatever the requested flags, attempt read/write access,
1052      * as we don't know what flags future file opens may require.
1053      * If this fails, try again with the required flags. 
1054      * Even if we open read/write when only read access was 
1055      * requested the setting of the can_write flag in
1056      * the file_struct will protect us from errant
1057      * write requests. We never need to worry about O_APPEND
1058      * as this is not set anywhere in Samba.
1059      */
1060     fd_ptr->real_open_flags = O_RDWR;
1061     /* Set the flags as needed without the read/write modes. */
1062     open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY);
1063     fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode);
1064     /*
1065      * On some systems opening a file for R/W access on a read only
1066      * filesystems sets errno to EROFS.
1067      */
1068 #ifdef EROFS
1069     if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) {
1070 #else /* No EROFS */
1071     if((fd_ptr->fd == -1) && (errno == EACCES)) {
1072 #endif /* EROFS */
1073       if(flags & O_WRONLY) {
1074         fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode);
1075         fd_ptr->real_open_flags = O_WRONLY;
1076       } else {
1077         fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode);
1078         fd_ptr->real_open_flags = O_RDONLY;
1079       }
1080     }
1081   }
1082
1083   if ((fd_ptr->fd >=0) && 
1084       Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
1085     pstring dname;
1086     int dum1,dum2,dum3;
1087     char *p;
1088     strcpy(dname,fname);
1089     p = strrchr(dname,'/');
1090     if (p) *p = 0;
1091     if (sys_disk_free(dname,&dum1,&dum2,&dum3) < 
1092         lp_minprintspace(SNUM(cnum))) {
1093       fd_attempt_close(fd_ptr);
1094       Files[fnum].fd_ptr = 0;
1095       if(fd_ptr->ref_count == 0)
1096         sys_unlink(fname);
1097       errno = ENOSPC;
1098       return;
1099     }
1100   }
1101     
1102   if (fd_ptr->fd < 0)
1103     {
1104       DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
1105                fname,strerror(errno),flags));
1106       /* Ensure the ref_count is decremented. */
1107       fd_attempt_close(fd_ptr);
1108       check_for_pipe(fname);
1109       return;
1110     }
1111
1112   if (fd_ptr->fd >= 0)
1113     {
1114       if(sbuf == 0) {
1115         /* Do the fstat */
1116         if(fstat(fd_ptr->fd, &statbuf) == -1) {
1117           /* Error - backout !! */
1118           DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
1119                    fd_ptr->fd, fname,strerror(errno)));
1120           /* Ensure the ref_count is decremented. */
1121           fd_attempt_close(fd_ptr);
1122           return;
1123         }
1124         sbuf = &statbuf;
1125       }
1126       /* Set the correct entries in fd_ptr. */
1127       fd_ptr->dev = (int32)sbuf->st_dev;
1128       fd_ptr->inode = (int32)sbuf->st_ino;
1129
1130       Files[fnum].fd_ptr = fd_ptr;
1131       Connections[cnum].num_files_open++;
1132       Files[fnum].mode = sbuf->st_mode;
1133       GetTimeOfDay(&Files[fnum].open_time);
1134       Files[fnum].uid = current_user.id;
1135       Files[fnum].size = 0;
1136       Files[fnum].pos = -1;
1137       Files[fnum].open = True;
1138       Files[fnum].mmap_ptr = NULL;
1139       Files[fnum].mmap_size = 0;
1140       Files[fnum].can_lock = True;
1141       Files[fnum].can_read = ((flags & O_WRONLY)==0);
1142       Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
1143       Files[fnum].share_mode = 0;
1144       Files[fnum].share_pending = False;
1145       Files[fnum].print_file = Connections[cnum].printer;
1146       Files[fnum].modified = False;
1147       Files[fnum].cnum = cnum;
1148       string_set(&Files[fnum].name,dos_to_unix(fname,False));
1149       Files[fnum].wbmpx_ptr = NULL;      
1150
1151       /*
1152        * If the printer is marked as postscript output a leading
1153        * file identifier to ensure the file is treated as a raw
1154        * postscript file.
1155        * This has a similar effect as CtrlD=0 in WIN.INI file.
1156        * tim@fsg.com 09/06/94
1157        */
1158       if (Files[fnum].print_file && POSTSCRIPT(cnum) && 
1159           Files[fnum].can_write) 
1160         {
1161           DEBUG(3,("Writing postscript line\n"));
1162           write_file(fnum,"%!\n",3);
1163         }
1164       
1165       DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
1166                timestring(),Connections[cnum].user,fname,
1167                BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
1168                Connections[cnum].num_files_open,fnum));
1169
1170     }
1171
1172 #if USE_MMAP
1173   /* mmap it if read-only */
1174   if (!Files[fnum].can_write)
1175     {
1176       Files[fnum].mmap_size = file_size(fname);
1177       Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
1178                                           PROT_READ,MAP_SHARED,Files[fnum].fd_ptr->fd,0);
1179
1180       if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
1181         {
1182           DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
1183           Files[fnum].mmap_ptr = NULL;
1184         }
1185     }
1186 #endif
1187 }
1188
1189 /*******************************************************************
1190 sync a file
1191 ********************************************************************/
1192 void sync_file(int fnum)
1193 {
1194 #ifndef NO_FSYNC
1195   fsync(Files[fnum].fd_ptr->fd);
1196 #endif
1197 }
1198
1199 /****************************************************************************
1200 run a file if it is a magic script
1201 ****************************************************************************/
1202 static void check_magic(int fnum,int cnum)
1203 {
1204   if (!*lp_magicscript(SNUM(cnum)))
1205     return;
1206
1207   DEBUG(5,("checking magic for %s\n",Files[fnum].name));
1208
1209   {
1210     char *p;
1211     if (!(p = strrchr(Files[fnum].name,'/')))
1212       p = Files[fnum].name;
1213     else
1214       p++;
1215
1216     if (!strequal(lp_magicscript(SNUM(cnum)),p))
1217       return;
1218   }
1219
1220   {
1221     int ret;
1222     pstring magic_output;
1223     pstring fname;
1224     strcpy(fname,Files[fnum].name);
1225
1226     if (*lp_magicoutput(SNUM(cnum)))
1227       strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
1228     else
1229       sprintf(magic_output,"%s.out",fname);
1230
1231     chmod(fname,0755);
1232     ret = smbrun(fname,magic_output,False);
1233     DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
1234     unlink(fname);
1235   }
1236 }
1237
1238
1239 /****************************************************************************
1240 close a file - possibly invalidating the read prediction
1241 ****************************************************************************/
1242 void close_file(int fnum)
1243 {
1244   int cnum = Files[fnum].cnum;
1245   invalidate_read_prediction(Files[fnum].fd_ptr->fd);
1246   Files[fnum].open = False;
1247   Connections[cnum].num_files_open--;
1248   if(Files[fnum].wbmpx_ptr) 
1249     {
1250       free((char *)Files[fnum].wbmpx_ptr);
1251       Files[fnum].wbmpx_ptr = NULL;
1252     }
1253
1254 #if USE_MMAP
1255   if(Files[fnum].mmap_ptr) 
1256     {
1257       munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size);
1258       Files[fnum].mmap_ptr = NULL;
1259     }
1260 #endif
1261
1262   if (lp_share_modes(SNUM(cnum)))
1263     del_share_mode(fnum);
1264
1265   fd_attempt_close(Files[fnum].fd_ptr);
1266
1267   /* NT uses smbclose to start a print - weird */
1268   if (Files[fnum].print_file)
1269     print_file(fnum);
1270
1271   /* check for magic scripts */
1272   check_magic(fnum,cnum);
1273
1274   DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
1275            timestring(),Connections[cnum].user,Files[fnum].name,
1276            Connections[cnum].num_files_open));
1277 }
1278
1279 enum {AFAIL,AREAD,AWRITE,AALL};
1280
1281 /*******************************************************************
1282 reproduce the share mode access table
1283 ********************************************************************/
1284 static int access_table(int new_deny,int old_deny,int old_mode,
1285                         int share_pid,char *fname)
1286 {
1287   if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
1288
1289   if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
1290     if (old_deny == new_deny && share_pid == getpid()) 
1291         return(AALL);    
1292
1293     if (old_mode == 0) return(AREAD);
1294
1295     /* the new smbpub.zip spec says that if the file extension is
1296        .com, .dll, .exe or .sym then allow the open. I will force
1297        it to read-only as this seems sensible although the spec is
1298        a little unclear on this. */
1299     if ((fname = strrchr(fname,'.'))) {
1300       if (strequal(fname,".com") ||
1301           strequal(fname,".dll") ||
1302           strequal(fname,".exe") ||
1303           strequal(fname,".sym"))
1304         return(AREAD);
1305     }
1306
1307     return(AFAIL);
1308   }
1309
1310   switch (new_deny) 
1311     {
1312     case DENY_WRITE:
1313       if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1314       if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1315       if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1316       return(AFAIL);
1317     case DENY_READ:
1318       if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1319       if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1320       if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1321       return(AFAIL);
1322     case DENY_NONE:
1323       if (old_deny==DENY_WRITE) return(AREAD);
1324       if (old_deny==DENY_READ) return(AWRITE);
1325       if (old_deny==DENY_NONE) return(AALL);
1326       return(AFAIL);      
1327     }
1328   return(AFAIL);      
1329 }
1330
1331 /*******************************************************************
1332 check if the share mode on a file allows it to be deleted or unlinked
1333 return True if sharing doesn't prevent the operation
1334 ********************************************************************/
1335 BOOL check_file_sharing(int cnum,char *fname)
1336 {
1337   int pid=0;
1338   int share_mode = get_share_mode_byname(cnum,fname,&pid);
1339
1340   if (!pid || !share_mode) return(True);
1341  
1342   if (share_mode == DENY_DOS)
1343     return(pid == getpid());
1344
1345   /* XXXX exactly what share mode combinations should be allowed for
1346      deleting/renaming? */
1347   return(False);
1348 }
1349
1350 /****************************************************************************
1351   C. Hoch 11/22/95
1352   Helper for open_file_shared. 
1353   Truncate a file after checking locking; close file if locked.
1354   **************************************************************************/
1355 static void truncate_unless_locked(int fnum, int cnum)
1356 {
1357   if (Files[fnum].can_write){
1358     if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1359       close_file(fnum);   
1360       errno = EACCES;
1361       unix_ERR_class = ERRDOS;
1362       unix_ERR_code = ERRlock;
1363     }
1364     else
1365       ftruncate(Files[fnum].fd_ptr->fd,0); 
1366   }
1367 }
1368
1369
1370 /****************************************************************************
1371 open a file with a share mode
1372 ****************************************************************************/
1373 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1374                       int mode,int *Access,int *action)
1375 {
1376   int flags=0;
1377   int flags2=0;
1378   int deny_mode = (share_mode>>4)&7;
1379   struct stat sbuf;
1380   BOOL file_existed = file_exist(fname,&sbuf);
1381   BOOL fcbopen = False;
1382   int share_pid=0;
1383
1384   Files[fnum].open = False;
1385   Files[fnum].fd_ptr = 0;
1386
1387   /* this is for OS/2 EAs - try and say we don't support them */
1388   if (strstr(fname,".+,;=[].")) {
1389     unix_ERR_class = ERRDOS;
1390     unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1391     return;
1392   }
1393
1394   if ((ofun & 0x3) == 0 && file_existed) {
1395     errno = EEXIST;
1396     return;
1397   }
1398       
1399   if (ofun & 0x10)
1400     flags2 |= O_CREAT;
1401   if ((ofun & 0x3) == 2)
1402     flags2 |= O_TRUNC;
1403
1404   /* note that we ignore the append flag as 
1405      append does not mean the same thing under dos and unix */
1406
1407   switch (share_mode&0xF)
1408     {
1409     case 1: 
1410       flags = O_WRONLY; 
1411       break;
1412     case 0xF: 
1413       fcbopen = True;
1414       flags = O_RDWR; 
1415       break;
1416     case 2: 
1417       flags = O_RDWR; 
1418       break;
1419     default:
1420       flags = O_RDONLY;
1421       break;
1422     }
1423   
1424   if (flags != O_RDONLY && file_existed && 
1425       (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) {
1426     if (!fcbopen) {
1427       errno = EACCES;
1428       return;
1429     }
1430     flags = O_RDONLY;
1431   }
1432
1433   if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) {
1434     DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1435     errno = EINVAL;
1436     return;
1437   }
1438
1439   if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1440
1441   if (lp_share_modes(SNUM(cnum))) {
1442     int old_share=0;
1443
1444     if (file_existed)
1445       old_share = get_share_mode(cnum,&sbuf,&share_pid);
1446
1447     if (share_pid) {
1448       /* someone else has a share lock on it, check to see 
1449          if we can too */
1450       int old_open_mode = old_share&0xF;
1451       int old_deny_mode = (old_share>>4)&7;
1452
1453       if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) {
1454         DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
1455                  deny_mode,old_deny_mode,old_open_mode,fname));
1456         errno = EACCES;
1457         unix_ERR_class = ERRDOS;
1458         unix_ERR_code = ERRbadshare;
1459         return;
1460       }
1461
1462       {
1463         int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1464                                           share_pid,fname);
1465
1466         if ((access_allowed == AFAIL) ||
1467             (!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) ||
1468             (access_allowed == AREAD && flags == O_WRONLY) ||
1469             (access_allowed == AWRITE && flags == O_RDONLY)) {
1470           DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1471                    deny_mode,old_deny_mode,old_open_mode,
1472                    share_pid,fname,
1473                    access_allowed));
1474           errno = EACCES;
1475           unix_ERR_class = ERRDOS;
1476           unix_ERR_code = ERRbadshare;
1477           return;
1478         }
1479         
1480         if (access_allowed == AREAD)
1481           flags = O_RDONLY;
1482         
1483         if (access_allowed == AWRITE)
1484           flags = O_WRONLY;
1485       }
1486     }
1487   }
1488
1489   DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1490            flags,flags2,mode));
1491
1492   open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
1493   if (!Files[fnum].open && flags==O_RDWR && errno!=ENOENT && fcbopen) {
1494     flags = O_RDONLY;
1495     open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 );
1496   }
1497
1498   if (Files[fnum].open) {
1499     int open_mode=0;
1500     switch (flags) {
1501     case O_RDONLY:
1502       open_mode = 0;
1503       break;
1504     case O_RDWR:
1505       open_mode = 2;
1506       break;
1507     case O_WRONLY:
1508       open_mode = 1;
1509       break;
1510     }
1511
1512     Files[fnum].share_mode = (deny_mode<<4) | open_mode;
1513     Files[fnum].share_pending = True;
1514
1515     if (Access) {
1516       (*Access) = open_mode;
1517     }
1518     
1519     if (action) {
1520       if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1521       if (!file_existed) *action = 2;
1522       if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1523     }
1524
1525     if (!share_pid)
1526       share_mode_pending = True;
1527
1528     if ((flags2&O_TRUNC) && file_existed)
1529       truncate_unless_locked(fnum,cnum);
1530   }
1531 }
1532
1533
1534
1535 /*******************************************************************
1536 check for files that we should now set our share modes on
1537 ********************************************************************/
1538 static void check_share_modes(void)
1539 {
1540   int i;
1541   for (i=0;i<MAX_OPEN_FILES;i++)
1542     if(Files[i].open && Files[i].share_pending) {
1543       if (lp_share_modes(SNUM(Files[i].cnum))) {
1544         int pid=0;
1545         get_share_mode_by_fnum(Files[i].cnum,i,&pid);
1546         if (!pid) {
1547           set_share_mode(i,Files[i].share_mode);
1548           Files[i].share_pending = False;
1549         }
1550       } else {
1551         Files[i].share_pending = False; 
1552       }
1553     }
1554 }
1555
1556
1557 /****************************************************************************
1558 seek a file. Try to avoid the seek if possible
1559 ****************************************************************************/
1560 int seek_file(int fnum,int pos)
1561 {
1562   int offset = 0;
1563   if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1564     offset = 3;
1565
1566   Files[fnum].pos = lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET) - offset;
1567   return(Files[fnum].pos);
1568 }
1569
1570 /****************************************************************************
1571 read from a file
1572 ****************************************************************************/
1573 int read_file(int fnum,char *data,int pos,int n)
1574 {
1575   int ret=0,readret;
1576
1577   if (!Files[fnum].can_write)
1578     {
1579       ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n);
1580
1581       data += ret;
1582       n -= ret;
1583       pos += ret;
1584     }
1585
1586 #if USE_MMAP
1587   if (Files[fnum].mmap_ptr)
1588     {
1589       int num = MIN(n,Files[fnum].mmap_size-pos);
1590       if (num > 0)
1591         {
1592           memcpy(data,Files[fnum].mmap_ptr+pos,num);
1593           data += num;
1594           pos += num;
1595           n -= num;
1596           ret += num;
1597         }
1598     }
1599 #endif
1600
1601   if (n <= 0)
1602     return(ret);
1603
1604   if (seek_file(fnum,pos) != pos)
1605     {
1606       DEBUG(3,("Failed to seek to %d\n",pos));
1607       return(ret);
1608     }
1609   
1610   if (n > 0) {
1611     readret = read(Files[fnum].fd_ptr->fd,data,n);
1612     if (readret > 0) ret += readret;
1613   }
1614
1615   return(ret);
1616 }
1617
1618
1619 /****************************************************************************
1620 write to a file
1621 ****************************************************************************/
1622 int write_file(int fnum,char *data,int n)
1623 {
1624   if (!Files[fnum].can_write) {
1625     errno = EPERM;
1626     return(0);
1627   }
1628
1629   if (!Files[fnum].modified) {
1630     struct stat st;
1631     Files[fnum].modified = True;
1632     if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) {
1633       int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1634       if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {  
1635         dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1636       }
1637     }  
1638   }
1639
1640   return(write_data(Files[fnum].fd_ptr->fd,data,n));
1641 }
1642
1643
1644 /****************************************************************************
1645 load parameters specific to a connection/service
1646 ****************************************************************************/
1647 BOOL become_service(int cnum,BOOL do_chdir)
1648 {
1649   extern char magic_char;
1650   static int last_cnum = -1;
1651   int snum;
1652
1653   if (!OPEN_CNUM(cnum))
1654     {
1655       last_cnum = -1;
1656       return(False);
1657     }
1658
1659   Connections[cnum].lastused = smb_last_time;
1660
1661   snum = SNUM(cnum);
1662   
1663   if (do_chdir &&
1664       ChDir(Connections[cnum].connectpath) != 0 &&
1665       ChDir(Connections[cnum].origpath) != 0)
1666     {
1667       DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1668             Connections[cnum].connectpath,cnum));     
1669       return(False);
1670     }
1671
1672   if (cnum == last_cnum)
1673     return(True);
1674
1675   last_cnum = cnum;
1676
1677   case_default = lp_defaultcase(snum);
1678   case_preserve = lp_preservecase(snum);
1679   short_case_preserve = lp_shortpreservecase(snum);
1680   case_mangle = lp_casemangle(snum);
1681   case_sensitive = lp_casesensitive(snum);
1682   magic_char = lp_magicchar(snum);
1683   use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1684   return(True);
1685 }
1686
1687
1688 /****************************************************************************
1689   find a service entry
1690 ****************************************************************************/
1691 int find_service(char *service)
1692 {
1693    int iService;
1694
1695    string_sub(service,"\\","/");
1696
1697    iService = lp_servicenumber(service);
1698
1699    /* now handle the special case of a home directory */
1700    if (iService < 0)
1701    {
1702       char *phome_dir = get_home_dir(service);
1703       DEBUG(3,("checking for home directory %s gave %s\n",service,
1704             phome_dir?phome_dir:"(NULL)"));
1705       if (phome_dir)
1706       {   
1707          int iHomeService;
1708          if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1709          {
1710             lp_add_home(service,iHomeService,phome_dir);
1711             iService = lp_servicenumber(service);
1712          }
1713       }
1714    }
1715
1716    /* If we still don't have a service, attempt to add it as a printer. */
1717    if (iService < 0)
1718    {
1719       int iPrinterService;
1720
1721       if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1722       {
1723          char *pszTemp;
1724
1725          DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1726          pszTemp = PRINTCAP;
1727          if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
1728          {
1729             DEBUG(3,("%s is a valid printer name\n", service));
1730             DEBUG(3,("adding %s as a printer service\n", service));
1731             lp_add_printer(service,iPrinterService);
1732             iService = lp_servicenumber(service);
1733             if (iService < 0)
1734                DEBUG(0,("failed to add %s as a printer service!\n", service));
1735          }
1736          else
1737             DEBUG(3,("%s is not a valid printer name\n", service));
1738       }
1739    }
1740
1741    /* just possibly it's a default service? */
1742    if (iService < 0) 
1743      {
1744        char *defservice = lp_defaultservice();
1745        if (defservice && *defservice && !strequal(defservice,service)) {
1746          iService = find_service(defservice);
1747          if (iService >= 0) {
1748            string_sub(service,"_","/");
1749            iService = lp_add_service(service,iService);
1750          }
1751        }
1752      }
1753
1754    if (iService >= 0)
1755       if (!VALID_SNUM(iService))
1756       {
1757          DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1758          iService = -1;
1759       }
1760
1761    if (iService < 0)
1762       DEBUG(3,("find_service() failed to find service %s\n", service));
1763
1764    return (iService);
1765 }
1766
1767
1768 /****************************************************************************
1769   create an error packet from a cached error.
1770 ****************************************************************************/
1771 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
1772 {
1773   write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
1774
1775   int32 eclass = wbmpx->wr_errclass;
1776   int32 err = wbmpx->wr_error;
1777
1778   /* We can now delete the auxiliary struct */
1779   free((char *)wbmpx);
1780   Files[fnum].wbmpx_ptr = NULL;
1781   return error_packet(inbuf,outbuf,eclass,err,line);
1782 }
1783
1784
1785 struct
1786 {
1787   int unixerror;
1788   int smbclass;
1789   int smbcode;
1790 } unix_smb_errmap[] =
1791 {
1792   {EPERM,ERRDOS,ERRnoaccess},
1793   {EACCES,ERRDOS,ERRnoaccess},
1794   {ENOENT,ERRDOS,ERRbadfile},
1795   {EIO,ERRHRD,ERRgeneral},
1796   {EBADF,ERRSRV,ERRsrverror},
1797   {EINVAL,ERRSRV,ERRsrverror},
1798   {EEXIST,ERRDOS,ERRfilexists},
1799   {ENFILE,ERRDOS,ERRnofids},
1800   {EMFILE,ERRDOS,ERRnofids},
1801   {ENOSPC,ERRHRD,ERRdiskfull},
1802 #ifdef EDQUOT
1803   {EDQUOT,ERRHRD,ERRdiskfull},
1804 #endif
1805 #ifdef ENOTEMPTY
1806   {ENOTEMPTY,ERRDOS,ERRnoaccess},
1807 #endif
1808 #ifdef EXDEV
1809   {EXDEV,ERRDOS,ERRdiffdevice},
1810 #endif
1811   {EROFS,ERRHRD,ERRnowrite},
1812   {0,0,0}
1813 };
1814
1815
1816 /****************************************************************************
1817   create an error packet from errno
1818 ****************************************************************************/
1819 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
1820 {
1821   int eclass=def_class;
1822   int ecode=def_code;
1823   int i=0;
1824
1825   if (unix_ERR_class != SUCCESS)
1826     {
1827       eclass = unix_ERR_class;
1828       ecode = unix_ERR_code;
1829       unix_ERR_class = SUCCESS;
1830       unix_ERR_code = 0;
1831     }
1832   else
1833     {
1834       while (unix_smb_errmap[i].smbclass != 0)
1835         {
1836           if (unix_smb_errmap[i].unixerror == errno)
1837             {
1838               eclass = unix_smb_errmap[i].smbclass;
1839               ecode = unix_smb_errmap[i].smbcode;
1840               break;
1841             }
1842           i++;
1843         }
1844     }
1845
1846   return(error_packet(inbuf,outbuf,eclass,ecode,line));
1847 }
1848
1849
1850 /****************************************************************************
1851   create an error packet. Normally called using the ERROR() macro
1852 ****************************************************************************/
1853 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
1854 {
1855   int outsize = set_message(outbuf,0,0,True);
1856   int cmd;
1857   cmd = CVAL(inbuf,smb_com);
1858   
1859   CVAL(outbuf,smb_rcls) = error_class;
1860   SSVAL(outbuf,smb_err,error_code);  
1861   
1862   DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
1863            timestring(),
1864            line,
1865            (int)CVAL(inbuf,smb_com),
1866            smb_fn_name(CVAL(inbuf,smb_com)),
1867            error_class,
1868            error_code));
1869
1870   if (errno != 0)
1871     DEBUG(3,("error string = %s\n",strerror(errno)));
1872   
1873   return(outsize);
1874 }
1875
1876
1877 #ifndef SIGCLD_IGNORE
1878 /****************************************************************************
1879 this prevents zombie child processes
1880 ****************************************************************************/
1881 static int sig_cld()
1882 {
1883   static int depth = 0;
1884   if (depth != 0)
1885     {
1886       DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
1887       depth=0;
1888       return(0);
1889     }
1890   depth++;
1891
1892   BlockSignals(True,SIGCLD);
1893   DEBUG(5,("got SIGCLD\n"));
1894
1895 #ifdef USE_WAITPID
1896   while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
1897 #endif
1898
1899   /* Stop zombies */
1900   /* Stevens, Adv. Unix Prog. says that on system V you must call
1901      wait before reinstalling the signal handler, because the kernel
1902      calls the handler from within the signal-call when there is a
1903      child that has exited. This would lead to an infinite recursion
1904      if done vice versa. */
1905         
1906 #ifndef DONT_REINSTALL_SIG
1907 #ifdef SIGCLD_IGNORE
1908   signal(SIGCLD, SIG_IGN);  
1909 #else
1910   signal(SIGCLD, SIGNAL_CAST sig_cld);
1911 #endif
1912 #endif
1913
1914 #ifndef USE_WAITPID
1915   while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
1916 #endif
1917   depth--;
1918   BlockSignals(False,SIGCLD);
1919   return 0;
1920 }
1921 #endif
1922
1923 /****************************************************************************
1924   this is called when the client exits abruptly
1925   **************************************************************************/
1926 static int sig_pipe()
1927 {
1928   extern int password_client;
1929   BlockSignals(True,SIGPIPE);
1930
1931   if (password_client != -1) {
1932     DEBUG(3,("lost connection to password server\n"));
1933     close(password_client);
1934     password_client = -1;
1935 #ifndef DONT_REINSTALL_SIG
1936     signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1937 #endif
1938     BlockSignals(False,SIGPIPE);
1939     return 0;
1940   }
1941
1942   exit_server("Got sigpipe\n");
1943   return(0);
1944 }
1945
1946 /****************************************************************************
1947   open the socket communication
1948 ****************************************************************************/
1949 static BOOL open_sockets(BOOL is_daemon,int port)
1950 {
1951   extern int Client;
1952
1953   if (is_daemon)
1954     {
1955       int s;
1956       struct sockaddr addr;
1957       int in_addrlen = sizeof(addr);
1958        
1959       /* Stop zombies */
1960 #ifdef SIGCLD_IGNORE
1961       signal(SIGCLD, SIG_IGN);
1962 #else
1963       signal(SIGCLD, SIGNAL_CAST sig_cld);
1964 #endif
1965
1966       /* open an incoming socket */
1967       s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
1968       if (s == -1)
1969         return(False);
1970
1971       /* ready to listen */
1972       if (listen(s, 5) == -1) 
1973         {
1974           DEBUG(0,("listen: %s",strerror(errno)));
1975           close(s);
1976           return False;
1977         }
1978       
1979       if(atexit_set == 0)
1980         atexit(killkids);
1981
1982       /* now accept incoming connections - forking a new process
1983          for each incoming connection */
1984       DEBUG(2,("waiting for a connection\n"));
1985       while (1)
1986         {
1987           Client = accept(s,&addr,&in_addrlen);
1988
1989           if (Client == -1 && errno == EINTR)
1990             continue;
1991
1992           if (Client == -1)
1993             {
1994               DEBUG(0,("accept: %s",strerror(errno)));
1995               continue;
1996             }
1997
1998 #ifdef NO_FORK_DEBUG
1999 #ifndef NO_SIGNAL_TEST
2000           signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2001           signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2002 #endif
2003           return True;
2004 #else
2005           if (Client != -1 && fork()==0)
2006             {
2007 #ifndef NO_SIGNAL_TEST
2008               signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2009               signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2010 #endif
2011               /* close the listening socket */
2012               close(s);
2013
2014               /* close our standard file descriptors */
2015               close_low_fds();
2016               am_parent = 0;
2017   
2018               set_socket_options(Client,"SO_KEEPALIVE");
2019               set_socket_options(Client,user_socket_options);
2020
2021               return True; 
2022             }
2023           close(Client); /* The parent doesn't need this socket */
2024 #endif
2025         }
2026     }
2027   else
2028     {
2029       /* We will abort gracefully when the client or remote system 
2030          goes away */
2031 #ifndef NO_SIGNAL_TEST
2032       signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2033 #endif
2034       Client = dup(0);
2035
2036       /* close our standard file descriptors */
2037       close_low_fds();
2038
2039       set_socket_options(Client,"SO_KEEPALIVE");
2040       set_socket_options(Client,user_socket_options);
2041     }
2042
2043   return True;
2044 }
2045
2046
2047 /****************************************************************************
2048 check if a snum is in use
2049 ****************************************************************************/
2050 BOOL snum_used(int snum)
2051 {
2052   int i;
2053   for (i=0;i<MAX_CONNECTIONS;i++)
2054     if (OPEN_CNUM(i) && (SNUM(i) == snum))
2055       return(True);
2056   return(False);
2057 }
2058
2059 /****************************************************************************
2060   reload the services file
2061   **************************************************************************/
2062 BOOL reload_services(BOOL test)
2063 {
2064   BOOL ret;
2065
2066   if (lp_loaded())
2067     {
2068       pstring fname;
2069       strcpy(fname,lp_configfile());
2070       if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
2071         {
2072           strcpy(servicesf,fname);
2073           test = False;
2074         }
2075     }
2076
2077   reopen_logs();
2078
2079   if (test && !lp_file_list_changed())
2080     return(True);
2081
2082   lp_killunused(snum_used);
2083
2084   ret = lp_load(servicesf,False);
2085
2086   /* perhaps the config filename is now set */
2087   if (!test)
2088     reload_services(True);
2089
2090   reopen_logs();
2091
2092   load_interfaces();
2093
2094   {
2095     extern int Client;
2096     if (Client != -1) {      
2097       set_socket_options(Client,"SO_KEEPALIVE");
2098       set_socket_options(Client,user_socket_options);
2099     }
2100   }
2101
2102   create_mangled_stack(lp_mangledstack());
2103
2104   /* this forces service parameters to be flushed */
2105   become_service(-1,True);
2106
2107   return(ret);
2108 }
2109
2110
2111
2112 /****************************************************************************
2113 this prevents zombie child processes
2114 ****************************************************************************/
2115 static int sig_hup()
2116 {
2117   BlockSignals(True,SIGHUP);
2118   DEBUG(0,("Got SIGHUP\n"));
2119   reload_services(False);
2120 #ifndef DONT_REINSTALL_SIG
2121   signal(SIGHUP,SIGNAL_CAST sig_hup);
2122 #endif
2123   BlockSignals(False,SIGHUP);
2124   return(0);
2125 }
2126
2127 /****************************************************************************
2128 Setup the groups a user belongs to.
2129 ****************************************************************************/
2130 int setup_groups(char *user, int uid, int gid, int *p_ngroups, 
2131                  int **p_igroups, gid_t **p_groups)
2132 {
2133   if (-1 == initgroups(user,gid))
2134     {
2135       if (getuid() == 0)
2136         {
2137           DEBUG(0,("Unable to initgroups!\n"));
2138           if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
2139             DEBUG(0,("This is probably a problem with the account %s\n",user));
2140         }
2141     }
2142   else
2143     {
2144       int i,ngroups;
2145       int *igroups;
2146       gid_t grp = 0;
2147       ngroups = getgroups(0,&grp);
2148       if (ngroups <= 0)
2149         ngroups = 32;
2150       igroups = (int *)malloc(sizeof(int)*ngroups);
2151       for (i=0;i<ngroups;i++)
2152         igroups[i] = 0x42424242;
2153       ngroups = getgroups(ngroups,(gid_t *)igroups);
2154
2155       if (igroups[0] == 0x42424242)
2156         ngroups = 0;
2157
2158       *p_ngroups = ngroups;
2159
2160       /* The following bit of code is very strange. It is due to the
2161          fact that some OSes use int* and some use gid_t* for
2162          getgroups, and some (like SunOS) use both, one in prototypes,
2163          and one in man pages and the actual code. Thus we detect it
2164          dynamically using some very ugly code */
2165       if (ngroups > 0)
2166         {
2167           /* does getgroups return ints or gid_t ?? */
2168           static BOOL groups_use_ints = True;
2169
2170           if (groups_use_ints && 
2171               ngroups == 1 && 
2172               SVAL(igroups,2) == 0x4242)
2173             groups_use_ints = False;
2174           
2175           for (i=0;groups_use_ints && i<ngroups;i++)
2176             if (igroups[i] == 0x42424242)
2177               groups_use_ints = False;
2178               
2179           if (groups_use_ints)
2180             {
2181               *p_igroups = igroups;
2182               *p_groups = (gid_t *)igroups;       
2183             }
2184           else
2185             {
2186               gid_t *groups = (gid_t *)igroups;
2187               igroups = (int *)malloc(sizeof(int)*ngroups);
2188               for (i=0;i<ngroups;i++)
2189                 igroups[i] = groups[i];
2190               *p_igroups = igroups;
2191               *p_groups = (gid_t *)groups;
2192             }
2193         }
2194       DEBUG(3,("%s is in %d groups\n",user,ngroups));
2195       for (i=0;i<ngroups;i++)
2196         DEBUG(3,("%d ",igroups[i]));
2197       DEBUG(3,("\n"));
2198     }
2199   return 0;
2200 }
2201
2202 /****************************************************************************
2203   make a connection to a service
2204 ****************************************************************************/
2205 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid)
2206 {
2207   int cnum;
2208   int snum;
2209   struct passwd *pass = NULL;
2210   connection_struct *pcon;
2211   BOOL guest = False;
2212   BOOL force = False;
2213   static BOOL first_connection = True;
2214
2215   strlower(service);
2216
2217   snum = find_service(service);
2218   if (snum < 0)
2219     {
2220       if (strequal(service,"IPC$"))
2221         {         
2222           DEBUG(3,("%s refusing IPC connection\n",timestring()));
2223           return(-3);
2224         }
2225
2226       DEBUG(0,("%s couldn't find service %s\n",timestring(),service));      
2227       return(-2);
2228     }
2229
2230   if (strequal(service,HOMES_NAME))
2231     {
2232       if (*user && Get_Pwnam(user,True))
2233         return(make_connection(user,user,password,pwlen,dev,vuid));
2234
2235       if (validated_username(vuid))
2236         {
2237           strcpy(user,validated_username(vuid));
2238           return(make_connection(user,user,password,pwlen,dev,vuid));
2239         }
2240     }
2241
2242   if (!lp_snum_ok(snum) || !check_access(snum)) {    
2243     return(-4);
2244   }
2245
2246   /* you can only connect to the IPC$ service as an ipc device */
2247   if (strequal(service,"IPC$"))
2248     strcpy(dev,"IPC");
2249
2250   if (*dev == '?' || !*dev)
2251     {
2252       if (lp_print_ok(snum))
2253         strcpy(dev,"LPT1:");
2254       else
2255         strcpy(dev,"A:");
2256     }
2257
2258   /* if the request is as a printer and you can't print then refuse */
2259   strupper(dev);
2260   if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
2261     DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
2262     return(-6);
2263   }
2264
2265   /* lowercase the user name */
2266   strlower(user);
2267
2268   /* add it as a possible user name */
2269   add_session_user(service);
2270
2271   /* shall we let them in? */
2272   if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
2273     {
2274       DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
2275       return(-1);
2276     }
2277   
2278   cnum = find_free_connection(str_checksum(service) + str_checksum(user));
2279   if (cnum < 0)
2280     {
2281       DEBUG(0,("%s couldn't find free connection\n",timestring()));      
2282       return(-1);
2283     }
2284
2285   pcon = &Connections[cnum];
2286   bzero((char *)pcon,sizeof(*pcon));
2287
2288   /* find out some info about the user */
2289   pass = Get_Pwnam(user,True);
2290
2291   if (pass == NULL)
2292     {
2293       DEBUG(0,("%s couldn't find account %s\n",timestring(),user)); 
2294       return(-7);
2295     }
2296
2297   pcon->read_only = lp_readonly(snum);
2298
2299   {
2300     pstring list;
2301     StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
2302     string_sub(list,"%S",service);
2303
2304     if (user_in_list(user,list))
2305       pcon->read_only = True;
2306
2307     StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
2308     string_sub(list,"%S",service);
2309
2310     if (user_in_list(user,list))
2311       pcon->read_only = False;    
2312   }
2313
2314   /* admin user check */
2315   if (user_in_list(user,lp_admin_users(snum)) &&
2316       !pcon->read_only)
2317     {
2318       pcon->admin_user = True;
2319       DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2320     }
2321   else
2322     pcon->admin_user = False;
2323     
2324   pcon->force_user = force;
2325   pcon->vuid = vuid;
2326   pcon->uid = pass->pw_uid;
2327   pcon->gid = pass->pw_gid;
2328   pcon->num_files_open = 0;
2329   pcon->lastused = time(NULL);
2330   pcon->service = snum;
2331   pcon->used = True;
2332   pcon->printer = (strncmp(dev,"LPT",3) == 0);
2333   pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2334   pcon->dirptr = NULL;
2335   string_set(&pcon->dirpath,"");
2336   string_set(&pcon->user,user);
2337
2338 #if HAVE_GETGRNAM 
2339   if (*lp_force_group(snum))
2340     {
2341       struct group *gptr;
2342       pstring gname;
2343
2344       StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1);
2345       /* default service may be a group name            */
2346       string_sub(gname,"%S",service);
2347       gptr = (struct group *)getgrnam(gname);
2348
2349       if (gptr)
2350         {
2351           pcon->gid = gptr->gr_gid;
2352           DEBUG(3,("Forced group %s\n",gname));
2353         }
2354       else
2355         DEBUG(1,("Couldn't find group %s\n",gname));
2356     }
2357 #endif
2358
2359   if (*lp_force_user(snum))
2360     {
2361       struct passwd *pass2;
2362       fstring fuser;
2363       strcpy(fuser,lp_force_user(snum));
2364       pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2365       if (pass2)
2366         {
2367           pcon->uid = pass2->pw_uid;
2368           string_set(&pcon->user,fuser);
2369           strcpy(user,fuser);
2370           pcon->force_user = True;
2371           DEBUG(3,("Forced user %s\n",fuser));    
2372         }
2373       else
2374         DEBUG(1,("Couldn't find user %s\n",fuser));
2375     }
2376
2377   {
2378     pstring s;
2379     strcpy(s,lp_pathname(snum));
2380     standard_sub(cnum,s);
2381     string_set(&pcon->connectpath,s);
2382     DEBUG(3,("Connect path is %s\n",s));
2383   }
2384
2385   /* groups stuff added by ih */
2386   pcon->ngroups = 0;
2387   pcon->groups = NULL;
2388
2389   if (!IS_IPC(cnum))
2390     {
2391       /* Find all the groups this uid is in and store them. Used by become_user() */
2392       setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2393       
2394       /* check number of connections */
2395       if (!claim_connection(cnum,
2396                             lp_servicename(SNUM(cnum)),
2397                             lp_max_connections(SNUM(cnum)),False))
2398         {
2399           DEBUG(1,("too many connections - rejected\n"));
2400           return(-8);
2401         }  
2402
2403       if (lp_status(SNUM(cnum)))
2404         claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2405
2406       first_connection = False;
2407     } /* IS_IPC */
2408
2409   pcon->open = True;
2410
2411   /* execute any "root preexec = " line */
2412   if (*lp_rootpreexec(SNUM(cnum)))
2413     {
2414       pstring cmd;
2415       strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2416       standard_sub(cnum,cmd);
2417       DEBUG(5,("cmd=%s\n",cmd));
2418       smbrun(cmd,NULL,False);
2419     }
2420
2421   if (!become_user(cnum,pcon->vuid))
2422     {
2423       DEBUG(0,("Can't become connected user!\n"));
2424       pcon->open = False;
2425       if (!IS_IPC(cnum)) {
2426         yield_connection(cnum,
2427                          lp_servicename(SNUM(cnum)),
2428                          lp_max_connections(SNUM(cnum)));
2429         if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2430       }
2431       return(-1);
2432     }
2433
2434   if (ChDir(pcon->connectpath) != 0)
2435     {
2436       DEBUG(0,("Can't change directory to %s (%s)\n",
2437                pcon->connectpath,strerror(errno)));
2438       pcon->open = False;
2439       unbecome_user();
2440       if (!IS_IPC(cnum)) {
2441         yield_connection(cnum,
2442                          lp_servicename(SNUM(cnum)),
2443                          lp_max_connections(SNUM(cnum)));
2444         if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2445       }
2446       return(-5);      
2447     }
2448
2449   string_set(&pcon->origpath,pcon->connectpath);
2450
2451 #if SOFTLINK_OPTIMISATION
2452   /* resolve any soft links early */
2453   {
2454     pstring s;
2455     strcpy(s,pcon->connectpath);
2456     GetWd(s);
2457     string_set(&pcon->connectpath,s);
2458     ChDir(pcon->connectpath);
2459   }
2460 #endif
2461
2462   num_connections_open++;
2463   add_session_user(user);
2464   
2465   /* execute any "preexec = " line */
2466   if (*lp_preexec(SNUM(cnum)))
2467     {
2468       pstring cmd;
2469       strcpy(cmd,lp_preexec(SNUM(cnum)));
2470       standard_sub(cnum,cmd);
2471       smbrun(cmd,NULL,False);
2472     }
2473   
2474   /* we've finished with the sensitive stuff */
2475   unbecome_user();
2476
2477   {
2478     DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2479                             timestring(),
2480                             remote_machine,
2481                             client_addr(),
2482                             lp_servicename(SNUM(cnum)),user,
2483                             pcon->uid,
2484                             pcon->gid,
2485                             (int)getpid()));
2486   }
2487
2488   return(cnum);
2489 }
2490
2491
2492 /****************************************************************************
2493   find first available file slot
2494 ****************************************************************************/
2495 int find_free_file(void )
2496 {
2497   int i;
2498   /* we start at 1 here for an obscure reason I can't now remember,
2499      but I think is important :-) */
2500   for (i=1;i<MAX_OPEN_FILES;i++)
2501     if (!Files[i].open)
2502       return(i);
2503   DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2504   return(-1);
2505 }
2506
2507 /****************************************************************************
2508   find first available connection slot, starting from a random position.
2509 The randomisation stops problems with the server dieing and clients
2510 thinking the server is still available.
2511 ****************************************************************************/
2512 static int find_free_connection(int hash )
2513 {
2514   int i;
2515   BOOL used=False;
2516   hash = (hash % (MAX_CONNECTIONS-2))+1;
2517
2518  again:
2519
2520   for (i=hash+1;i!=hash;)
2521     {
2522       if (!Connections[i].open && Connections[i].used == used) 
2523         {
2524           DEBUG(3,("found free connection number %d\n",i));
2525           return(i);
2526         }
2527       i++;
2528       if (i == MAX_CONNECTIONS)
2529         i = 1;
2530     }
2531
2532   if (!used)
2533     {
2534       used = !used;
2535       goto again;
2536     }
2537
2538   DEBUG(1,("ERROR! Out of connection structures\n"));
2539   return(-1);
2540 }
2541
2542
2543 /****************************************************************************
2544 reply for the core protocol
2545 ****************************************************************************/
2546 int reply_corep(char *outbuf)
2547 {
2548   int outsize = set_message(outbuf,1,0,True);
2549
2550   Protocol = PROTOCOL_CORE;
2551
2552   return outsize;
2553 }
2554
2555
2556 /****************************************************************************
2557 reply for the coreplus protocol
2558 ****************************************************************************/
2559 int reply_coreplus(char *outbuf)
2560 {
2561   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2562   int outsize = set_message(outbuf,13,0,True);
2563   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2564                                  readbraw and writebraw (possibly) */
2565   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2566   SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */  
2567
2568   Protocol = PROTOCOL_COREPLUS;
2569
2570   return outsize;
2571 }
2572
2573
2574 /****************************************************************************
2575 reply for the lanman 1.0 protocol
2576 ****************************************************************************/
2577 int reply_lanman1(char *outbuf)
2578 {
2579   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2580   int secword=0;
2581   BOOL doencrypt = SMBENCRYPT();
2582   time_t t = time(NULL);
2583
2584   if (lp_security()>=SEC_USER) secword |= 1;
2585   if (doencrypt) secword |= 2;
2586
2587   set_message(outbuf,13,doencrypt?8:0,True);
2588   SSVAL(outbuf,smb_vwv1,secword); 
2589 #ifdef SMB_PASSWD
2590   /* Create a token value and add it to the outgoing packet. */
2591   if (doencrypt) 
2592     generate_next_challenge(smb_buf(outbuf));
2593 #endif
2594
2595   Protocol = PROTOCOL_LANMAN1;
2596
2597   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2598     DEBUG(3,("using password server validation\n"));
2599 #ifdef SMB_PASSWD
2600   if (doencrypt) set_challenge(smb_buf(outbuf));    
2601 #endif
2602   }
2603
2604   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2605   SSVAL(outbuf,smb_vwv2,max_recv);
2606   SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2607   SSVAL(outbuf,smb_vwv4,1);
2608   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2609                                  readbraw writebraw (possibly) */
2610   SIVAL(outbuf,smb_vwv6,getpid());
2611   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2612
2613   put_dos_date(outbuf,smb_vwv8,t);
2614
2615   return (smb_len(outbuf)+4);
2616 }
2617
2618
2619 /****************************************************************************
2620 reply for the lanman 2.0 protocol
2621 ****************************************************************************/
2622 int reply_lanman2(char *outbuf)
2623 {
2624   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2625   int secword=0;
2626   BOOL doencrypt = SMBENCRYPT();
2627   time_t t = time(NULL);
2628
2629   if (lp_security()>=SEC_USER) secword |= 1;
2630   if (doencrypt) secword |= 2;
2631
2632   set_message(outbuf,13,doencrypt?8:0,True);
2633   SSVAL(outbuf,smb_vwv1,secword); 
2634 #ifdef SMB_PASSWD
2635   /* Create a token value and add it to the outgoing packet. */
2636   if (doencrypt) 
2637     generate_next_challenge(smb_buf(outbuf));
2638 #endif
2639
2640   SIVAL(outbuf,smb_vwv6,getpid());
2641
2642   Protocol = PROTOCOL_LANMAN2;
2643
2644   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2645     DEBUG(3,("using password server validation\n"));
2646 #ifdef SMB_PASSWD
2647     if (doencrypt) set_challenge(smb_buf(outbuf));    
2648 #endif
2649   }
2650
2651   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2652   SSVAL(outbuf,smb_vwv2,max_recv);
2653   SSVAL(outbuf,smb_vwv3,lp_maxmux()); 
2654   SSVAL(outbuf,smb_vwv4,1);
2655   SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2656   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2657   put_dos_date(outbuf,smb_vwv8,t);
2658
2659   return (smb_len(outbuf)+4);
2660 }
2661
2662
2663 /****************************************************************************
2664 reply for the nt protocol
2665 ****************************************************************************/
2666 int reply_nt1(char *outbuf)
2667 {
2668   /* dual names + lock_and_read + nt SMBs + remote API calls */
2669   int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ;
2670 /*
2671   other valid capabilities which we may support at some time...
2672                      CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
2673                      CAP_LARGE_FILES|CAP_LARGE_READX|
2674                      CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
2675  */
2676
2677   int secword=0;
2678   BOOL doencrypt = SMBENCRYPT();
2679   time_t t = time(NULL);
2680   int data_len;
2681   int encrypt_len;
2682   char challenge_len = 8;
2683
2684   if (lp_readraw() && lp_writeraw())
2685   {
2686     capabilities |= CAP_RAW_MODE;
2687   }
2688
2689   if (lp_security()>=SEC_USER) secword |= 1;
2690   if (doencrypt) secword |= 2;
2691
2692   /* decide where (if) to put the encryption challenge, and
2693      follow it with the OEM'd domain name
2694    */
2695   encrypt_len = doencrypt?challenge_len:0;
2696 #if UNICODE
2697   data_len = encrypt_len + 2*(strlen(lp_workgroup())+1);
2698 #else
2699   data_len = encrypt_len + strlen(lp_workgroup()) + 1;
2700 #endif
2701
2702   set_message(outbuf,17,data_len,True);
2703
2704 #if UNICODE
2705   /* put the OEM'd domain name */
2706   PutUniCode(smb_buf(outbuf)+encrypt_len,lp_workgroup());
2707 #else
2708   strcpy(smb_buf(outbuf)+encrypt_len, lp_workgroup());
2709 #endif
2710
2711   CVAL(outbuf,smb_vwv1) = secword;
2712 #ifdef SMB_PASSWD
2713   /* Create a token value and add it to the outgoing packet. */
2714   if (doencrypt)
2715   {
2716     generate_next_challenge(smb_buf(outbuf));
2717
2718     /* Tell the nt machine how long the challenge is. */
2719     SSVALS(outbuf,smb_vwv16+1,challenge_len);
2720   }
2721 #endif
2722
2723   Protocol = PROTOCOL_NT1;
2724
2725   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2726     DEBUG(3,("using password server validation\n"));
2727 #ifdef SMB_PASSWD
2728     if (doencrypt) set_challenge(smb_buf(outbuf));    
2729 #endif
2730   }
2731
2732   SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2733   SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2734   SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
2735   SIVAL(outbuf,smb_vwv5+1,0xffff); /* raw size. LOTS! */
2736   SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2737   SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2738   put_long_date(outbuf+smb_vwv11+1,t);
2739   SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
2740   SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */
2741
2742   return (smb_len(outbuf)+4);
2743 }
2744
2745 /* these are the protocol lists used for auto architecture detection:
2746
2747 WinNT 3.51:
2748 protocol [PC NETWORK PROGRAM 1.0]
2749 protocol [XENIX CORE]
2750 protocol [MICROSOFT NETWORKS 1.03]
2751 protocol [LANMAN1.0]
2752 protocol [Windows for Workgroups 3.1a]
2753 protocol [LM1.2X002]
2754 protocol [LANMAN2.1]
2755 protocol [NT LM 0.12]
2756
2757 Win95:
2758 protocol [PC NETWORK PROGRAM 1.0]
2759 protocol [XENIX CORE]
2760 protocol [MICROSOFT NETWORKS 1.03]
2761 protocol [LANMAN1.0]
2762 protocol [Windows for Workgroups 3.1a]
2763 protocol [LM1.2X002]
2764 protocol [LANMAN2.1]
2765 protocol [NT LM 0.12]
2766
2767 OS/2:
2768 protocol [PC NETWORK PROGRAM 1.0]
2769 protocol [XENIX CORE]
2770 protocol [LANMAN1.0]
2771 protocol [LM1.2X002]
2772 protocol [LANMAN2.1]
2773 */
2774
2775 /*
2776   * Modified to recognize the architecture of the remote machine better.
2777   *
2778   * This appears to be the matrix of which protocol is used by which
2779   * MS product.
2780        Protocol                       WfWg    Win95   WinNT  OS/2
2781        PC NETWORK PROGRAM 1.0          1       1       1      1
2782        XENIX CORE                                      2      2
2783        MICROSOFT NETWORKS 3.0          2       2       
2784        DOS LM1.2X002                   3       3       
2785        MICROSOFT NETWORKS 1.03                         3
2786        DOS LANMAN2.1                   4       4       
2787        LANMAN1.0                                       4      3
2788        Windows for Workgroups 3.1a     5       5       5
2789        LM1.2X002                                       6      4
2790        LANMAN2.1                                       7      5
2791        NT LM 0.12                              6       8
2792   *
2793   *  tim@fsg.com 09/29/95
2794   */
2795   
2796 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
2797 #define ARCH_WIN95    0x2
2798 #define ARCH_OS2      0xC      /* Again OS/2 is like NT */
2799 #define ARCH_WINNT    0x8
2800 #define ARCH_SAMBA    0x10
2801  
2802 #define ARCH_ALL      0x1F
2803  
2804 /* List of supported protocols, most desired first */
2805 struct {
2806   char *proto_name;
2807   char *short_name;
2808   int (*proto_reply_fn)(char *);
2809   int protocol_level;
2810 } supported_protocols[] = {
2811   {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
2812   {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
2813   {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
2814   {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
2815   {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
2816   {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
2817   {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
2818   {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
2819   {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
2820   {NULL,NULL},
2821 };
2822
2823
2824 /****************************************************************************
2825   reply to a negprot
2826 ****************************************************************************/
2827 static int reply_negprot(char *inbuf,char *outbuf)
2828 {
2829   extern fstring remote_arch;
2830   int outsize = set_message(outbuf,1,0,True);
2831   int Index=0;
2832   int choice= -1;
2833   int protocol;
2834   char *p;
2835   int bcc = SVAL(smb_buf(inbuf),-2);
2836   int arch = ARCH_ALL;
2837
2838   p = smb_buf(inbuf)+1;
2839   while (p < (smb_buf(inbuf) + bcc))
2840     { 
2841       Index++;
2842       DEBUG(3,("Requested protocol [%s]\n",p));
2843       if (strcsequal(p,"Windows for Workgroups 3.1a"))
2844         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
2845       else if (strcsequal(p,"DOS LM1.2X002"))
2846         arch &= ( ARCH_WFWG | ARCH_WIN95 );
2847       else if (strcsequal(p,"DOS LANMAN2.1"))
2848         arch &= ( ARCH_WFWG | ARCH_WIN95 );
2849       else if (strcsequal(p,"NT LM 0.12"))
2850         arch &= ( ARCH_WIN95 | ARCH_WINNT );
2851       else if (strcsequal(p,"LANMAN2.1"))
2852         arch &= ( ARCH_WINNT | ARCH_OS2 );
2853       else if (strcsequal(p,"LM1.2X002"))
2854         arch &= ( ARCH_WINNT | ARCH_OS2 );
2855       else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
2856         arch &= ARCH_WINNT;
2857       else if (strcsequal(p,"XENIX CORE"))
2858         arch &= ( ARCH_WINNT | ARCH_OS2 );
2859       else if (strcsequal(p,"Samba")) {
2860         arch = ARCH_SAMBA;
2861         break;
2862       }
2863  
2864       p += strlen(p) + 2;
2865     }
2866     
2867   switch ( arch ) {
2868   case ARCH_SAMBA:
2869     strcpy(remote_arch,"Samba");
2870     break;
2871   case ARCH_WFWG:
2872     strcpy(remote_arch,"WfWg");
2873     break;
2874   case ARCH_WIN95:
2875     strcpy(remote_arch,"Win95");
2876     break;
2877   case ARCH_WINNT:
2878     strcpy(remote_arch,"WinNT");
2879     break;
2880   case ARCH_OS2:
2881     strcpy(remote_arch,"OS2");
2882     break;
2883   default:
2884     strcpy(remote_arch,"UNKNOWN");
2885     break;
2886   }
2887  
2888   /* possibly reload - change of architecture */
2889   reload_services(True);      
2890     
2891   /* a special case to stop password server loops */
2892   if (Index == 1 && strequal(remote_machine,myhostname) && 
2893       lp_security()==SEC_SERVER)
2894     exit_server("Password server loop!");
2895   
2896   /* Check for protocols, most desirable first */
2897   for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
2898     {
2899       p = smb_buf(inbuf)+1;
2900       Index = 0;
2901       if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
2902         while (p < (smb_buf(inbuf) + bcc))
2903           { 
2904             if (strequal(p,supported_protocols[protocol].proto_name))
2905               choice = Index;
2906             Index++;
2907             p += strlen(p) + 2;
2908           }
2909       if(choice != -1)
2910         break;
2911     }
2912   
2913   SSVAL(outbuf,smb_vwv0,choice);
2914   if(choice != -1) {
2915     extern fstring remote_proto;
2916     strcpy(remote_proto,supported_protocols[protocol].short_name);
2917     reload_services(True);          
2918     outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
2919     DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
2920   }
2921   else {
2922     DEBUG(0,("No protocol supported !\n"));
2923   }
2924   SSVAL(outbuf,smb_vwv0,choice);
2925   
2926   DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
2927
2928   return(outsize);
2929 }
2930
2931
2932 /****************************************************************************
2933 close all open files for a connection
2934 ****************************************************************************/
2935 static void close_open_files(int cnum)
2936 {
2937   int i;
2938   for (i=0;i<MAX_OPEN_FILES;i++)
2939     if( Files[i].cnum == cnum && Files[i].open) {
2940       close_file(i);
2941     }
2942 }
2943
2944
2945
2946 /****************************************************************************
2947 close a cnum
2948 ****************************************************************************/
2949 void close_cnum(int cnum, uint16 vuid)
2950 {
2951   DirCacheFlush(SNUM(cnum));
2952
2953   unbecome_user();
2954
2955   if (!OPEN_CNUM(cnum))
2956     {
2957       DEBUG(0,("Can't close cnum %d\n",cnum));
2958       return;
2959     }
2960
2961   DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
2962                           timestring(),
2963                           remote_machine,client_addr(),
2964                           lp_servicename(SNUM(cnum))));
2965
2966   yield_connection(cnum,
2967                    lp_servicename(SNUM(cnum)),
2968                    lp_max_connections(SNUM(cnum)));
2969
2970   if (lp_status(SNUM(cnum)))
2971     yield_connection(cnum,"STATUS.",MAXSTATUS);
2972
2973   close_open_files(cnum);
2974   dptr_closecnum(cnum);
2975
2976   /* execute any "postexec = " line */
2977   if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid))
2978     {
2979       pstring cmd;
2980       strcpy(cmd,lp_postexec(SNUM(cnum)));
2981       standard_sub(cnum,cmd);
2982       smbrun(cmd,NULL,False);
2983       unbecome_user();
2984     }
2985
2986   unbecome_user();
2987   /* execute any "root postexec = " line */
2988   if (*lp_rootpostexec(SNUM(cnum)))
2989     {
2990       pstring cmd;
2991       strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
2992       standard_sub(cnum,cmd);
2993       smbrun(cmd,NULL,False);
2994     }
2995
2996   Connections[cnum].open = False;
2997   num_connections_open--;
2998   if (Connections[cnum].ngroups && Connections[cnum].groups)
2999     {
3000       if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
3001         free(Connections[cnum].groups);
3002       free(Connections[cnum].igroups);
3003       Connections[cnum].groups = NULL;
3004       Connections[cnum].igroups = NULL;
3005       Connections[cnum].ngroups = 0;
3006     }
3007
3008   string_set(&Connections[cnum].user,"");
3009   string_set(&Connections[cnum].dirpath,"");
3010   string_set(&Connections[cnum].connectpath,"");
3011 }
3012
3013
3014 /****************************************************************************
3015 simple routines to do connection counting
3016 ****************************************************************************/
3017 BOOL yield_connection(int cnum,char *name,int max_connections)
3018 {
3019   struct connect_record crec;
3020   pstring fname;
3021   FILE *f;
3022   int mypid = getpid();
3023   int i;
3024
3025   DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
3026
3027   if (max_connections <= 0)
3028     return(True);
3029
3030   bzero(&crec,sizeof(crec));
3031
3032   strcpy(fname,lp_lockdir());
3033   standard_sub(cnum,fname);
3034   trim_string(fname,"","/");
3035
3036   strcat(fname,"/");
3037   strcat(fname,name);
3038   strcat(fname,".LCK");
3039
3040   f = fopen(fname,"r+");
3041   if (!f)
3042     {
3043       DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
3044       return(False);
3045     }
3046
3047   fseek(f,0,SEEK_SET);
3048
3049   /* find a free spot */
3050   for (i=0;i<max_connections;i++)
3051     {
3052       if (fread(&crec,sizeof(crec),1,f) != 1)
3053         {
3054           DEBUG(2,("Entry not found in lock file %s\n",fname));
3055           fclose(f);
3056           return(False);
3057         }
3058       if (crec.pid == mypid && crec.cnum == cnum)
3059         break;
3060     }
3061
3062   if (crec.pid != mypid || crec.cnum != cnum)
3063     {
3064       fclose(f);
3065       DEBUG(2,("Entry not found in lock file %s\n",fname));
3066       return(False);
3067     }
3068
3069   bzero((void *)&crec,sizeof(crec));
3070   
3071   /* remove our mark */
3072   if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3073       fwrite(&crec,sizeof(crec),1,f) != 1)
3074     {
3075       DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
3076       fclose(f);
3077       return(False);
3078     }
3079
3080   DEBUG(3,("Yield successful\n"));
3081
3082   fclose(f);
3083   return(True);
3084 }
3085
3086
3087 /****************************************************************************
3088 simple routines to do connection counting
3089 ****************************************************************************/
3090 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
3091 {
3092   struct connect_record crec;
3093   pstring fname;
3094   FILE *f;
3095   int snum = SNUM(cnum);
3096   int i,foundi= -1;
3097   int total_recs;
3098
3099   if (max_connections <= 0)
3100     return(True);
3101
3102   DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
3103
3104   strcpy(fname,lp_lockdir());
3105   standard_sub(cnum,fname);
3106   trim_string(fname,"","/");
3107
3108   if (!directory_exist(fname,NULL))
3109     mkdir(fname,0755);
3110
3111   strcat(fname,"/");
3112   strcat(fname,name);
3113   strcat(fname,".LCK");
3114
3115   if (!file_exist(fname,NULL))
3116     {
3117       int oldmask = umask(022);
3118       f = fopen(fname,"w");
3119       if (f) fclose(f);
3120       umask(oldmask);
3121     }
3122
3123   total_recs = file_size(fname) / sizeof(crec);
3124
3125   f = fopen(fname,"r+");
3126
3127   if (!f)
3128     {
3129       DEBUG(1,("couldn't open lock file %s\n",fname));
3130       return(False);
3131     }
3132
3133   /* find a free spot */
3134   for (i=0;i<max_connections;i++)
3135     {
3136
3137       if (i>=total_recs || 
3138           fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3139           fread(&crec,sizeof(crec),1,f) != 1)
3140         {
3141           if (foundi < 0) foundi = i;
3142           break;
3143         }
3144
3145       if (Clear && crec.pid && !process_exists(crec.pid))
3146         {
3147           fseek(f,i*sizeof(crec),SEEK_SET);
3148           bzero((void *)&crec,sizeof(crec));
3149           fwrite(&crec,sizeof(crec),1,f);
3150           if (foundi < 0) foundi = i;
3151           continue;
3152         }
3153       if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
3154         {
3155           foundi=i;
3156           if (!Clear) break;
3157         }
3158     }  
3159
3160   if (foundi < 0)
3161     {
3162       DEBUG(3,("no free locks in %s\n",fname));
3163       fclose(f);
3164       return(False);
3165     }      
3166
3167   /* fill in the crec */
3168   bzero((void *)&crec,sizeof(crec));
3169   crec.magic = 0x280267;
3170   crec.pid = getpid();
3171   crec.cnum = cnum;
3172   crec.uid = Connections[cnum].uid;
3173   crec.gid = Connections[cnum].gid;
3174   StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
3175   crec.start = time(NULL);
3176
3177   StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
3178   StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1);
3179   
3180   /* make our mark */
3181   if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
3182       fwrite(&crec,sizeof(crec),1,f) != 1)
3183     {
3184       fclose(f);
3185       return(False);
3186     }
3187
3188   fclose(f);
3189   return(True);
3190 }
3191
3192 #if DUMP_CORE
3193 /*******************************************************************
3194 prepare to dump a core file - carefully!
3195 ********************************************************************/
3196 static BOOL dump_core(void)
3197 {
3198   char *p;
3199   pstring dname;
3200   strcpy(dname,debugf);
3201   if ((p=strrchr(dname,'/'))) *p=0;
3202   strcat(dname,"/corefiles");
3203   mkdir(dname,0700);
3204   sys_chown(dname,getuid(),getgid());
3205   chmod(dname,0700);
3206   if (chdir(dname)) return(False);
3207   umask(~(0700));
3208
3209 #ifndef NO_GETRLIMIT
3210 #ifdef RLIMIT_CORE
3211   {
3212     struct rlimit rlp;
3213     getrlimit(RLIMIT_CORE, &rlp);
3214     rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
3215     setrlimit(RLIMIT_CORE, &rlp);
3216     getrlimit(RLIMIT_CORE, &rlp);
3217     DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
3218   }
3219 #endif
3220 #endif
3221
3222
3223   DEBUG(0,("Dumping core in %s\n",dname));
3224   return(True);
3225 }
3226 #endif
3227
3228 /****************************************************************************
3229 exit the server
3230 ****************************************************************************/
3231 void exit_server(char *reason)
3232 {
3233   static int firsttime=1;
3234   int i;
3235
3236   if (!firsttime) exit(0);
3237   firsttime = 0;
3238
3239   unbecome_user();
3240   DEBUG(2,("Closing connections\n"));
3241   for (i=0;i<MAX_CONNECTIONS;i++)
3242     if (Connections[i].open)
3243       close_cnum(i,-1);
3244 #ifdef DFS_AUTH
3245   if (dcelogin_atmost_once)
3246     dfs_unlogin();
3247 #endif
3248   if (!reason) {   
3249     int oldlevel = DEBUGLEVEL;
3250     DEBUGLEVEL = 10;
3251     DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
3252     if (last_inbuf)
3253       show_msg(last_inbuf);
3254     DEBUGLEVEL = oldlevel;
3255     DEBUG(0,("===============================================================\n"));
3256 #if DUMP_CORE
3257     if (dump_core()) return;
3258 #endif
3259   }    
3260
3261 #if FAST_SHARE_MODES
3262   stop_share_mode_mgmt();
3263 #endif
3264
3265   DEBUG(3,("%s Server exit  (%s)\n",timestring(),reason?reason:""));
3266   exit(0);
3267 }
3268
3269 /****************************************************************************
3270 do some standard substitutions in a string
3271 ****************************************************************************/
3272 void standard_sub(int cnum,char *s)
3273 {
3274   if (!strchr(s,'%')) return;
3275
3276   if (VALID_CNUM(cnum))
3277     {
3278       string_sub(s,"%S",lp_servicename(Connections[cnum].service));
3279       string_sub(s,"%P",Connections[cnum].connectpath);
3280       string_sub(s,"%u",Connections[cnum].user);
3281       if (strstr(s,"%H")) {
3282         char *home = get_home_dir(Connections[cnum].user);
3283         if (home) string_sub(s,"%H",home);
3284       }
3285       string_sub(s,"%g",gidtoname(Connections[cnum].gid));
3286     }
3287   standard_sub_basic(s);
3288 }
3289
3290 /*
3291 These flags determine some of the permissions required to do an operation 
3292
3293 Note that I don't set NEED_WRITE on some write operations because they
3294 are used by some brain-dead clients when printing, and I don't want to
3295 force write permissions on print services.
3296 */
3297 #define AS_USER (1<<0)
3298 #define NEED_WRITE (1<<1)
3299 #define TIME_INIT (1<<2)
3300 #define CAN_IPC (1<<3)
3301 #define AS_GUEST (1<<5)
3302
3303
3304 /* 
3305    define a list of possible SMB messages and their corresponding
3306    functions. Any message that has a NULL function is unimplemented -
3307    please feel free to contribute implementations!
3308 */
3309 struct smb_message_struct
3310 {
3311   int code;
3312   char *name;
3313   int (*fn)();
3314   int flags;
3315 #if PROFILING
3316   unsigned long time;
3317 #endif
3318 }
3319  smb_messages[] = {
3320
3321     /* CORE PROTOCOL */
3322
3323    {SMBnegprot,"SMBnegprot",reply_negprot,0},
3324    {SMBtcon,"SMBtcon",reply_tcon,0},
3325    {SMBtdis,"SMBtdis",reply_tdis,0},
3326    {SMBexit,"SMBexit",reply_exit,0},
3327    {SMBioctl,"SMBioctl",reply_ioctl,0},
3328    {SMBecho,"SMBecho",reply_echo,0},
3329    {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
3330    {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
3331    {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
3332    {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3333    {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3334    {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3335    {SMBsearch,"SMBsearch",reply_search,AS_USER},
3336    {SMBopen,"SMBopen",reply_open,AS_USER},
3337
3338    /* note that SMBmknew and SMBcreate are deliberately overloaded */   
3339    {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3340    {SMBmknew,"SMBmknew",reply_mknew,AS_USER}, 
3341
3342    {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3343    {SMBread,"SMBread",reply_read,AS_USER},
3344    {SMBwrite,"SMBwrite",reply_write,AS_USER},
3345    {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
3346    {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3347    {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3348    {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3349    {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3350
3351    /* this is a Pathworks specific call, allowing the 
3352       changing of the root path */
3353    {pSETDIR,"pSETDIR",reply_setdir,AS_USER}, 
3354
3355    {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3356    {SMBflush,"SMBflush",reply_flush,AS_USER},
3357    {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3358    {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3359    {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3360    {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST},
3361    {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3362    {SMBlock,"SMBlock",reply_lock,AS_USER},
3363    {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3364    
3365    /* CORE+ PROTOCOL FOLLOWS */
3366    
3367    {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3368    {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3369    {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3370    {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3371    {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3372    
3373    /* LANMAN1.0 PROTOCOL FOLLOWS */
3374    
3375    {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3376    {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3377    {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3378    {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3379    {SMBwritec,"SMBwritec",NULL,AS_USER},
3380    {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3381    {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3382    {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3383    {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3384    {SMBioctls,"SMBioctls",NULL,AS_USER},
3385    {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3386    {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3387    
3388    {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC},
3389    {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3390    {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3391    {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3392    
3393    {SMBffirst,"SMBffirst",reply_search,AS_USER},
3394    {SMBfunique,"SMBfunique",reply_search,AS_USER},
3395    {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3396
3397    /* LANMAN2.0 PROTOCOL FOLLOWS */
3398    {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3399    {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3400    {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3401    {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3402
3403    /* messaging routines */
3404    {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3405    {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3406    {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3407    {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3408
3409    /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3410    
3411    {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3412    {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3413    {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3414    {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3415  };
3416
3417 /****************************************************************************
3418 return a string containing the function name of a SMB command
3419 ****************************************************************************/
3420 char *smb_fn_name(int type)
3421 {
3422   static char *unknown_name = "SMBunknown";
3423   static int num_smb_messages = 
3424     sizeof(smb_messages) / sizeof(struct smb_message_struct);
3425   int match;
3426
3427   for (match=0;match<num_smb_messages;match++)
3428     if (smb_messages[match].code == type)
3429       break;
3430
3431   if (match == num_smb_messages)
3432     return(unknown_name);
3433
3434   return(smb_messages[match].name);
3435 }
3436
3437
3438 /****************************************************************************
3439 do a switch on the message type, and return the response size
3440 ****************************************************************************/
3441 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3442 {
3443   static int pid= -1;
3444   int outsize = 0;
3445   static int num_smb_messages = 
3446     sizeof(smb_messages) / sizeof(struct smb_message_struct);
3447   int match;
3448
3449 #if PROFILING
3450   struct timeval msg_start_time;
3451   struct timeval msg_end_time;
3452   static unsigned long total_time = 0;
3453
3454   GetTimeOfDay(&msg_start_time);
3455 #endif
3456
3457   if (pid == -1)
3458     pid = getpid();
3459
3460   errno = 0;
3461   last_message = type;
3462
3463   /* make sure this is an SMB packet */
3464   if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3465     {
3466       DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3467       return(-1);
3468     }
3469
3470   for (match=0;match<num_smb_messages;match++)
3471     if (smb_messages[match].code == type)
3472       break;
3473
3474   if (match == num_smb_messages)
3475     {
3476       DEBUG(0,("Unknown message type %d!\n",type));
3477       outsize = reply_unknown(inbuf,outbuf);
3478     }
3479   else
3480     {
3481       DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3482       if (smb_messages[match].fn)
3483         {
3484           int cnum = SVAL(inbuf,smb_tid);
3485           int flags = smb_messages[match].flags;
3486           uint16 session_tag = SVAL(inbuf,smb_uid);
3487
3488           /* does this protocol need to be run as root? */
3489           if (!(flags & AS_USER))
3490             unbecome_user();
3491
3492           /* does this protocol need to be run as the connected user? */
3493           if ((flags & AS_USER) && !become_user(cnum,session_tag)) {
3494             if (flags & AS_GUEST) 
3495               flags &= ~AS_USER;
3496             else
3497               return(ERROR(ERRSRV,ERRinvnid));
3498           }
3499           /* this code is to work around a bug is MS client 3 without
3500              introducing a security hole - it needs to be able to do
3501              print queue checks as guest if it isn't logged in properly */
3502           if (flags & AS_USER)
3503             flags &= ~AS_GUEST;
3504
3505           /* does it need write permission? */
3506           if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3507             return(ERROR(ERRSRV,ERRaccess));
3508
3509           /* ipc services are limited */
3510           if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3511             return(ERROR(ERRSRV,ERRaccess));        
3512
3513           /* load service specific parameters */
3514           if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3515             return(ERROR(ERRSRV,ERRaccess));
3516
3517           /* does this protocol need to be run as guest? */
3518           if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3519             return(ERROR(ERRSRV,ERRaccess));
3520
3521           last_inbuf = inbuf;
3522
3523           outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3524         }
3525       else
3526         {
3527           outsize = reply_unknown(inbuf,outbuf);
3528         }
3529     }
3530
3531 #if PROFILING
3532   GetTimeOfDay(&msg_end_time);
3533   if (!(smb_messages[match].flags & TIME_INIT))
3534     {
3535       smb_messages[match].time = 0;
3536       smb_messages[match].flags |= TIME_INIT;
3537     }
3538   {
3539     unsigned long this_time =     
3540       (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3541         (msg_end_time.tv_usec - msg_start_time.tv_usec);
3542     smb_messages[match].time += this_time;
3543     total_time += this_time;
3544   }
3545   DEBUG(2,("TIME %s  %d usecs   %g pct\n",
3546            smb_fn_name(type),smb_messages[match].time,
3547         (100.0*smb_messages[match].time) / total_time));
3548 #endif
3549
3550   return(outsize);
3551 }
3552
3553
3554 /****************************************************************************
3555   construct a chained reply and add it to the already made reply
3556   **************************************************************************/
3557 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
3558 {
3559   static char *orig_inbuf;
3560   static char *orig_outbuf;
3561   int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
3562   unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
3563   char *inbuf2, *outbuf2;
3564   int outsize2;
3565   char inbuf_saved[smb_wct];
3566   char outbuf_saved[smb_wct];
3567   extern int chain_size;
3568   int wct = CVAL(outbuf,smb_wct);
3569   int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
3570
3571   /* maybe its not chained */
3572   if (smb_com2 == 0xFF) {
3573     CVAL(outbuf,smb_vwv0) = 0xFF;
3574     return outsize;
3575   }
3576
3577   if (chain_size == 0) {
3578     /* this is the first part of the chain */
3579     orig_inbuf = inbuf;
3580     orig_outbuf = outbuf;
3581   }
3582
3583   /* we need to tell the client where the next part of the reply will be */
3584   SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
3585   CVAL(outbuf,smb_vwv0) = smb_com2;
3586
3587   /* remember how much the caller added to the chain, only counting stuff
3588      after the parameter words */
3589   chain_size += outsize - smb_wct;
3590
3591   /* work out pointers into the original packets. The
3592      headers on these need to be filled in */
3593   inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
3594   outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
3595
3596   /* remember the original command type */
3597   smb_com1 = CVAL(orig_inbuf,smb_com);
3598
3599   /* save the data which will be overwritten by the new headers */
3600   memcpy(inbuf_saved,inbuf2,smb_wct);
3601   memcpy(outbuf_saved,outbuf2,smb_wct);
3602
3603   /* give the new packet the same header as the last part of the SMB */
3604   memmove(inbuf2,inbuf,smb_wct);
3605
3606   /* create the in buffer */
3607   CVAL(inbuf2,smb_com) = smb_com2;
3608
3609   /* create the out buffer */
3610   bzero(outbuf2,smb_size);
3611   set_message(outbuf2,0,0,True);
3612   CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com);
3613   
3614   memcpy(outbuf2+4,inbuf2+4,4);
3615   CVAL(outbuf2,smb_rcls) = SUCCESS;
3616   CVAL(outbuf2,smb_reh) = 0;
3617   CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set 
3618                                                                   means a reply */
3619   SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */
3620   SSVAL(outbuf2,smb_err,SUCCESS);
3621   SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid));
3622   SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid));
3623   SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid));
3624   SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid));
3625
3626   DEBUG(3,("Chained message\n"));
3627   show_msg(inbuf2);
3628
3629   /* process the request */
3630   outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
3631                             bufsize-chain_size);
3632
3633   /* copy the new reply and request headers over the old ones, but
3634      preserve the smb_com field */
3635   memmove(orig_outbuf,outbuf2,smb_wct);
3636   CVAL(orig_outbuf,smb_com) = smb_com1;
3637
3638   /* restore the saved data, being careful not to overwrite any
3639    data from the reply header */
3640   memcpy(inbuf2,inbuf_saved,smb_wct);
3641   {
3642     int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
3643     if (ofs < 0) ofs = 0;
3644     memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
3645   }
3646
3647   return outsize2;
3648 }
3649
3650
3651
3652 /****************************************************************************
3653   construct a reply to the incoming packet
3654 ****************************************************************************/
3655 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3656 {
3657   int type = CVAL(inbuf,smb_com);
3658   int outsize = 0;
3659   int msg_type = CVAL(inbuf,0);
3660   extern int chain_size;
3661
3662   smb_last_time = time(NULL);
3663
3664   chain_size = 0;
3665   chain_fnum = -1;
3666
3667   bzero(outbuf,smb_size);
3668
3669   if (msg_type != 0)
3670     return(reply_special(inbuf,outbuf));  
3671
3672   CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3673   set_message(outbuf,0,0,True);
3674   
3675   memcpy(outbuf+4,inbuf+4,4);
3676   CVAL(outbuf,smb_rcls) = SUCCESS;
3677   CVAL(outbuf,smb_reh) = 0;
3678   CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set 
3679                                                              means a reply */
3680   SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3681   SSVAL(outbuf,smb_err,SUCCESS);
3682   SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3683   SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3684   SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3685   SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3686
3687   outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3688
3689   outsize += chain_size;
3690
3691   if(outsize > 4)
3692     smb_setlen(outbuf,outsize - 4);
3693   return(outsize);
3694 }
3695
3696
3697 /****************************************************************************
3698   process commands from the client
3699 ****************************************************************************/
3700 static void process(void)
3701 {
3702   static int trans_num = 0;
3703   int nread;
3704   extern int Client;
3705
3706   InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3707   OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3708   if ((InBuffer == NULL) || (OutBuffer == NULL)) 
3709     return;
3710
3711   InBuffer += SMB_ALIGNMENT;
3712   OutBuffer += SMB_ALIGNMENT;
3713
3714 #if PRIME_NMBD
3715   DEBUG(3,("priming nmbd\n"));
3716   {
3717     struct in_addr ip;
3718     ip = *interpret_addr2("localhost");
3719     if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3720     *OutBuffer = 0;
3721     send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
3722   }
3723 #endif    
3724
3725   while (True)
3726     {
3727       int32 len;      
3728       int msg_type;
3729       int msg_flags;
3730       int type;
3731       int deadtime = lp_deadtime()*60;
3732       int counter;
3733       int last_keepalive=0;
3734
3735       if (deadtime <= 0)
3736         deadtime = DEFAULT_SMBD_TIMEOUT;
3737
3738       if (lp_readprediction())
3739         do_read_prediction();
3740
3741       {
3742         extern pstring share_del_pending;
3743         if (*share_del_pending) {
3744           unbecome_user();
3745           if (!unlink(share_del_pending))
3746             DEBUG(3,("Share file deleted %s\n",share_del_pending));
3747           else
3748             DEBUG(2,("Share del failed of %s\n",share_del_pending));
3749           share_del_pending[0] = 0;
3750         }
3751       }
3752
3753       if (share_mode_pending) {
3754         unbecome_user();
3755         check_share_modes();
3756         share_mode_pending=False;
3757       }
3758
3759       errno = 0;      
3760
3761       for (counter=SMBD_SELECT_LOOP; 
3762            !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000); 
3763            counter += SMBD_SELECT_LOOP)
3764         {
3765           int i;
3766           time_t t;
3767           BOOL allidle = True;
3768           extern int keepalive;
3769
3770           if (smb_read_error == READ_EOF) {
3771             DEBUG(3,("end of file from client\n"));
3772             return;
3773           }
3774
3775           if (smb_read_error == READ_ERROR) {
3776             DEBUG(3,("receive_smb error (%s) exiting\n",
3777                      strerror(errno)));
3778             return;
3779           }
3780
3781           t = time(NULL);
3782
3783           /* become root again if waiting */
3784           unbecome_user();
3785
3786           /* check for smb.conf reload */
3787           if (!(counter%SMBD_RELOAD_CHECK))
3788             reload_services(True);
3789
3790           /* check the share modes every 10 secs */
3791           if (!(counter%SHARE_MODES_CHECK))
3792             check_share_modes();
3793
3794           /* clean the share modes every 5 minutes */
3795           if (!(counter%SHARE_MODES_CLEAN))
3796             clean_share_modes();
3797
3798           /* automatic timeout if all connections are closed */      
3799           if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3800             DEBUG(2,("%s Closing idle connection\n",timestring()));
3801             return;
3802           }
3803
3804           if (keepalive && (counter-last_keepalive)>keepalive) {
3805             extern int password_client;
3806             if (!send_keepalive(Client)) {
3807               DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3808               return;
3809             }       
3810             /* also send a keepalive to the password server if its still
3811                connected */
3812             if (password_client != -1)
3813               send_keepalive(password_client);
3814             last_keepalive = counter;
3815           }
3816
3817           /* check for connection timeouts */
3818           for (i=0;i<MAX_CONNECTIONS;i++)
3819             if (Connections[i].open)
3820               {
3821                 /* close dirptrs on connections that are idle */
3822                 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
3823                   dptr_idlecnum(i);
3824
3825                 if (Connections[i].num_files_open > 0 ||
3826                     (t-Connections[i].lastused)<deadtime)
3827                   allidle = False;
3828               }
3829
3830           if (allidle && num_connections_open>0) {
3831             DEBUG(2,("%s Closing idle connection 2\n",timestring()));
3832             return;
3833           }
3834         }
3835
3836       msg_type = CVAL(InBuffer,0);
3837       msg_flags = CVAL(InBuffer,1);
3838       type = CVAL(InBuffer,smb_com);
3839
3840       len = smb_len(InBuffer);
3841
3842       DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
3843
3844       nread = len + 4;
3845       
3846       DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
3847
3848 #ifdef WITH_VTP
3849       if(trans_num == 1 && VT_Check(InBuffer)) {
3850         VT_Process();
3851         return;
3852       }
3853 #endif
3854
3855
3856       if (msg_type == 0)
3857         show_msg(InBuffer);
3858
3859       nread = construct_reply(InBuffer,OutBuffer,nread,max_send);
3860       
3861       if(nread > 0) {
3862         if (CVAL(OutBuffer,0) == 0)
3863           show_msg(OutBuffer);
3864         
3865         if (nread != smb_len(OutBuffer) + 4) 
3866           {
3867             DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
3868                      nread,
3869                      smb_len(OutBuffer)));
3870           }
3871         else
3872           send_smb(Client,OutBuffer);
3873       }
3874       trans_num++;
3875     }
3876 }
3877
3878
3879 /****************************************************************************
3880   initialise connect, service and file structs
3881 ****************************************************************************/
3882 static void init_structs(void )
3883 {
3884   int i;
3885   get_myname(myhostname,NULL);
3886
3887   for (i=0;i<MAX_CONNECTIONS;i++)
3888     {
3889       Connections[i].open = False;
3890       Connections[i].num_files_open=0;
3891       Connections[i].lastused=0;
3892       Connections[i].used=False;
3893       string_init(&Connections[i].user,"");
3894       string_init(&Connections[i].dirpath,"");
3895       string_init(&Connections[i].connectpath,"");
3896       string_init(&Connections[i].origpath,"");
3897     }
3898
3899   for (i=0;i<MAX_OPEN_FILES;i++)
3900     {
3901       Files[i].open = False;
3902       string_init(&Files[i].name,"");
3903
3904     }
3905
3906   for (i=0;i<MAX_OPEN_FILES;i++)
3907     {
3908       file_fd_struct *fd_ptr = &FileFd[i];
3909       fd_ptr->ref_count = 0;
3910       fd_ptr->dev = (int32)-1;
3911       fd_ptr->inode = (int32)-1;
3912       fd_ptr->fd = -1;
3913       fd_ptr->fd_readonly = -1;
3914       fd_ptr->fd_writeonly = -1;
3915       fd_ptr->real_open_flags = -1;
3916     }
3917
3918   init_dptrs();
3919 }
3920
3921 /****************************************************************************
3922 usage on the program
3923 ****************************************************************************/
3924 static void usage(char *pname)
3925 {
3926   DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
3927
3928   printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
3929   printf("Version %s\n",VERSION);
3930   printf("\t-D                    become a daemon\n");
3931   printf("\t-p port               listen on the specified port\n");
3932   printf("\t-d debuglevel         set the debuglevel\n");
3933   printf("\t-l log basename.      Basename for log/debug files\n");
3934   printf("\t-s services file.     Filename of services file\n");
3935   printf("\t-P                    passive only\n");
3936   printf("\t-a                    overwrite log file, don't append\n");
3937   printf("\n");
3938 }
3939
3940
3941 /****************************************************************************
3942   main program
3943 ****************************************************************************/
3944  int main(int argc,char *argv[])
3945 {
3946   extern BOOL append_log;
3947   /* shall I run as a daemon */
3948   BOOL is_daemon = False;
3949   int port = SMB_PORT;
3950   int opt;
3951   extern char *optarg;
3952   char pidFile[100] = { 0 };
3953
3954 #ifdef NEED_AUTH_PARAMETERS
3955   set_auth_parameters(argc,argv);
3956 #endif
3957
3958 #ifdef SecureWare
3959   setluid(0);
3960 #endif
3961
3962   append_log = True;
3963
3964   TimeInit();
3965
3966   strcpy(debugf,SMBLOGFILE);  
3967
3968   setup_logging(argv[0],False);
3969
3970   charset_initialise();
3971
3972   /* make absolutely sure we run as root - to handle cases whre people
3973      are crazy enough to have it setuid */
3974 #ifdef USE_SETRES
3975   setresuid(0,0,0);
3976 #else
3977   setuid(0);
3978   seteuid(0);
3979   setuid(0);
3980   seteuid(0);
3981 #endif
3982
3983   fault_setup(exit_server);
3984   signal(SIGTERM , SIGNAL_CAST dflt_sig);
3985
3986   /* we want total control over the permissions on created files,
3987      so set our umask to 0 */
3988   umask(0);
3989
3990   GetWd(OriginalDir);
3991
3992   init_uid();
3993
3994   /* this is for people who can't start the program correctly */
3995   while (argc > 1 && (*argv[1] != '-'))
3996     {
3997       argv++;
3998       argc--;
3999     }
4000
4001   while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF)
4002     switch (opt)
4003       {
4004       case 'f':
4005         strncpy(pidFile, optarg, sizeof(pidFile));
4006         break;
4007       case 'O':
4008         strcpy(user_socket_options,optarg);
4009         break;
4010       case 'i':
4011         strcpy(scope,optarg);
4012         break;
4013       case 'P':
4014         {
4015           extern BOOL passive;
4016           passive = True;
4017         }
4018         break;  
4019       case 's':
4020         strcpy(servicesf,optarg);
4021         break;
4022       case 'l':
4023         strcpy(debugf,optarg);
4024         break;
4025       case 'a':
4026         {
4027           extern BOOL append_log;
4028           append_log = !append_log;
4029         }
4030         break;
4031       case 'D':
4032         is_daemon = True;
4033         break;
4034       case 'd':
4035         if (*optarg == 'A')
4036           DEBUGLEVEL = 10000;
4037         else
4038           DEBUGLEVEL = atoi(optarg);
4039         break;
4040       case 'p':
4041         port = atoi(optarg);
4042         break;
4043       case 'h':
4044         usage(argv[0]);
4045         exit(0);
4046         break;
4047       default:
4048         usage(argv[0]);
4049         exit(1);
4050       }
4051
4052   reopen_logs();
4053
4054   DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
4055   DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
4056
4057 #ifndef NO_GETRLIMIT
4058 #ifdef RLIMIT_NOFILE
4059   {
4060     struct rlimit rlp;
4061     getrlimit(RLIMIT_NOFILE, &rlp);
4062     rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
4063     setrlimit(RLIMIT_NOFILE, &rlp);
4064     getrlimit(RLIMIT_NOFILE, &rlp);
4065     DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
4066   }
4067 #endif
4068 #endif
4069
4070   
4071   DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4072         getuid(),getgid(),geteuid(),getegid()));
4073
4074   if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
4075     {
4076       DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
4077       exit(1);
4078     }
4079
4080   init_structs();
4081
4082   if (!reload_services(False))
4083     return(-1); 
4084
4085 #ifndef NO_SIGNAL_TEST
4086   signal(SIGHUP,SIGNAL_CAST sig_hup);
4087 #endif
4088   
4089   DEBUG(3,("%s loaded services\n",timestring()));
4090
4091   if (!is_daemon && !is_a_socket(0))
4092     {
4093       DEBUG(0,("standard input is not a socket, assuming -D option\n"));
4094       is_daemon = True;
4095     }
4096
4097   if (is_daemon)
4098     {
4099       DEBUG(3,("%s becoming a daemon\n",timestring()));
4100       become_daemon();
4101     }
4102
4103   if (*pidFile)
4104     {
4105       int     fd;
4106       char    buf[20];
4107
4108       if ((fd = open(pidFile,
4109          O_NONBLOCK | O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
4110         {
4111            DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
4112            exit(1);
4113         }
4114       if(fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
4115         {
4116           DEBUG(0,("ERROR: smbd is already running\n"));
4117           exit(1);
4118         }
4119       sprintf(buf, "%u\n", (unsigned int) getpid());
4120       if (write(fd, buf, strlen(buf)) < 0)
4121         {
4122           DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
4123           exit(1);
4124         }
4125       /* Leave pid file open & locked for the duration... */
4126     }
4127
4128   if (!open_sockets(is_daemon,port))
4129     exit(1);
4130
4131 #if FAST_SHARE_MODES
4132   if (!start_share_mode_mgmt())
4133     exit(1);
4134 #endif
4135
4136   /* possibly reload the services file. */
4137   reload_services(True);
4138
4139   max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
4140
4141   if (*lp_rootdir())
4142     {
4143       if (sys_chroot(lp_rootdir()) == 0)
4144         DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4145     }
4146
4147   process();
4148   close_sockets();
4149
4150   exit_server("normal exit");
4151   return(0);
4152 }
4153
4154