2 Unix SMB/Netbios implementation.
4 Main SMB server routines
5 Copyright (C) Andrew Tridgell 1992-1995
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.
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.
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.
25 pstring servicesf = CONFIGFILE;
26 extern pstring debugf;
27 extern pstring sesssetup_user;
29 char *InBuffer = NULL;
30 char *OutBuffer = NULL;
31 char *last_inbuf = NULL;
33 BOOL share_mode_pending = False;
35 /* the last message the was processed */
36 int last_message = -1;
38 /* a useful macro to debug the last message processed */
39 #define LAST_MESSAGE() smb_fn_name(last_message)
42 extern int DEBUGLEVEL;
43 extern int case_default;
44 extern BOOL case_sensitive;
45 extern BOOL case_preserve;
46 extern BOOL use_mangled_map;
47 extern BOOL short_case_preserve;
48 extern BOOL case_mangle;
49 extern time_t smb_last_time;
51 extern int smb_read_error;
53 extern pstring user_socket_options;
55 connection_struct Connections[MAX_CONNECTIONS];
56 files_struct Files[MAX_OPEN_FILES];
60 int maxxmit = BUFFER_SIZE;
62 /* a fnum to use when chaining */
65 /* number of open connections */
66 static int num_connections_open = 0;
68 extern fstring remote_machine;
71 /* these can be set by some functions to override the error codes */
72 int unix_ERR_class=SUCCESS;
76 extern int extra_time_offset;
78 extern pstring myhostname;
80 static int find_free_connection(int hash);
82 /* for readability... */
83 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
84 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
85 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
86 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
87 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
91 /****************************************************************************
92 change a dos mode to a unix mode
93 base permission for files:
94 everybody gets read bit set
95 dos readonly is represented in unix by removing everyone's write bit
96 dos archive is represented in unix by the user's execute bit
97 dos system is represented in unix by the group's execute bit
98 dos hidden is represented in unix by the other's execute bit
99 base permission for directories:
100 dos directory is represented in unix by unix's dir bit and the exec bit
101 ****************************************************************************/
102 mode_t unix_mode(int cnum,int dosmode)
104 mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
106 if ( !IS_DOS_READONLY(dosmode) )
107 result |= (S_IWUSR | S_IWGRP | S_IWOTH);
109 if (IS_DOS_DIR(dosmode))
110 result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
112 if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
115 if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
118 if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
121 result &= CREATE_MODE(cnum);
126 /****************************************************************************
127 change a unix mode to a dos mode
128 ****************************************************************************/
129 int dos_mode(int cnum,char *path,struct stat *sbuf)
132 extern struct current_user current_user;
134 if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
135 if (!((sbuf->st_mode & S_IWOTH) ||
136 Connections[cnum].admin_user ||
137 ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) ||
138 ((sbuf->st_mode & S_IWGRP) &&
139 in_group(sbuf->st_gid,current_user.gid,
140 current_user.ngroups,current_user.igroups))))
143 if ((sbuf->st_mode & S_IWUSR) == 0)
147 if ((sbuf->st_mode & S_IXUSR) != 0)
150 if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
153 if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
156 if (S_ISDIR(sbuf->st_mode))
157 result = aDIR | (result & aRONLY);
160 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
164 /* hide files with a name starting with a . */
165 if (lp_hide_dot_files(SNUM(cnum)))
167 char *p = strrchr(path,'/');
173 if (p[0] == '.' && p[1] != '.' && p[1] != 0)
181 /*******************************************************************
182 chmod a file - but preserve some bits
183 ********************************************************************/
184 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
193 if (sys_stat(fname,st)) return(-1);
196 if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
198 if (dos_mode(cnum,fname,st) == dosmode) return(0);
200 unixmode = unix_mode(cnum,dosmode);
202 /* preserve the s bits */
203 mask |= (S_ISUID | S_ISGID);
205 /* preserve the t bit */
210 /* possibly preserve the x bits */
211 if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
212 if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
213 if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
215 unixmode |= (st->st_mode & mask);
217 /* if we previously had any r bits set then leave them alone */
218 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
219 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
223 /* if we previously had any w bits set then leave them alone
224 if the new mode is not rdonly */
225 if (!IS_DOS_READONLY(dosmode) &&
226 (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
227 unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
231 return(sys_chmod(fname,unixmode));
235 /****************************************************************************
236 check if two filenames are equal
238 this needs to be careful about whether we are case sensitive
239 ****************************************************************************/
240 static BOOL fname_equal(char *name1, char *name2)
242 int l1 = strlen(name1);
243 int l2 = strlen(name2);
245 /* handle filenames ending in a single dot */
246 if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
250 ret = fname_equal(name1,name2);
255 if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
259 ret = fname_equal(name1,name2);
264 /* now normal filename handling */
266 return(strcmp(name1,name2) == 0);
268 return(strequal(name1,name2));
272 /****************************************************************************
273 mangle the 2nd name and check if it is then equal to the first name
274 ****************************************************************************/
275 static BOOL mangled_equal(char *name1, char *name2)
282 strcpy(tmpname,name2);
283 mangle_name_83(tmpname);
285 return(strequal(name1,tmpname));
289 /****************************************************************************
290 scan a directory to find a filename, matching without case sensitivity
292 If the name looks like a mangled name then try via the mangling functions
293 ****************************************************************************/
294 static BOOL scan_directory(char *path, char *name,int snum,BOOL docache)
301 mangled = is_mangled(name);
303 /* handle null paths */
307 if (docache && (dname = DirCacheCheck(path,name,snum))) {
313 check_mangled_stack(name);
315 /* open the directory */
316 if (!(cur_dir = OpenDir(path)))
318 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
322 /* now scan for matching names */
323 while ((dname = ReadDirName(cur_dir)))
326 (strequal(dname,".") || strequal(dname,"..")))
330 if (!name_map_mangle(name2,False,snum)) continue;
332 if ((mangled && mangled_equal(name,name2))
333 || fname_equal(name, name2))
335 /* we've found the file, change it's name and return */
336 if (docache) DirCacheAdd(path,name,dname,snum);
347 /****************************************************************************
348 This routine is called to convert names from the dos namespace to unix
349 namespace. It needs to handle any case conversions, mangling, format
352 We assume that we have already done a chdir() to the right "root" directory
355 The function will return False if some part of the name except for the last
356 part cannot be resolved
357 ****************************************************************************/
358 BOOL unix_convert(char *name,int cnum)
366 /* convert to basic unix format - removing \ chars and cleaning it up */
368 unix_clean_name(name);
370 if (!case_sensitive &&
371 (!case_preserve || (is_8_3(name) && !short_case_preserve)))
374 /* names must be relative to the root of the service - trim any leading /.
375 also trim trailing /'s */
376 trim_string(name,"/","/");
378 /* check if it's a printer file */
379 if (Connections[cnum].printer)
381 if ((! *name) || strchr(name,'/') || !is_8_3(name))
385 sprintf(name2,"%.6s.XXXXXX",remote_machine);
386 /* sanitise the name */
387 for (s=name2 ; *s ; s++)
388 if (!issafe(*s)) *s = '_';
389 strcpy(name,(char *)mktemp(name2));
394 /* stat the name - if it exists then we are all done! */
395 if (sys_stat(name,&st) == 0)
398 DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
400 /* a special case - if we don't have any mangling chars and are case
401 sensitive then searching won't help */
402 if (case_sensitive && !is_mangled(name) &&
403 !lp_strip_dot() && !use_mangled_map)
406 /* now we need to recursively match the name against the real
407 directory structure */
410 while (strncmp(start,"./",2) == 0)
413 /* now match each part of the path name separately, trying the names
414 as is first, then trying to scan the directory for matching names */
415 for (;start;start = (end?end+1:(char *)NULL))
417 /* pinpoint the end of this section of the filename */
418 end = strchr(start, '/');
420 /* chop the name at this point */
423 /* check if the name exists up to this point */
424 if (sys_stat(name, &st) == 0)
426 /* it exists. it must either be a directory or this must be
427 the last part of the path for it to be OK */
428 if (end && !(st.st_mode & S_IFDIR))
430 /* an intermediate part of the name isn't a directory */
431 DEBUG(5,("Not a dir %s\n",start));
442 /* remember the rest of the pathname so it can be restored
444 if (end) strcpy(rest,end+1);
447 /* try to find this part of the path in the directory */
448 if (strchr(start,'?') || strchr(start,'*') ||
449 !scan_directory(dirpath, start, SNUM(cnum), end?True:False))
453 /* an intermediate part of the name can't be found */
454 DEBUG(5,("Intermediate not found %s\n",start));
459 /* just the last part of the name doesn't exist */
460 /* we may need to strupper() or strlower() it in case
461 this conversion is being used for file creation
463 /* if the filename is of mixed case then don't normalise it */
464 if (!case_preserve &&
465 (!strhasupper(start) || !strhaslower(start)))
468 /* check on the mangled stack to see if we can recover the
469 base of the filename */
470 if (is_mangled(start))
471 check_mangled_stack(start);
473 DEBUG(5,("New file %s\n",start));
477 /* restore the rest of the string */
480 strcpy(start+strlen(start)+1,rest);
481 end = start + strlen(start);
485 /* add to the dirpath that we have resolved so far */
486 if (*dirpath) strcat(dirpath,"/");
487 strcat(dirpath,start);
489 /* restore the / that we wiped out earlier */
493 /* the name has been resolved */
494 DEBUG(5,("conversion finished %s\n",name));
499 /****************************************************************************
500 normalise for DOS usage
501 ****************************************************************************/
502 static void disk_norm(int *bsize,int *dfree,int *dsize)
504 /* check if the disk is beyond the max disk size */
505 int maxdisksize = lp_maxdisksize();
507 /* convert to blocks - and don't overflow */
508 maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
509 if (*dsize > maxdisksize) *dsize = maxdisksize;
510 if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop
515 while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512)
520 if (*bsize > WORDMAX )
523 if (*dsize > WORDMAX)
525 if (*dfree > WORDMAX)
532 /****************************************************************************
533 return number of 1K blocks available on a path and total number
534 ****************************************************************************/
535 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
537 char *df_command = lp_dfree_command();
551 if (disk_quotas(path, bsize, dfree, dsize))
553 disk_norm(bsize,dfree,dsize);
554 return(((*bsize)/1024)*(*dfree));
559 /* possibly use system() to get the result */
560 if (df_command && *df_command)
566 sprintf(outfile,"/tmp/dfree.smb.%d",(int)getpid());
567 sprintf(syscmd,"%s %s",df_command,path);
568 standard_sub_basic(syscmd);
570 ret = smbrun(syscmd,outfile);
571 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
574 FILE *f = fopen(outfile,"r");
580 fscanf(f,"%d %d %d",dsize,dfree,bsize);
584 DEBUG(0,("Can't open %s\n",outfile));
588 disk_norm(bsize,dfree,dsize);
589 return(((*bsize)/1024)*(*dfree));
593 DEBUG(1,("Warning - no statfs function\n"));
597 if (statfs(path,&fs,sizeof(fs),0) != 0)
600 if (statvfs(path, &fs))
603 if (statfs(path,&fs,sizeof(fs)) == -1)
605 if (statfs(path,&fs) == -1)
607 #endif /* USE_STATVFS */
610 DEBUG(3,("dfree call failed code errno=%d\n",errno));
614 return(((*bsize)/1024)*(*dfree));
619 *dfree = fs.fd_req.bfree;
620 *dsize = fs.fd_req.btot;
623 *bsize = fs.f_frsize;
626 /* eg: osf1 has f_fsize = fundamental filesystem block size,
627 f_bsize = optimal transfer block size (MX: 94-04-19) */
632 #endif /* USE_STATVFS */
637 *dfree = fs.f_bavail;
639 *dsize = fs.f_blocks;
642 #if defined(SCO) || defined(ISC) || defined(MIPS)
646 /* handle rediculous bsize values - some OSes are broken */
647 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
649 disk_norm(bsize,dfree,dsize);
655 DEBUG(0,("dfree seems to be broken on your system\n"));
656 *dsize = 20*1024*1024/(*bsize);
657 *dfree = MAX(1,*dfree);
659 return(((*bsize)/1024)*(*dfree));
664 /****************************************************************************
665 wrap it to get filenames right
666 ****************************************************************************/
667 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
669 return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
674 /****************************************************************************
675 check a filename - possibly caling reducename
677 This is called by every routine before it allows an operation on a filename.
678 It does any final confirmation necessary to ensure that the filename is
679 a valid one for the user to access.
680 ****************************************************************************/
681 BOOL check_name(char *name,int cnum)
687 ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
689 DEBUG(5,("check_name on %s failed\n",name));
694 /****************************************************************************
695 check a filename - possibly caling reducename
696 ****************************************************************************/
697 static void check_for_pipe(char *fname)
699 /* special case of pipe opens */
703 if (strstr(s,"pipe/"))
705 DEBUG(3,("Rejecting named pipe open for %s\n",fname));
706 unix_ERR_class = ERRSRV;
707 unix_ERR_code = ERRaccess;
712 /****************************************************************************
714 ****************************************************************************/
715 void open_file(int fnum,int cnum,char *fname1,int flags,int mode)
719 Files[fnum].open = False;
723 strcpy(fname,fname1);
725 /* check permissions */
726 if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
728 DEBUG(3,("Permission denied opening %s\n",fname));
729 check_for_pipe(fname);
733 /* this handles a bug in Win95 - it doesn't say to create the file when it
735 if (Connections[cnum].printer)
739 if (flags == O_WRONLY)
740 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
744 /* XXXX - is this OK?? */
745 /* this works around a utime bug but can cause other problems */
746 if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
751 Files[fnum].fd = sys_open(fname,flags,mode);
753 if ((Files[fnum].fd>=0) &&
754 Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
759 p = strrchr(dname,'/');
761 if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
762 lp_minprintspace(SNUM(cnum))) {
763 close(Files[fnum].fd);
772 /* Fix for files ending in '.' */
773 if((Files[fnum].fd == -1) && (errno == ENOENT) &&
774 (strchr(fname,'.')==NULL))
777 Files[fnum].fd = sys_open(fname,flags,mode);
780 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
781 if ((Files[fnum].fd == -1) && (errno == ENAMETOOLONG))
784 char *p = strrchr(fname, '/');
786 if (p == fname) /* name is "/xxx" */
788 max_len = pathconf("/", _PC_NAME_MAX);
791 else if ((p == NULL) || (p == fname))
794 max_len = pathconf(".", _PC_NAME_MAX);
799 max_len = pathconf(fname, _PC_NAME_MAX);
803 if (strlen(p) > max_len)
805 char tmp = p[max_len];
808 if ((Files[fnum].fd = sys_open(fname,flags,mode)) == -1)
814 if (Files[fnum].fd < 0)
816 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
817 fname,strerror(errno),flags));
818 check_for_pipe(fname);
822 if (Files[fnum].fd >= 0)
825 Connections[cnum].num_files_open++;
826 fstat(Files[fnum].fd,&st);
827 Files[fnum].mode = st.st_mode;
828 Files[fnum].open_time = time(NULL);
829 Files[fnum].size = 0;
830 Files[fnum].pos = -1;
831 Files[fnum].open = True;
832 Files[fnum].mmap_ptr = NULL;
833 Files[fnum].mmap_size = 0;
834 Files[fnum].can_lock = True;
835 Files[fnum].can_read = ((flags & O_WRONLY)==0);
836 Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
837 Files[fnum].share_mode = 0;
838 Files[fnum].share_pending = False;
839 Files[fnum].print_file = Connections[cnum].printer;
840 Files[fnum].modified = False;
841 Files[fnum].cnum = cnum;
842 string_set(&Files[fnum].name,fname);
843 Files[fnum].wbmpx_ptr = NULL;
846 * If the printer is marked as postscript output a leading
847 * file identifier to ensure the file is treated as a raw
849 * This has a similar effect as CtrlD=0 in WIN.INI file.
850 * tim@fsg.com 09/06/94
852 if (Files[fnum].print_file && POSTSCRIPT(cnum) &&
853 Files[fnum].can_write)
855 DEBUG(3,("Writing postscript line\n"));
856 write_file(fnum,"%!\n",3);
859 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
860 timestring(),Connections[cnum].user,fname,
861 BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
862 Connections[cnum].num_files_open,fnum));
867 /* mmap it if read-only */
868 if (!Files[fnum].can_write)
870 Files[fnum].mmap_size = file_size(fname);
871 Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
872 PROT_READ,MAP_SHARED,Files[fnum].fd,0);
874 if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
876 DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
877 Files[fnum].mmap_ptr = NULL;
883 /*******************************************************************
885 ********************************************************************/
886 void sync_file(int fnum)
889 fsync(Files[fnum].fd);
893 /****************************************************************************
894 run a file if it is a magic script
895 ****************************************************************************/
896 static void check_magic(int fnum,int cnum)
898 if (!*lp_magicscript(SNUM(cnum)))
901 DEBUG(5,("checking magic for %s\n",Files[fnum].name));
905 if (!(p = strrchr(Files[fnum].name,'/')))
906 p = Files[fnum].name;
910 if (!strequal(lp_magicscript(SNUM(cnum)),p))
916 pstring magic_output;
918 strcpy(fname,Files[fnum].name);
920 if (*lp_magicoutput(SNUM(cnum)))
921 strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
923 sprintf(magic_output,"%s.out",fname);
926 ret = smbrun(fname,magic_output);
927 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
933 /****************************************************************************
934 close a file - possibly invalidating the read prediction
935 ****************************************************************************/
936 void close_file(int fnum)
938 int cnum = Files[fnum].cnum;
939 invalidate_read_prediction(Files[fnum].fd);
940 Files[fnum].open = False;
941 Connections[cnum].num_files_open--;
942 if(Files[fnum].wbmpx_ptr)
944 free((char *)Files[fnum].wbmpx_ptr);
945 Files[fnum].wbmpx_ptr = NULL;
949 if(Files[fnum].mmap_ptr)
951 munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size);
952 Files[fnum].mmap_ptr = NULL;
956 if (lp_share_modes(SNUM(cnum)))
957 del_share_mode(fnum);
959 close(Files[fnum].fd);
961 /* NT uses smbclose to start a print - weird */
962 if (Files[fnum].print_file)
965 /* check for magic scripts */
966 check_magic(fnum,cnum);
968 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
969 timestring(),Connections[cnum].user,Files[fnum].name,
970 Connections[cnum].num_files_open));
973 enum {AFAIL,AREAD,AWRITE,AALL};
975 /*******************************************************************
976 reproduce the share mode access table
977 ********************************************************************/
978 static int access_table(int new_deny,int old_deny,int old_mode,
979 int share_pid,char *fname)
981 if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
983 if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
984 if (old_deny == new_deny && share_pid == getpid())
987 if (old_mode == 0) return(AREAD);
989 /* the new smbpub.zip spec says that if the file extension is
990 .com, .dll, .exe or .sym then allow the open. I will force
991 it to read-only as this seems sensible although the spec is
992 a little unclear on this. */
993 if ((fname = strrchr(fname,'.'))) {
994 if (strequal(fname,".com") ||
995 strequal(fname,".dll") ||
996 strequal(fname,".exe") ||
997 strequal(fname,".sym"))
1007 if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1008 if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1009 if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1012 if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1013 if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1014 if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1017 if (old_deny==DENY_WRITE) return(AREAD);
1018 if (old_deny==DENY_READ) return(AWRITE);
1019 if (old_deny==DENY_NONE) return(AALL);
1025 /*******************************************************************
1026 check if the share mode on a file allows it to be deleted or unlinked
1027 return True if sharing doesn't prevent the operation
1028 ********************************************************************/
1029 BOOL check_file_sharing(int cnum,char *fname)
1032 int share_mode = get_share_mode_byname(cnum,fname,&pid);
1034 if (!pid || !share_mode) return(True);
1036 if (share_mode == DENY_DOS)
1037 return(pid == getpid());
1039 /* XXXX exactly what share mode combinations should be allowed for
1040 deleting/renaming? */
1044 /****************************************************************************
1046 Helper for open_file_shared.
1047 Truncate a file after checking locking; close file if locked.
1048 **************************************************************************/
1049 static void truncate_unless_locked(int fnum, int cnum)
1051 if (Files[fnum].can_write){
1052 if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1055 unix_ERR_class = ERRDOS;
1056 unix_ERR_code = ERRlock;
1059 ftruncate(Files[fnum].fd,0);
1064 /****************************************************************************
1065 open a file with a share mode
1066 ****************************************************************************/
1067 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1068 int mode,int *Access,int *action)
1072 int deny_mode = (share_mode>>4)&7;
1074 BOOL file_existed = file_exist(fname,&sbuf);
1075 BOOL fcbopen = False;
1078 Files[fnum].open = False;
1079 Files[fnum].fd = -1;
1081 /* this is for OS/2 EAs - try and say we don't support them */
1082 if (strstr(fname,".+,;=[].")) {
1083 unix_ERR_class = ERRDOS;
1084 unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1088 if ((ofun & 0x3) == 0 && file_existed) {
1095 if ((ofun & 0x3) == 2)
1098 /* note that we ignore the append flag as
1099 append does not mean the same thing under dos and unix */
1101 switch (share_mode&0xF)
1118 if (flags != O_RDONLY && file_existed &&
1119 (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) {
1127 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) {
1128 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1133 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1135 if (lp_share_modes(SNUM(cnum))) {
1139 old_share = get_share_mode(cnum,&sbuf,&share_pid);
1142 /* someone else has a share lock on it, check to see
1144 int old_open_mode = old_share&0xF;
1145 int old_deny_mode = (old_share>>4)&7;
1147 if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) {
1148 DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
1149 deny_mode,old_deny_mode,old_open_mode,fname));
1151 unix_ERR_class = ERRDOS;
1152 unix_ERR_code = ERRbadshare;
1157 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1160 if ((access_allowed == AFAIL) ||
1161 (access_allowed == AREAD && flags == O_WRONLY) ||
1162 (access_allowed == AWRITE && flags == O_RDONLY)) {
1163 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1164 deny_mode,old_deny_mode,old_open_mode,
1168 unix_ERR_class = ERRDOS;
1169 unix_ERR_code = ERRbadshare;
1173 if (access_allowed == AREAD)
1176 if (access_allowed == AWRITE)
1182 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1183 flags,flags2,mode));
1185 open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode);
1186 if (!Files[fnum].open && flags==O_RDWR && errno!=ENOENT && fcbopen) {
1188 open_file(fnum,cnum,fname,flags,mode);
1191 if (Files[fnum].open) {
1205 Files[fnum].share_mode = (deny_mode<<4) | open_mode;
1206 Files[fnum].share_pending = True;
1209 (*Access) = open_mode;
1213 if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1214 if (!file_existed) *action = 2;
1215 if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1219 share_mode_pending = True;
1221 if ((flags2&O_TRUNC) && file_existed)
1222 truncate_unless_locked(fnum,cnum);
1228 /*******************************************************************
1229 check for files that we should now set our share modes on
1230 ********************************************************************/
1231 static void check_share_modes(void)
1234 for (i=0;i<MAX_OPEN_FILES;i++)
1235 if(Files[i].open && Files[i].share_pending) {
1236 if (lp_share_modes(SNUM(Files[i].cnum))) {
1238 get_share_mode_by_fnum(Files[i].cnum,i,&pid);
1240 set_share_mode(i,Files[i].share_mode);
1241 Files[i].share_pending = False;
1244 Files[i].share_pending = False;
1250 /****************************************************************************
1251 seek a file. Try to avoid the seek if possible
1252 ****************************************************************************/
1253 int seek_file(int fnum,int pos)
1256 if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1259 Files[fnum].pos = lseek(Files[fnum].fd,pos+offset,SEEK_SET) - offset;
1260 return(Files[fnum].pos);
1263 /****************************************************************************
1265 ****************************************************************************/
1266 int read_file(int fnum,char *data,int pos,int n)
1270 if (!Files[fnum].can_write)
1272 ret = read_predict(Files[fnum].fd,pos,data,NULL,n);
1280 if (Files[fnum].mmap_ptr)
1282 int num = MIN(n,Files[fnum].mmap_size-pos);
1285 memcpy(data,Files[fnum].mmap_ptr+pos,num);
1297 if (seek_file(fnum,pos) != pos)
1299 DEBUG(3,("Failed to seek to %d\n",pos));
1304 readret = read(Files[fnum].fd,data,n);
1305 if (readret > 0) ret += readret;
1312 /****************************************************************************
1314 ****************************************************************************/
1315 int write_file(int fnum,char *data,int n)
1317 if (!Files[fnum].can_write) {
1322 if (!Files[fnum].modified) {
1324 Files[fnum].modified = True;
1325 if (fstat(Files[fnum].fd,&st) == 0) {
1326 int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1327 if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {
1328 dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1333 return(write_data(Files[fnum].fd,data,n));
1337 /****************************************************************************
1338 load parameters specific to a connection/service
1339 ****************************************************************************/
1340 BOOL become_service(int cnum,BOOL do_chdir)
1342 extern char magic_char;
1343 static int last_cnum = -1;
1346 if (!OPEN_CNUM(cnum))
1352 Connections[cnum].lastused = smb_last_time;
1357 ChDir(Connections[cnum].connectpath) != 0 &&
1358 ChDir(Connections[cnum].origpath) != 0)
1360 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1361 Connections[cnum].connectpath,cnum));
1365 if (cnum == last_cnum)
1370 case_default = lp_defaultcase(snum);
1371 case_preserve = lp_preservecase(snum);
1372 short_case_preserve = lp_shortpreservecase(snum);
1373 case_mangle = lp_casemangle(snum);
1374 case_sensitive = lp_casesensitive(snum);
1375 magic_char = lp_magicchar(snum);
1376 use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1381 /****************************************************************************
1382 find a service entry
1383 ****************************************************************************/
1384 int find_service(char *service)
1388 string_sub(service,"\\","/");
1390 iService = lp_servicenumber(service);
1392 /* now handle the special case of a home directory */
1395 char *phome_dir = get_home_dir(service);
1396 DEBUG(3,("checking for home directory %s gave %s\n",service,
1397 phome_dir?phome_dir:"(NULL)"));
1401 if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1403 lp_add_home(service,iHomeService,phome_dir);
1404 iService = lp_servicenumber(service);
1409 /* If we still don't have a service, attempt to add it as a printer. */
1412 int iPrinterService;
1414 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1418 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1420 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
1422 DEBUG(3,("%s is a valid printer name\n", service));
1423 DEBUG(3,("adding %s as a printer service\n", service));
1424 lp_add_printer(service,iPrinterService);
1425 iService = lp_servicenumber(service);
1427 DEBUG(0,("failed to add %s as a printer service!\n", service));
1430 DEBUG(3,("%s is not a valid printer name\n", service));
1434 /* just possibly it's a default service? */
1437 char *defservice = lp_defaultservice();
1438 if (defservice && *defservice && !strequal(defservice,service)) {
1439 iService = find_service(defservice);
1440 if (iService >= 0) {
1441 string_sub(service,"_","/");
1442 iService = lp_add_service(service,iService);
1448 if (!VALID_SNUM(iService))
1450 DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1455 DEBUG(3,("find_service() failed to find service %s\n", service));
1461 /****************************************************************************
1462 create an error packet from a cached error.
1463 ****************************************************************************/
1464 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
1466 write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
1468 int32 eclass = wbmpx->wr_errclass;
1469 int32 err = wbmpx->wr_error;
1471 /* We can now delete the auxiliary struct */
1472 free((char *)wbmpx);
1473 Files[fnum].wbmpx_ptr = NULL;
1474 return error_packet(inbuf,outbuf,eclass,err,line);
1483 } unix_smb_errmap[] =
1485 {EPERM,ERRDOS,ERRnoaccess},
1486 {EACCES,ERRDOS,ERRnoaccess},
1487 {ENOENT,ERRDOS,ERRbadfile},
1488 {EIO,ERRHRD,ERRgeneral},
1489 {EBADF,ERRSRV,ERRsrverror},
1490 {EINVAL,ERRSRV,ERRsrverror},
1491 {EEXIST,ERRDOS,ERRfilexists},
1492 {ENFILE,ERRDOS,ERRnofids},
1493 {EMFILE,ERRDOS,ERRnofids},
1494 {ENOSPC,ERRHRD,ERRdiskfull},
1496 {EDQUOT,ERRHRD,ERRdiskfull},
1499 {ENOTEMPTY,ERRDOS,ERRnoaccess},
1502 {EXDEV,ERRDOS,ERRdiffdevice},
1504 {EROFS,ERRHRD,ERRnowrite},
1509 /****************************************************************************
1510 create an error packet from errno
1511 ****************************************************************************/
1512 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
1514 int eclass=def_class;
1518 if (unix_ERR_class != SUCCESS)
1520 eclass = unix_ERR_class;
1521 ecode = unix_ERR_code;
1522 unix_ERR_class = SUCCESS;
1527 while (unix_smb_errmap[i].smbclass != 0)
1529 if (unix_smb_errmap[i].unixerror == errno)
1531 eclass = unix_smb_errmap[i].smbclass;
1532 ecode = unix_smb_errmap[i].smbcode;
1539 return(error_packet(inbuf,outbuf,eclass,ecode,line));
1543 /****************************************************************************
1544 create an error packet. Normally called using the ERROR() macro
1545 ****************************************************************************/
1546 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
1548 int outsize = set_message(outbuf,0,0,True);
1550 cmd = CVAL(inbuf,smb_com);
1552 CVAL(outbuf,smb_rcls) = error_class;
1553 SSVAL(outbuf,smb_err,error_code);
1555 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
1558 (int)CVAL(inbuf,smb_com),
1559 smb_fn_name(CVAL(inbuf,smb_com)),
1564 DEBUG(3,("error string = %s\n",strerror(errno)));
1570 #ifndef SIGCLD_IGNORE
1571 /****************************************************************************
1572 this prevents zombie child processes
1573 ****************************************************************************/
1574 static int sig_cld()
1576 static int depth = 0;
1579 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
1585 BlockSignals(True,SIGCLD);
1586 DEBUG(5,("got SIGCLD\n"));
1589 while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
1593 /* Stevens, Adv. Unix Prog. says that on system V you must call
1594 wait before reinstalling the signal handler, because the kernel
1595 calls the handler from within the signal-call when there is a
1596 child that has exited. This would lead to an infinite recursion
1597 if done vice versa. */
1599 #ifndef DONT_REINSTALL_SIG
1600 #ifdef SIGCLD_IGNORE
1601 signal(SIGCLD, SIG_IGN);
1603 signal(SIGCLD, SIGNAL_CAST sig_cld);
1608 while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
1611 BlockSignals(False,SIGCLD);
1616 /****************************************************************************
1617 this is called when the client exits abruptly
1618 **************************************************************************/
1619 static int sig_pipe()
1621 exit_server("Got sigpipe\n");
1625 /****************************************************************************
1626 open the socket communication
1627 ****************************************************************************/
1628 static BOOL open_sockets(BOOL is_daemon,int port)
1635 struct sockaddr addr;
1636 int in_addrlen = sizeof(addr);
1639 #ifdef SIGCLD_IGNORE
1640 signal(SIGCLD, SIG_IGN);
1642 signal(SIGCLD, SIGNAL_CAST sig_cld);
1645 /* open an incoming socket */
1646 s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
1650 /* ready to listen */
1651 if (listen(s, 5) == -1)
1653 DEBUG(0,("listen: %s",strerror(errno)));
1658 /* now accept incoming connections - forking a new process
1659 for each incoming connection */
1660 DEBUG(2,("waiting for a connection\n"));
1663 Client = accept(s,&addr,&in_addrlen);
1665 if (Client == -1 && errno == EINTR)
1670 DEBUG(0,("accept: %s",strerror(errno)));
1674 #ifdef NO_FORK_DEBUG
1675 #ifndef NO_SIGNAL_TEST
1676 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1677 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
1681 if (Client != -1 && fork()==0)
1683 #ifndef NO_SIGNAL_TEST
1684 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1685 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
1687 /* close the listening socket */
1690 /* close our standard file descriptors */
1693 set_socket_options(Client,"SO_KEEPALIVE");
1694 set_socket_options(Client,user_socket_options);
1698 close(Client); /* The parent doesn't need this socket */
1704 /* We will abort gracefully when the client or remote system
1706 #ifndef NO_SIGNAL_TEST
1707 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1711 /* close our standard file descriptors */
1714 set_socket_options(Client,"SO_KEEPALIVE");
1715 set_socket_options(Client,user_socket_options);
1722 /****************************************************************************
1723 check if a snum is in use
1724 ****************************************************************************/
1725 BOOL snum_used(int snum)
1728 for (i=0;i<MAX_CONNECTIONS;i++)
1729 if (OPEN_CNUM(i) && (SNUM(i) == snum))
1734 /****************************************************************************
1735 reload the services file
1736 **************************************************************************/
1737 BOOL reload_services(BOOL test)
1744 strcpy(fname,lp_configfile());
1745 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
1747 strcpy(servicesf,fname);
1754 if (test && !lp_file_list_changed())
1757 lp_killunused(snum_used);
1759 ret = lp_load(servicesf,False);
1761 /* perhaps the config filename is now set */
1763 reload_services(True);
1772 set_socket_options(Client,"SO_KEEPALIVE");
1773 set_socket_options(Client,user_socket_options);
1777 create_mangled_stack(lp_mangledstack());
1779 /* this forces service parameters to be flushed */
1780 become_service(-1,True);
1787 /****************************************************************************
1788 this prevents zombie child processes
1789 ****************************************************************************/
1790 static int sig_hup()
1792 BlockSignals(True,SIGHUP);
1793 DEBUG(0,("Got SIGHUP\n"));
1794 reload_services(False);
1795 #ifndef DONT_REINSTALL_SIG
1796 signal(SIGHUP,SIGNAL_CAST sig_hup);
1798 BlockSignals(False,SIGHUP);
1802 /****************************************************************************
1803 Setup the groups a user belongs to.
1804 ****************************************************************************/
1805 int setup_groups(char *user, int uid, int gid, int *p_ngroups,
1806 int **p_igroups, gid_t **p_groups)
1808 if (-1 == initgroups(user,gid))
1812 DEBUG(0,("Unable to initgroups!\n"));
1813 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
1814 DEBUG(0,("This is probably a problem with the account %s\n",user));
1822 ngroups = getgroups(0,&grp);
1825 igroups = (int *)malloc(sizeof(int)*ngroups);
1826 for (i=0;i<ngroups;i++)
1827 igroups[i] = 0x42424242;
1828 ngroups = getgroups(ngroups,(gid_t *)igroups);
1830 if (igroups[0] == 0x42424242)
1833 *p_ngroups = ngroups;
1835 /* The following bit of code is very strange. It is due to the
1836 fact that some OSes use int* and some use gid_t* for
1837 getgroups, and some (like SunOS) use both, one in prototypes,
1838 and one in man pages and the actual code. Thus we detect it
1839 dynamically using some very ugly code */
1842 /* does getgroups return ints or gid_t ?? */
1843 static BOOL groups_use_ints = True;
1845 if (groups_use_ints &&
1847 SVAL(igroups,2) == 0x4242)
1848 groups_use_ints = False;
1850 for (i=0;groups_use_ints && i<ngroups;i++)
1851 if (igroups[i] == 0x42424242)
1852 groups_use_ints = False;
1854 if (groups_use_ints)
1856 *p_igroups = igroups;
1857 *p_groups = (gid_t *)igroups;
1861 gid_t *groups = (gid_t *)igroups;
1862 igroups = (int *)malloc(sizeof(int)*ngroups);
1863 for (i=0;i<ngroups;i++)
1864 igroups[i] = groups[i];
1865 *p_igroups = igroups;
1866 *p_groups = (gid_t *)groups;
1869 DEBUG(3,("%s is in %d groups\n",user,ngroups));
1870 for (i=0;i<ngroups;i++)
1871 DEBUG(3,("%d ",igroups[i]));
1877 /****************************************************************************
1878 make a connection to a service
1879 ****************************************************************************/
1880 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,int vuid)
1884 struct passwd *pass = NULL;
1885 connection_struct *pcon;
1888 static BOOL first_connection = True;
1892 snum = find_service(service);
1895 if (strequal(service,"IPC$"))
1897 DEBUG(3,("%s refusing IPC connection\n",timestring()));
1901 DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
1905 if (strequal(service,HOMES_NAME))
1907 if (*user && Get_Pwnam(user,True))
1908 return(make_connection(user,user,password,pwlen,dev,vuid));
1910 if (validated_username(vuid))
1912 strcpy(user,validated_username(vuid));
1913 return(make_connection(user,user,password,pwlen,dev,vuid));
1917 if (!lp_snum_ok(snum) || !check_access(snum)) {
1921 /* you can only connect to the IPC$ service as an ipc device */
1922 if (strequal(service,"IPC$"))
1925 if (*dev == '?' || !*dev)
1927 if (lp_print_ok(snum))
1928 strcpy(dev,"LPT1:");
1933 /* if the request is as a printer and you can't print then refuse */
1935 if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
1936 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
1940 /* lowercase the user name */
1943 /* add it as a possible user name */
1944 add_session_user(service);
1946 /* shall we let them in? */
1947 if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
1949 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
1953 cnum = find_free_connection(str_checksum(service) + str_checksum(user));
1956 DEBUG(0,("%s couldn't find free connection\n",timestring()));
1960 pcon = &Connections[cnum];
1961 bzero((char *)pcon,sizeof(*pcon));
1963 /* find out some info about the user */
1964 pass = Get_Pwnam(user,True);
1968 DEBUG(0,("%s couldn't find account %s\n",timestring(),user));
1972 pcon->read_only = lp_readonly(snum);
1976 StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
1977 string_sub(list,"%S",service);
1979 if (user_in_list(user,list))
1980 pcon->read_only = True;
1982 StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
1983 string_sub(list,"%S",service);
1985 if (user_in_list(user,list))
1986 pcon->read_only = False;
1989 /* admin user check */
1990 if (user_in_list(user,lp_admin_users(snum)) &&
1993 pcon->admin_user = True;
1994 DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
1997 pcon->admin_user = False;
1999 pcon->force_user = force;
2000 pcon->uid = pass->pw_uid;
2001 pcon->gid = pass->pw_gid;
2002 pcon->num_files_open = 0;
2003 pcon->lastused = time(NULL);
2004 pcon->service = snum;
2006 pcon->printer = (strncmp(dev,"LPT",3) == 0);
2007 pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2008 pcon->dirptr = NULL;
2009 string_set(&pcon->dirpath,"");
2010 string_set(&pcon->user,user);
2013 if (*lp_force_group(snum))
2015 struct group *gptr = (struct group *)getgrnam(lp_force_group(snum));
2018 pcon->gid = gptr->gr_gid;
2019 DEBUG(3,("Forced group %s\n",lp_force_group(snum)));
2022 DEBUG(1,("Couldn't find group %s\n",lp_force_group(snum)));
2026 if (*lp_force_user(snum))
2028 struct passwd *pass2;
2030 strcpy(fuser,lp_force_user(snum));
2031 pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2034 pcon->uid = pass2->pw_uid;
2035 string_set(&pcon->user,fuser);
2037 pcon->force_user = True;
2038 DEBUG(3,("Forced user %s\n",fuser));
2041 DEBUG(1,("Couldn't find user %s\n",fuser));
2046 strcpy(s,lp_pathname(snum));
2047 standard_sub(cnum,s);
2048 string_set(&pcon->connectpath,s);
2049 DEBUG(3,("Connect path is %s\n",s));
2052 /* groups stuff added by ih */
2054 pcon->groups = NULL;
2058 /* Find all the groups this uid is in and store them. Used by become_user() */
2059 setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2061 /* check number of connections */
2062 if (!claim_connection(cnum,
2063 lp_servicename(SNUM(cnum)),
2064 lp_max_connections(SNUM(cnum)),False))
2066 DEBUG(1,("too many connections - rejected\n"));
2070 if (lp_status(SNUM(cnum)))
2071 claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2073 first_connection = False;
2078 /* execute any "root preexec = " line */
2079 if (*lp_rootpreexec(SNUM(cnum)))
2082 strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2083 standard_sub(cnum,cmd);
2084 DEBUG(5,("cmd=%s\n",cmd));
2088 if (!become_user(cnum,pcon->uid))
2090 DEBUG(0,("Can't become connected user!\n"));
2092 if (!IS_IPC(cnum)) {
2093 yield_connection(cnum,
2094 lp_servicename(SNUM(cnum)),
2095 lp_max_connections(SNUM(cnum)));
2096 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2101 if (ChDir(pcon->connectpath) != 0)
2103 DEBUG(0,("Can't change directory to %s (%s)\n",
2104 pcon->connectpath,strerror(errno)));
2107 if (!IS_IPC(cnum)) {
2108 yield_connection(cnum,
2109 lp_servicename(SNUM(cnum)),
2110 lp_max_connections(SNUM(cnum)));
2111 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2116 string_set(&pcon->origpath,pcon->connectpath);
2118 #if SOFTLINK_OPTIMISATION
2119 /* resolve any soft links early */
2122 strcpy(s,pcon->connectpath);
2124 string_set(&pcon->connectpath,s);
2125 ChDir(pcon->connectpath);
2129 num_connections_open++;
2130 add_session_user(user);
2132 /* execute any "preexec = " line */
2133 if (*lp_preexec(SNUM(cnum)))
2136 strcpy(cmd,lp_preexec(SNUM(cnum)));
2137 standard_sub(cnum,cmd);
2141 /* we've finished with the sensitive stuff */
2145 extern struct from_host Client_info;
2146 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2148 Client_info.name,Client_info.addr,
2149 lp_servicename(SNUM(cnum)),user,
2159 /****************************************************************************
2160 find first available file slot
2161 ****************************************************************************/
2162 int find_free_file(void )
2165 /* we start at 1 here for an obscure reason I can't now remember,
2166 but I think is important :-) */
2167 for (i=1;i<MAX_OPEN_FILES;i++)
2170 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2174 /****************************************************************************
2175 find first available connection slot, starting from a random position.
2176 The randomisation stops problems with the server dieing and clients
2177 thinking the server is still available.
2178 ****************************************************************************/
2179 static int find_free_connection(int hash )
2183 hash = (hash % (MAX_CONNECTIONS-2))+1;
2187 for (i=hash+1;i!=hash;)
2189 if (!Connections[i].open && Connections[i].used == used)
2191 DEBUG(3,("found free connection number %d\n",i));
2195 if (i == MAX_CONNECTIONS)
2205 DEBUG(1,("ERROR! Out of connection structures\n"));
2210 /****************************************************************************
2211 reply for the core protocol
2212 ****************************************************************************/
2213 int reply_corep(char *outbuf)
2215 int outsize = set_message(outbuf,1,0,True);
2217 Protocol = PROTOCOL_CORE;
2223 /****************************************************************************
2224 reply for the coreplus protocol
2225 ****************************************************************************/
2226 int reply_coreplus(char *outbuf)
2228 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2229 int outsize = set_message(outbuf,13,0,True);
2230 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2231 readbraw and writebraw (possibly) */
2232 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2233 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
2235 Protocol = PROTOCOL_COREPLUS;
2241 /****************************************************************************
2242 reply for the lanman 1.0 protocol
2243 ****************************************************************************/
2244 int reply_lanman1(char *outbuf)
2246 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2248 BOOL doencrypt = SMBENCRYPT();
2249 time_t t = time(NULL);
2251 if (lp_security()>=SEC_USER) secword |= 1;
2252 if (doencrypt) secword |= 2;
2254 set_message(outbuf,13,doencrypt?8:0,True);
2255 SSVAL(outbuf,smb_vwv1,secword);
2257 /* Create a token value and add it to the outgoing packet. */
2259 generate_next_challenge(smb_buf(outbuf));
2262 Protocol = PROTOCOL_LANMAN1;
2264 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2265 DEBUG(3,("using password server validation\n"));
2267 if (doencrypt) set_challenge(smb_buf(outbuf));
2271 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2272 SSVAL(outbuf,smb_vwv2,maxxmit);
2273 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2274 SSVAL(outbuf,smb_vwv4,1);
2275 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2276 readbraw writebraw (possibly) */
2277 SIVAL(outbuf,smb_vwv6,getpid());
2278 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2280 put_dos_date(outbuf,smb_vwv8,t);
2282 return (smb_len(outbuf)+4);
2286 /****************************************************************************
2287 reply for the lanman 2.0 protocol
2288 ****************************************************************************/
2289 int reply_lanman2(char *outbuf)
2291 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2293 BOOL doencrypt = SMBENCRYPT();
2294 time_t t = time(NULL);
2296 if (lp_security()>=SEC_USER) secword |= 1;
2297 if (doencrypt) secword |= 2;
2299 set_message(outbuf,13,doencrypt?8:0,True);
2300 SSVAL(outbuf,smb_vwv1,secword);
2302 /* Create a token value and add it to the outgoing packet. */
2304 generate_next_challenge(smb_buf(outbuf));
2307 SIVAL(outbuf,smb_vwv6,getpid());
2309 Protocol = PROTOCOL_LANMAN2;
2311 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2312 DEBUG(3,("using password server validation\n"));
2314 if (doencrypt) set_challenge(smb_buf(outbuf));
2318 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2319 SSVAL(outbuf,smb_vwv2,maxxmit);
2320 SSVAL(outbuf,smb_vwv3,lp_maxmux());
2321 SSVAL(outbuf,smb_vwv4,1);
2322 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2323 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2324 put_dos_date(outbuf,smb_vwv8,t);
2326 return (smb_len(outbuf)+4);
2329 /****************************************************************************
2330 reply for the nt protocol
2331 ****************************************************************************/
2332 int reply_nt1(char *outbuf)
2334 int capabilities=0x300; /* has dual names + lock_and_read */
2336 BOOL doencrypt = SMBENCRYPT();
2337 time_t t = time(NULL);
2339 if (lp_security()>=SEC_USER) secword |= 1;
2340 if (doencrypt) secword |= 2;
2342 set_message(outbuf,17,doencrypt?8:0,True);
2343 CVAL(outbuf,smb_vwv1) = secword;
2345 /* Create a token value and add it to the outgoing packet. */
2347 generate_next_challenge(smb_buf(outbuf));
2348 /* Tell the nt machine how long the challenge is. */
2349 SSVALS(outbuf,smb_vwv16+1,8);
2353 SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2355 Protocol = PROTOCOL_NT1;
2357 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2358 DEBUG(3,("using password server validation\n"));
2360 if (doencrypt) set_challenge(smb_buf(outbuf));
2364 if (lp_readraw() && lp_writeraw())
2367 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2368 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2369 SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */
2370 SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */
2371 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2372 put_long_date(outbuf+smb_vwv11+1,t);
2373 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
2375 return (smb_len(outbuf)+4);
2379 /* these are the protocol lists used for auto architecture detection:
2382 protocol [PC NETWORK PROGRAM 1.0]
2383 protocol [XENIX CORE]
2384 protocol [MICROSOFT NETWORKS 1.03]
2385 protocol [LANMAN1.0]
2386 protocol [Windows for Workgroups 3.1a]
2387 protocol [LM1.2X002]
2388 protocol [LANMAN2.1]
2389 protocol [NT LM 0.12]
2392 protocol [PC NETWORK PROGRAM 1.0]
2393 protocol [XENIX CORE]
2394 protocol [MICROSOFT NETWORKS 1.03]
2395 protocol [LANMAN1.0]
2396 protocol [Windows for Workgroups 3.1a]
2397 protocol [LM1.2X002]
2398 protocol [LANMAN2.1]
2399 protocol [NT LM 0.12]
2402 protocol [PC NETWORK PROGRAM 1.0]
2403 protocol [XENIX CORE]
2404 protocol [LANMAN1.0]
2405 protocol [LM1.2X002]
2406 protocol [LANMAN2.1]
2410 * Modified to recognize the architecture of the remote machine better.
2412 * This appears to be the matrix of which protocol is used by which
2414 Protocol WfWg Win95 WinNT OS/2
2415 PC NETWORK PROGRAM 1.0 1 1 1 1
2417 MICROSOFT NETWORKS 3.0 2 2
2419 MICROSOFT NETWORKS 1.03 3
2422 Windows for Workgroups 3.1a 5 5 5
2427 * tim@fsg.com 09/29/95
2430 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
2431 #define ARCH_WIN95 0x2
2432 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
2433 #define ARCH_WINNT 0x8
2434 #define ARCH_SAMBA 0x10
2436 #define ARCH_ALL 0x1F
2438 /* List of supported protocols, most desired first */
2442 int (*proto_reply_fn)(char *);
2444 } supported_protocols[] = {
2445 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
2446 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
2447 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2448 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2449 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2450 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2451 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2452 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
2453 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
2458 /****************************************************************************
2460 ****************************************************************************/
2461 static int reply_negprot(char *inbuf,char *outbuf)
2463 extern fstring remote_arch;
2464 int outsize = set_message(outbuf,1,0,True);
2469 int bcc = SVAL(smb_buf(inbuf),-2);
2470 int arch = ARCH_ALL;
2472 p = smb_buf(inbuf)+1;
2473 while (p < (smb_buf(inbuf) + bcc))
2476 DEBUG(3,("Requested protocol [%s]\n",p));
2477 if (strcsequal(p,"Windows for Workgroups 3.1a"))
2478 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
2479 else if (strcsequal(p,"DOS LM1.2X002"))
2480 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2481 else if (strcsequal(p,"DOS LANMAN2.1"))
2482 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2483 else if (strcsequal(p,"NT LM 0.12"))
2484 arch &= ( ARCH_WIN95 | ARCH_WINNT );
2485 else if (strcsequal(p,"LANMAN2.1"))
2486 arch &= ( ARCH_WINNT | ARCH_OS2 );
2487 else if (strcsequal(p,"LM1.2X002"))
2488 arch &= ( ARCH_WINNT | ARCH_OS2 );
2489 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
2491 else if (strcsequal(p,"XENIX CORE"))
2492 arch &= ( ARCH_WINNT | ARCH_OS2 );
2493 else if (strcsequal(p,"Samba")) {
2503 strcpy(remote_arch,"Samba");
2506 strcpy(remote_arch,"WfWg");
2509 strcpy(remote_arch,"Win95");
2512 strcpy(remote_arch,"WinNT");
2515 strcpy(remote_arch,"OS2");
2518 strcpy(remote_arch,"UNKNOWN");
2522 /* possibly reload - change of architecture */
2523 reload_services(True);
2525 /* a special case to stop password server loops */
2526 if (Index == 1 && strequal(remote_machine,myhostname) &&
2527 lp_security()==SEC_SERVER)
2528 exit_server("Password server loop!");
2530 /* Check for protocols, most desirable first */
2531 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
2533 p = smb_buf(inbuf)+1;
2535 if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
2536 while (p < (smb_buf(inbuf) + bcc))
2538 if (strequal(p,supported_protocols[protocol].proto_name))
2547 SSVAL(outbuf,smb_vwv0,choice);
2549 extern fstring remote_proto;
2550 strcpy(remote_proto,supported_protocols[protocol].short_name);
2551 reload_services(True);
2552 outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
2553 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
2556 DEBUG(0,("No protocol supported !\n"));
2558 SSVAL(outbuf,smb_vwv0,choice);
2560 DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
2566 /****************************************************************************
2567 parse a connect packet
2568 ****************************************************************************/
2569 void parse_connect(char *buf,char *service,char *user,char *password,int *pwlen,char *dev)
2571 char *p = smb_buf(buf) + 1;
2574 DEBUG(4,("parsing connect string %s\n",p));
2576 p2 = strrchr(p,'\\');
2580 strcpy(service,p2+1);
2585 *pwlen = strlen(password);
2592 p = strchr(service,'%');
2601 /****************************************************************************
2602 close all open files for a connection
2603 ****************************************************************************/
2604 static void close_open_files(int cnum)
2607 for (i=0;i<MAX_OPEN_FILES;i++)
2608 if( Files[i].cnum == cnum && Files[i].open) {
2615 /****************************************************************************
2617 ****************************************************************************/
2618 void close_cnum(int cnum, int uid)
2620 extern struct from_host Client_info;
2622 DirCacheFlush(SNUM(cnum));
2626 if (!OPEN_CNUM(cnum))
2628 DEBUG(0,("Can't close cnum %d\n",cnum));
2632 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
2634 Client_info.name,Client_info.addr,
2635 lp_servicename(SNUM(cnum))));
2637 yield_connection(cnum,
2638 lp_servicename(SNUM(cnum)),
2639 lp_max_connections(SNUM(cnum)));
2641 if (lp_status(SNUM(cnum)))
2642 yield_connection(cnum,"STATUS.",MAXSTATUS);
2644 close_open_files(cnum);
2645 dptr_closecnum(cnum);
2647 /* execute any "postexec = " line */
2648 if (*lp_postexec(SNUM(cnum)) && become_user(cnum,uid))
2651 strcpy(cmd,lp_postexec(SNUM(cnum)));
2652 standard_sub(cnum,cmd);
2658 /* execute any "root postexec = " line */
2659 if (*lp_rootpostexec(SNUM(cnum)))
2662 strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
2663 standard_sub(cnum,cmd);
2667 Connections[cnum].open = False;
2668 num_connections_open--;
2669 if (Connections[cnum].ngroups && Connections[cnum].groups)
2671 if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
2672 free(Connections[cnum].groups);
2673 free(Connections[cnum].igroups);
2674 Connections[cnum].groups = NULL;
2675 Connections[cnum].igroups = NULL;
2676 Connections[cnum].ngroups = 0;
2679 string_set(&Connections[cnum].user,"");
2680 string_set(&Connections[cnum].dirpath,"");
2681 string_set(&Connections[cnum].connectpath,"");
2685 /****************************************************************************
2686 simple routines to do connection counting
2687 ****************************************************************************/
2688 BOOL yield_connection(int cnum,char *name,int max_connections)
2690 struct connect_record crec;
2693 int mypid = getpid();
2696 DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
2698 if (max_connections <= 0)
2701 bzero(&crec,sizeof(crec));
2703 strcpy(fname,lp_lockdir());
2704 standard_sub(cnum,fname);
2705 trim_string(fname,"","/");
2709 strcat(fname,".LCK");
2711 f = fopen(fname,"r+");
2714 DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
2718 fseek(f,0,SEEK_SET);
2720 /* find a free spot */
2721 for (i=0;i<max_connections;i++)
2723 if (fread(&crec,sizeof(crec),1,f) != 1)
2725 DEBUG(2,("Entry not found in lock file %s\n",fname));
2729 if (crec.pid == mypid && crec.cnum == cnum)
2733 if (crec.pid != mypid || crec.cnum != cnum)
2736 DEBUG(2,("Entry not found in lock file %s\n",fname));
2740 bzero((void *)&crec,sizeof(crec));
2742 /* remove our mark */
2743 if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
2744 fwrite(&crec,sizeof(crec),1,f) != 1)
2746 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
2751 DEBUG(3,("Yield successful\n"));
2758 /****************************************************************************
2759 simple routines to do connection counting
2760 ****************************************************************************/
2761 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
2763 struct connect_record crec;
2766 int snum = SNUM(cnum);
2770 if (max_connections <= 0)
2773 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
2775 strcpy(fname,lp_lockdir());
2776 standard_sub(cnum,fname);
2777 trim_string(fname,"","/");
2779 if (!directory_exist(fname,NULL))
2784 strcat(fname,".LCK");
2786 if (!file_exist(fname,NULL))
2788 f = fopen(fname,"w");
2792 total_recs = file_size(fname) / sizeof(crec);
2794 f = fopen(fname,"r+");
2798 DEBUG(1,("couldn't open lock file %s\n",fname));
2802 /* find a free spot */
2803 for (i=0;i<max_connections;i++)
2806 if (i>=total_recs ||
2807 fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
2808 fread(&crec,sizeof(crec),1,f) != 1)
2810 if (foundi < 0) foundi = i;
2814 if (Clear && crec.pid && !process_exists(crec.pid))
2816 fseek(f,i*sizeof(crec),SEEK_SET);
2817 bzero((void *)&crec,sizeof(crec));
2818 fwrite(&crec,sizeof(crec),1,f);
2819 if (foundi < 0) foundi = i;
2822 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
2831 DEBUG(3,("no free locks in %s\n",fname));
2836 /* fill in the crec */
2837 bzero((void *)&crec,sizeof(crec));
2838 crec.magic = 0x280267;
2839 crec.pid = getpid();
2841 crec.uid = Connections[cnum].uid;
2842 crec.gid = Connections[cnum].gid;
2843 StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
2844 crec.start = time(NULL);
2847 extern struct from_host Client_info;
2848 StrnCpy(crec.machine,Client_info.name,sizeof(crec.machine)-1);
2849 StrnCpy(crec.addr,Client_info.addr,sizeof(crec.addr)-1);
2853 if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
2854 fwrite(&crec,sizeof(crec),1,f) != 1)
2865 /*******************************************************************
2866 prepare to dump a core file - carefully!
2867 ********************************************************************/
2868 static BOOL dump_core(void)
2872 strcpy(dname,debugf);
2873 if ((p=strrchr(dname,'/'))) *p=0;
2874 strcat(dname,"/corefiles");
2876 sys_chown(dname,getuid(),getgid());
2878 if (chdir(dname)) return(False);
2881 #ifndef NO_GETRLIMIT
2885 getrlimit(RLIMIT_CORE, &rlp);
2886 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
2887 setrlimit(RLIMIT_CORE, &rlp);
2888 getrlimit(RLIMIT_CORE, &rlp);
2889 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
2895 DEBUG(0,("Dumping core in %s\n",dname));
2900 /****************************************************************************
2902 ****************************************************************************/
2903 void exit_server(char *reason)
2905 static int firsttime=1;
2908 if (!firsttime) exit(0);
2912 DEBUG(2,("Closing connections\n"));
2913 for (i=0;i<MAX_CONNECTIONS;i++)
2914 if (Connections[i].open)
2917 if (dcelogin_atmost_once)
2921 int oldlevel = DEBUGLEVEL;
2923 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
2925 show_msg(last_inbuf);
2926 DEBUGLEVEL = oldlevel;
2927 DEBUG(0,("===============================================================\n"));
2929 if (dump_core()) return;
2932 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
2936 /****************************************************************************
2937 do some standard substitutions in a string
2938 ****************************************************************************/
2939 void standard_sub(int cnum,char *s)
2941 if (!strchr(s,'%')) return;
2943 if (VALID_CNUM(cnum))
2945 string_sub(s,"%S",lp_servicename(Connections[cnum].service));
2946 string_sub(s,"%P",Connections[cnum].connectpath);
2947 string_sub(s,"%u",Connections[cnum].user);
2948 if (strstr(s,"%H")) {
2949 char *home = get_home_dir(Connections[cnum].user);
2950 if (home) string_sub(s,"%H",home);
2952 string_sub(s,"%g",gidtoname(Connections[cnum].gid));
2954 standard_sub_basic(s);
2958 These flags determine some of the permissions required to do an operation
2960 Note that I don't set NEED_WRITE on some write operations because they
2961 are used by some brain-dead clients when printing, and I don't want to
2962 force write permissions on print services.
2964 #define AS_USER (1<<0)
2965 #define NEED_WRITE (1<<1)
2966 #define TIME_INIT (1<<2)
2967 #define CAN_IPC (1<<3)
2968 #define AS_GUEST (1<<5)
2972 define a list of possible SMB messages and their corresponding
2973 functions. Any message that has a NULL function is unimplemented -
2974 please feel free to contribute implementations!
2976 struct smb_message_struct
2990 {SMBnegprot,"SMBnegprot",reply_negprot,0},
2991 {SMBtcon,"SMBtcon",reply_tcon,0},
2992 {SMBtdis,"SMBtdis",reply_tdis,0},
2993 {SMBexit,"SMBexit",reply_exit,0},
2994 {SMBioctl,"SMBioctl",reply_ioctl,0},
2995 {SMBecho,"SMBecho",reply_echo,0},
2996 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
2997 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
2998 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0},
2999 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3000 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3001 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3002 {SMBsearch,"SMBsearch",reply_search,AS_USER},
3003 {SMBopen,"SMBopen",reply_open,AS_USER},
3005 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3006 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3007 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
3009 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3010 {SMBread,"SMBread",reply_read,AS_USER},
3011 {SMBwrite,"SMBwrite",reply_write,AS_USER},
3012 {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
3013 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3014 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3015 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3016 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3018 /* this is a Pathworks specific call, allowing the
3019 changing of the root path */
3020 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
3022 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3023 {SMBflush,"SMBflush",reply_flush,AS_USER},
3024 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3025 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3026 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3027 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST},
3028 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3029 {SMBlock,"SMBlock",reply_lock,AS_USER},
3030 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3032 /* CORE+ PROTOCOL FOLLOWS */
3034 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3035 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3036 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3037 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3038 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3040 /* LANMAN1.0 PROTOCOL FOLLOWS */
3042 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3043 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3044 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3045 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3046 {SMBwritec,"SMBwritec",NULL,AS_USER},
3047 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3048 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3049 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3050 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3051 {SMBioctls,"SMBioctls",NULL,AS_USER},
3052 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3053 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3055 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC},
3056 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3057 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3058 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3060 {SMBffirst,"SMBffirst",reply_search,AS_USER},
3061 {SMBfunique,"SMBfunique",reply_search,AS_USER},
3062 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3064 /* LANMAN2.0 PROTOCOL FOLLOWS */
3065 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3066 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3067 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3068 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3070 /* messaging routines */
3071 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3072 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3073 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3074 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3076 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3078 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3079 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3080 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3081 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3084 /****************************************************************************
3085 return a string containing the function name of a SMB command
3086 ****************************************************************************/
3087 char *smb_fn_name(int type)
3089 static char *unknown_name = "SMBunknown";
3090 static int num_smb_messages =
3091 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3094 for (match=0;match<num_smb_messages;match++)
3095 if (smb_messages[match].code == type)
3098 if (match == num_smb_messages)
3099 return(unknown_name);
3101 return(smb_messages[match].name);
3105 /****************************************************************************
3106 do a switch on the message type, and return the response size
3107 ****************************************************************************/
3108 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3112 static int num_smb_messages =
3113 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3117 struct timeval msg_start_time;
3118 struct timeval msg_end_time;
3119 static unsigned long total_time = 0;
3121 GetTimeOfDay(&msg_start_time);
3128 last_message = type;
3130 /* make sure this is an SMB packet */
3131 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3133 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3137 for (match=0;match<num_smb_messages;match++)
3138 if (smb_messages[match].code == type)
3141 if (match == num_smb_messages)
3143 DEBUG(0,("Unknown message type %d!\n",type));
3144 outsize = reply_unknown(inbuf,outbuf);
3148 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3149 if (smb_messages[match].fn)
3151 int cnum = SVAL(inbuf,smb_tid);
3152 int flags = smb_messages[match].flags;
3153 int uid = SVAL(inbuf,smb_uid);
3155 /* does this protocol need to be run as root? */
3156 if (!(flags & AS_USER))
3159 /* does this protocol need to be run as the connected user? */
3160 if ((flags & AS_USER) && !become_user(cnum,uid)) {
3161 if (flags & AS_GUEST)
3164 return(ERROR(ERRSRV,ERRinvnid));
3166 /* this code is to work around a bug is MS client 3 without
3167 introducing a security hole - it needs to be able to do
3168 print queue checks as guest if it isn't logged in properly */
3169 if (flags & AS_USER)
3172 /* does it need write permission? */
3173 if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3174 return(ERROR(ERRSRV,ERRaccess));
3176 /* ipc services are limited */
3177 if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3178 return(ERROR(ERRSRV,ERRaccess));
3180 /* load service specific parameters */
3181 if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3182 return(ERROR(ERRSRV,ERRaccess));
3184 /* does this protocol need to be run as guest? */
3185 if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3186 return(ERROR(ERRSRV,ERRaccess));
3190 outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3194 outsize = reply_unknown(inbuf,outbuf);
3199 GetTimeOfDay(&msg_end_time);
3200 if (!(smb_messages[match].flags & TIME_INIT))
3202 smb_messages[match].time = 0;
3203 smb_messages[match].flags |= TIME_INIT;
3206 unsigned long this_time =
3207 (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3208 (msg_end_time.tv_usec - msg_start_time.tv_usec);
3209 smb_messages[match].time += this_time;
3210 total_time += this_time;
3212 DEBUG(2,("TIME %s %d usecs %g pct\n",
3213 smb_fn_name(type),smb_messages[match].time,
3214 (100.0*smb_messages[match].time) / total_time));
3221 /****************************************************************************
3222 construct a chained reply and add it to the already made reply
3223 **************************************************************************/
3224 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
3226 static char *orig_inbuf;
3227 static char *orig_outbuf;
3228 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
3229 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
3230 char *inbuf2, *outbuf2;
3232 char inbuf_saved[smb_wct];
3233 char outbuf_saved[smb_wct];
3234 extern int chain_size;
3235 int wct = CVAL(outbuf,smb_wct);
3236 int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
3238 /* maybe its not chained */
3239 if (smb_com2 == 0xFF) {
3240 CVAL(outbuf,smb_vwv0) = 0xFF;
3244 if (chain_size == 0) {
3245 /* this is the first part of the chain */
3247 orig_outbuf = outbuf;
3250 /* we need to tell the client where the next part of the reply will be */
3251 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
3252 CVAL(outbuf,smb_vwv0) = smb_com2;
3254 /* remember how much the caller added to the chain, only counting stuff
3255 after the parameter words */
3256 chain_size += outsize - smb_wct;
3258 /* work out pointers into the original packets. The
3259 headers on these need to be filled in */
3260 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
3261 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
3263 /* remember the original command type */
3264 smb_com1 = CVAL(orig_outbuf,smb_com);
3266 /* save the data which will be overwritten by the new headers */
3267 memcpy(inbuf_saved,inbuf2,smb_wct);
3268 memcpy(outbuf_saved,outbuf2,smb_wct);
3270 /* give the new packet the same header as the first part of the SMB */
3271 memmove(inbuf2,orig_inbuf,smb_wct);
3273 /* create the in buffer */
3274 CVAL(inbuf2,smb_com) = smb_com2;
3276 /* create the out buffer */
3277 bzero(outbuf2,smb_size);
3278 set_message(outbuf2,0,0,True);
3279 CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com);
3281 memcpy(outbuf2+4,inbuf2+4,4);
3282 CVAL(outbuf2,smb_rcls) = SUCCESS;
3283 CVAL(outbuf2,smb_reh) = 0;
3284 CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set
3286 SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */
3287 SSVAL(outbuf2,smb_err,SUCCESS);
3288 SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid));
3289 SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid));
3290 SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid));
3291 SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid));
3293 DEBUG(3,("Chained message\n"));
3296 /* process the request */
3297 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
3298 bufsize-chain_size);
3300 /* copy the new reply header over the old one, but preserve
3301 the smb_com field */
3302 memmove(orig_outbuf,outbuf2,smb_wct);
3303 CVAL(orig_outbuf,smb_com) = smb_com1;
3305 /* restore the saved data, being careful not to overwrite any
3306 data from the reply header */
3307 memcpy(inbuf2,inbuf_saved,smb_wct);
3309 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
3310 if (ofs < 0) ofs = 0;
3311 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
3319 /****************************************************************************
3320 construct a reply to the incoming packet
3321 ****************************************************************************/
3322 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3324 int type = CVAL(inbuf,smb_com);
3326 int msg_type = CVAL(inbuf,0);
3327 extern int chain_size;
3329 smb_last_time = time(NULL);
3334 bzero(outbuf,smb_size);
3337 return(reply_special(inbuf,outbuf));
3339 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3340 set_message(outbuf,0,0,True);
3342 memcpy(outbuf+4,inbuf+4,4);
3343 CVAL(outbuf,smb_rcls) = SUCCESS;
3344 CVAL(outbuf,smb_reh) = 0;
3345 CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
3347 SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3348 SSVAL(outbuf,smb_err,SUCCESS);
3349 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3350 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3351 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3352 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3354 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3356 outsize += chain_size;
3359 smb_setlen(outbuf,outsize - 4);
3364 /****************************************************************************
3365 process commands from the client
3366 ****************************************************************************/
3367 static void process(void)
3369 static int trans_num = 0;
3371 extern struct from_host Client_info;
3374 fromhost(Client,&Client_info);
3376 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3377 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3378 if ((InBuffer == NULL) || (OutBuffer == NULL))
3381 InBuffer += SMB_ALIGNMENT;
3382 OutBuffer += SMB_ALIGNMENT;
3385 DEBUG(3,("priming nmbd\n"));
3388 ip = *interpret_addr2("localhost");
3389 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3391 send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
3401 int deadtime = lp_deadtime()*60;
3403 int last_keepalive=0;
3406 deadtime = DEFAULT_SMBD_TIMEOUT;
3408 if (lp_readprediction())
3409 do_read_prediction();
3412 extern pstring share_del_pending;
3413 if (*share_del_pending) {
3415 if (!unlink(share_del_pending))
3416 DEBUG(3,("Share file deleted %s\n",share_del_pending));
3418 DEBUG(2,("Share del failed of %s\n",share_del_pending));
3419 share_del_pending[0] = 0;
3423 if (share_mode_pending) {
3425 check_share_modes();
3426 share_mode_pending=False;
3431 for (counter=SMBD_SELECT_LOOP;
3432 !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000);
3433 counter += SMBD_SELECT_LOOP)
3437 BOOL allidle = True;
3438 extern int keepalive;
3440 if (smb_read_error == READ_EOF) {
3441 DEBUG(3,("end of file from client\n"));
3445 if (smb_read_error == READ_ERROR) {
3446 DEBUG(3,("receive_smb error (%s) exiting\n",
3453 /* become root again if waiting */
3456 /* check for smb.conf reload */
3457 if (!(counter%SMBD_RELOAD_CHECK))
3458 reload_services(True);
3460 /* check the share modes every 10 secs */
3461 if (!(counter%SHARE_MODES_CHECK))
3462 check_share_modes();
3464 /* clean the share modes every 5 minutes */
3465 if (!(counter%SHARE_MODES_CLEAN))
3466 clean_share_modes();
3468 /* automatic timeout if all connections are closed */
3469 if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3470 DEBUG(2,("%s Closing idle connection\n",timestring()));
3474 if (keepalive && (counter-last_keepalive)>keepalive) {
3475 extern int password_client;
3476 if (!send_keepalive(Client)) {
3477 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3480 /* also send a keepalive to the password server if its still
3482 if (password_client != -1)
3483 send_keepalive(password_client);
3484 last_keepalive = counter;
3487 /* check for connection timeouts */
3488 for (i=0;i<MAX_CONNECTIONS;i++)
3489 if (Connections[i].open)
3491 /* close dirptrs on connections that are idle */
3492 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
3495 if (Connections[i].num_files_open > 0 ||
3496 (t-Connections[i].lastused)<deadtime)
3500 if (allidle && num_connections_open>0) {
3501 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
3506 msg_type = CVAL(InBuffer,0);
3507 msg_flags = CVAL(InBuffer,1);
3508 type = CVAL(InBuffer,smb_com);
3510 len = smb_len(InBuffer);
3512 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
3516 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
3519 if(trans_num == 1 && VT_Check(InBuffer)) {
3529 nread = construct_reply(InBuffer,OutBuffer,nread,maxxmit);
3532 if (CVAL(OutBuffer,0) == 0)
3533 show_msg(OutBuffer);
3535 if (nread != smb_len(OutBuffer) + 4)
3537 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
3539 smb_len(OutBuffer)));
3542 send_smb(Client,OutBuffer);
3549 /****************************************************************************
3550 initialise connect, service and file structs
3551 ****************************************************************************/
3552 static void init_structs(void )
3555 get_myname(myhostname,NULL);
3557 for (i=0;i<MAX_CONNECTIONS;i++)
3559 Connections[i].open = False;
3560 Connections[i].num_files_open=0;
3561 Connections[i].lastused=0;
3562 Connections[i].used=False;
3563 string_init(&Connections[i].user,"");
3564 string_init(&Connections[i].dirpath,"");
3565 string_init(&Connections[i].connectpath,"");
3566 string_init(&Connections[i].origpath,"");
3569 for (i=0;i<MAX_OPEN_FILES;i++)
3571 Files[i].open = False;
3572 string_init(&Files[i].name,"");
3578 /****************************************************************************
3579 usage on the program
3580 ****************************************************************************/
3581 static void usage(char *pname)
3583 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
3585 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
3586 printf("Version %s\n",VERSION);
3587 printf("\t-D become a daemon\n");
3588 printf("\t-p port listen on the specified port\n");
3589 printf("\t-d debuglevel set the debuglevel\n");
3590 printf("\t-l log basename. Basename for log/debug files\n");
3591 printf("\t-s services file. Filename of services file\n");
3592 printf("\t-P passive only\n");
3593 printf("\t-a overwrite log file, don't append\n");
3598 /****************************************************************************
3600 ****************************************************************************/
3601 int main(int argc,char *argv[])
3603 extern BOOL append_log;
3604 /* shall I run as a daemon */
3605 BOOL is_daemon = False;
3606 int port = SMB_PORT;
3608 extern char *optarg;
3610 #ifdef NEED_AUTH_PARAMETERS
3611 set_auth_parameters(argc,argv);
3622 strcpy(debugf,SMBLOGFILE);
3624 setup_logging(argv[0],False);
3626 charset_initialise();
3628 /* make absolutely sure we run as root - to handle cases whre people
3629 are crazy enough to have it setuid */
3639 fault_setup(exit_server);
3641 umask(0777 & ~DEF_CREATE_MASK);
3645 /* this is for people who can't start the program correctly */
3646 while (argc > 1 && (*argv[1] != '-'))
3652 while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPa")) != EOF)
3656 strcpy(user_socket_options,optarg);
3659 strcpy(scope,optarg);
3663 extern BOOL passive;
3668 strcpy(servicesf,optarg);
3671 strcpy(debugf,optarg);
3675 extern BOOL append_log;
3676 append_log = !append_log;
3686 DEBUGLEVEL = atoi(optarg);
3689 port = atoi(optarg);
3702 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
3703 DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
3705 #ifndef NO_GETRLIMIT
3706 #ifdef RLIMIT_NOFILE
3709 getrlimit(RLIMIT_NOFILE, &rlp);
3710 rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
3711 setrlimit(RLIMIT_NOFILE, &rlp);
3712 getrlimit(RLIMIT_NOFILE, &rlp);
3713 DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
3719 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
3720 getuid(),getgid(),geteuid(),getegid()));
3722 if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
3724 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
3730 if (!reload_services(False))
3733 #ifndef NO_SIGNAL_TEST
3734 signal(SIGHUP,SIGNAL_CAST sig_hup);
3737 DEBUG(3,("%s loaded services\n",timestring()));
3739 if (!is_daemon && !is_a_socket(0))
3741 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
3747 DEBUG(3,("%s becoming a daemon\n",timestring()));
3751 if (!open_sockets(is_daemon,port))
3754 #if FAST_SHARE_MODES
3755 if (!start_share_mode_mgmt())
3759 /* possibly reload the services file. */
3760 reload_services(True);
3762 maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE);
3766 if (sys_chroot(lp_rootdir()) == 0)
3767 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
3773 #if FAST_SHARE_MODES
3774 stop_share_mode_mgmt();
3777 exit_server("normal exit");