line 1960 - call to atexit - address of higher order function killkids
[Samba/gbeck.git] / source / smbd / server.c
blob6ab6c76c4af9d6ef9cae6d5b24e4fff88ef7046c
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
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.
22 #include "includes.h"
23 #include "trans2.h"
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 int am_parent = 1;
34 int atexit_set = 0;
36 BOOL share_mode_pending = False;
38 /* the last message the was processed */
39 int last_message = -1;
41 /* a useful macro to debug the last message processed */
42 #define LAST_MESSAGE() smb_fn_name(last_message)
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;
54 extern int smb_read_error;
56 extern pstring user_socket_options;
58 connection_struct Connections[MAX_CONNECTIONS];
59 files_struct Files[MAX_OPEN_FILES];
62 * Indirection for file fd's. Needed as POSIX locking
63 * is based on file/process, not fd/process.
65 file_fd_struct FileFd[MAX_OPEN_FILES];
66 int max_file_fd_used = 0;
68 extern int Protocol;
70 int maxxmit = BUFFER_SIZE;
72 /* a fnum to use when chaining */
73 int chain_fnum = -1;
75 /* number of open connections */
76 static int num_connections_open = 0;
78 extern fstring remote_machine;
80 pstring OriginalDir;
82 /* these can be set by some functions to override the error codes */
83 int unix_ERR_class=SUCCESS;
84 int unix_ERR_code=0;
87 extern int extra_time_offset;
89 extern pstring myhostname;
91 static int find_free_connection(int hash);
93 /* for readability... */
94 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
95 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
96 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
97 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
98 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
100 /****************************************************************************
101 when exiting, take the whole family
102 ****************************************************************************/
103 void *dflt_sig(void)
105 exit_server("caught signal");
107 /****************************************************************************
108 Send a SIGTERM to our process group.
109 *****************************************************************************/
110 void killkids(void)
112 if(am_parent) kill(0,SIGTERM);
115 /****************************************************************************
116 change a dos mode to a unix mode
117 base permission for files:
118 everybody gets read bit set
119 dos readonly is represented in unix by removing everyone's write bit
120 dos archive is represented in unix by the user's execute bit
121 dos system is represented in unix by the group's execute bit
122 dos hidden is represented in unix by the other's execute bit
123 base permission for directories:
124 dos directory is represented in unix by unix's dir bit and the exec bit
125 ****************************************************************************/
126 mode_t unix_mode(int cnum,int dosmode)
128 mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
130 if ( !IS_DOS_READONLY(dosmode) )
131 result |= (S_IWUSR | S_IWGRP | S_IWOTH);
133 if (IS_DOS_DIR(dosmode))
134 result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
136 if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
137 result |= S_IXUSR;
139 if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
140 result |= S_IXGRP;
142 if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
143 result |= S_IXOTH;
145 result &= CREATE_MODE(cnum);
146 return(result);
150 /****************************************************************************
151 change a unix mode to a dos mode
152 ****************************************************************************/
153 int dos_mode(int cnum,char *path,struct stat *sbuf)
155 int result = 0;
156 extern struct current_user current_user;
158 if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
159 if (!((sbuf->st_mode & S_IWOTH) ||
160 Connections[cnum].admin_user ||
161 ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) ||
162 ((sbuf->st_mode & S_IWGRP) &&
163 in_group(sbuf->st_gid,current_user.gid,
164 current_user.ngroups,current_user.igroups))))
165 result |= aRONLY;
166 } else {
167 if ((sbuf->st_mode & S_IWUSR) == 0)
168 result |= aRONLY;
171 if ((sbuf->st_mode & S_IXUSR) != 0)
172 result |= aARCH;
174 if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
175 result |= aSYSTEM;
177 if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
178 result |= aHIDDEN;
180 if (S_ISDIR(sbuf->st_mode))
181 result = aDIR | (result & aRONLY);
183 #if LINKS_READ_ONLY
184 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
185 result |= aRONLY;
186 #endif
188 /* hide files with a name starting with a . */
189 if (lp_hide_dot_files(SNUM(cnum)))
191 char *p = strrchr(path,'/');
192 if (p)
193 p++;
194 else
195 p = path;
197 if (p[0] == '.' && p[1] != '.' && p[1] != 0)
198 result |= aHIDDEN;
201 return(result);
205 /*******************************************************************
206 chmod a file - but preserve some bits
207 ********************************************************************/
208 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
210 struct stat st1;
211 int mask=0;
212 int tmp;
213 int unixmode;
215 if (!st) {
216 st = &st1;
217 if (sys_stat(fname,st)) return(-1);
220 if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
222 if (dos_mode(cnum,fname,st) == dosmode) return(0);
224 unixmode = unix_mode(cnum,dosmode);
226 /* preserve the s bits */
227 mask |= (S_ISUID | S_ISGID);
229 /* preserve the t bit */
230 #ifdef S_ISVTX
231 mask |= S_ISVTX;
232 #endif
234 /* possibly preserve the x bits */
235 if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
236 if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
237 if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
239 unixmode |= (st->st_mode & mask);
241 /* if we previously had any r bits set then leave them alone */
242 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
243 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
244 unixmode |= tmp;
247 /* if we previously had any w bits set then leave them alone
248 if the new mode is not rdonly */
249 if (!IS_DOS_READONLY(dosmode) &&
250 (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
251 unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
252 unixmode |= tmp;
255 return(sys_chmod(fname,unixmode));
259 /****************************************************************************
260 check if two filenames are equal
262 this needs to be careful about whether we are case sensitive
263 ****************************************************************************/
264 static BOOL fname_equal(char *name1, char *name2)
266 int l1 = strlen(name1);
267 int l2 = strlen(name2);
269 /* handle filenames ending in a single dot */
270 if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
272 BOOL ret;
273 name1[l1-1] = 0;
274 ret = fname_equal(name1,name2);
275 name1[l1-1] = '.';
276 return(ret);
279 if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
281 BOOL ret;
282 name2[l2-1] = 0;
283 ret = fname_equal(name1,name2);
284 name2[l2-1] = '.';
285 return(ret);
288 /* now normal filename handling */
289 if (case_sensitive)
290 return(strcmp(name1,name2) == 0);
292 return(strequal(name1,name2));
296 /****************************************************************************
297 mangle the 2nd name and check if it is then equal to the first name
298 ****************************************************************************/
299 static BOOL mangled_equal(char *name1, char *name2)
301 pstring tmpname;
303 if (is_8_3(name2))
304 return(False);
306 strcpy(tmpname,name2);
307 mangle_name_83(tmpname);
309 return(strequal(name1,tmpname));
313 /****************************************************************************
314 scan a directory to find a filename, matching without case sensitivity
316 If the name looks like a mangled name then try via the mangling functions
317 ****************************************************************************/
318 static BOOL scan_directory(char *path, char *name,int snum,BOOL docache)
320 void *cur_dir;
321 char *dname;
322 BOOL mangled;
323 pstring name2;
325 mangled = is_mangled(name);
327 /* handle null paths */
328 if (*path == 0)
329 path = ".";
331 if (docache && (dname = DirCacheCheck(path,name,snum))) {
332 strcpy(name, dname);
333 return(True);
336 if (mangled)
337 check_mangled_stack(name);
339 /* open the directory */
340 if (!(cur_dir = OpenDir(path)))
342 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
343 return(False);
346 /* now scan for matching names */
347 while ((dname = ReadDirName(cur_dir)))
349 if (*dname == '.' &&
350 (strequal(dname,".") || strequal(dname,"..")))
351 continue;
353 strcpy(name2,dname);
354 if (!name_map_mangle(name2,False,snum)) continue;
356 if ((mangled && mangled_equal(name,name2))
357 || fname_equal(name, name2))
359 /* we've found the file, change it's name and return */
360 if (docache) DirCacheAdd(path,name,dname,snum);
361 strcpy(name, dname);
362 CloseDir(cur_dir);
363 return(True);
367 CloseDir(cur_dir);
368 return(False);
371 /****************************************************************************
372 This routine is called to convert names from the dos namespace to unix
373 namespace. It needs to handle any case conversions, mangling, format
374 changes etc.
376 We assume that we have already done a chdir() to the right "root" directory
377 for this service.
379 The function will return False if some part of the name except for the last
380 part cannot be resolved
382 If the saved_last_component != 0, then the unmodified last component
383 of the pathname is returned there. This is used in an exceptional
384 case in reply_mv (so far). If saved_last_component == 0 then nothing
385 is returned there.
386 ****************************************************************************/
387 BOOL unix_convert(char *name,int cnum,pstring saved_last_component)
389 struct stat st;
390 char *start, *end;
391 pstring dirpath;
393 *dirpath = 0;
394 if(saved_last_component)
395 *saved_last_component = 0;
397 /* convert to basic unix format - removing \ chars and cleaning it up */
398 unix_format(name);
399 unix_clean_name(name);
401 if (!case_sensitive &&
402 (!case_preserve || (is_8_3(name) && !short_case_preserve)))
403 strnorm(name);
405 /* names must be relative to the root of the service - trim any leading /.
406 also trim trailing /'s */
407 trim_string(name,"/","/");
409 /* check if it's a printer file */
410 if (Connections[cnum].printer)
412 if ((! *name) || strchr(name,'/') || !is_8_3(name))
414 char *s;
415 fstring name2;
416 sprintf(name2,"%.6s.XXXXXX",remote_machine);
417 /* sanitise the name */
418 for (s=name2 ; *s ; s++)
419 if (!issafe(*s)) *s = '_';
420 strcpy(name,(char *)mktemp(name2));
422 return(True);
426 * Ensure saved_last_component is valid even if file exists.
428 if(saved_last_component) {
429 end = strrchr(name, '/');
430 if(end)
431 strcpy(saved_last_component, end + 1);
432 else
433 strcpy(saved_last_component, name);
436 /* stat the name - if it exists then we are all done! */
437 if (sys_stat(name,&st) == 0)
438 return(True);
440 DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
442 /* a special case - if we don't have any mangling chars and are case
443 sensitive then searching won't help */
444 if (case_sensitive && !is_mangled(name) &&
445 !lp_strip_dot() && !use_mangled_map)
446 return(False);
448 /* now we need to recursively match the name against the real
449 directory structure */
451 start = name;
452 while (strncmp(start,"./",2) == 0)
453 start += 2;
455 /* now match each part of the path name separately, trying the names
456 as is first, then trying to scan the directory for matching names */
457 for (;start;start = (end?end+1:(char *)NULL))
459 /* pinpoint the end of this section of the filename */
460 end = strchr(start, '/');
462 /* chop the name at this point */
463 if (end) *end = 0;
465 if(saved_last_component != 0)
466 strcpy(saved_last_component, end ? end + 1 : start);
468 /* check if the name exists up to this point */
469 if (sys_stat(name, &st) == 0)
471 /* it exists. it must either be a directory or this must be
472 the last part of the path for it to be OK */
473 if (end && !(st.st_mode & S_IFDIR))
475 /* an intermediate part of the name isn't a directory */
476 DEBUG(5,("Not a dir %s\n",start));
477 *end = '/';
478 return(False);
481 else
483 pstring rest;
485 *rest = 0;
487 /* remember the rest of the pathname so it can be restored
488 later */
489 if (end) strcpy(rest,end+1);
491 /* try to find this part of the path in the directory */
492 if (strchr(start,'?') || strchr(start,'*') ||
493 !scan_directory(dirpath, start, SNUM(cnum), end?True:False))
495 if (end)
497 /* an intermediate part of the name can't be found */
498 DEBUG(5,("Intermediate not found %s\n",start));
499 *end = '/';
500 return(False);
503 /* just the last part of the name doesn't exist */
504 /* we may need to strupper() or strlower() it in case
505 this conversion is being used for file creation
506 purposes */
507 /* if the filename is of mixed case then don't normalise it */
508 if (!case_preserve &&
509 (!strhasupper(start) || !strhaslower(start)))
510 strnorm(start);
512 /* check on the mangled stack to see if we can recover the
513 base of the filename */
514 if (is_mangled(start))
515 check_mangled_stack(start);
517 DEBUG(5,("New file %s\n",start));
518 return(True);
521 /* restore the rest of the string */
522 if (end)
524 strcpy(start+strlen(start)+1,rest);
525 end = start + strlen(start);
529 /* add to the dirpath that we have resolved so far */
530 if (*dirpath) strcat(dirpath,"/");
531 strcat(dirpath,start);
533 /* restore the / that we wiped out earlier */
534 if (end) *end = '/';
537 /* the name has been resolved */
538 DEBUG(5,("conversion finished %s\n",name));
539 return(True);
543 /****************************************************************************
544 normalise for DOS usage
545 ****************************************************************************/
546 static void disk_norm(int *bsize,int *dfree,int *dsize)
548 /* check if the disk is beyond the max disk size */
549 int maxdisksize = lp_maxdisksize();
550 if (maxdisksize) {
551 /* convert to blocks - and don't overflow */
552 maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
553 if (*dsize > maxdisksize) *dsize = maxdisksize;
554 if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop
555 applications getting
556 div by 0 errors */
559 while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512)
561 *dfree /= 2;
562 *dsize /= 2;
563 *bsize *= 2;
564 if (*bsize > WORDMAX )
566 *bsize = WORDMAX;
567 if (*dsize > WORDMAX)
568 *dsize = WORDMAX;
569 if (*dfree > WORDMAX)
570 *dfree = WORDMAX;
571 break;
576 /****************************************************************************
577 return number of 1K blocks available on a path and total number
578 ****************************************************************************/
579 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
581 char *df_command = lp_dfree_command();
582 #ifndef NO_STATFS
583 #ifdef USE_STATVFS
584 struct statvfs fs;
585 #else
586 #ifdef ULTRIX
587 struct fs_data fs;
588 #else
589 struct statfs fs;
590 #endif
591 #endif
592 #endif
594 #ifdef QUOTAS
595 if (disk_quotas(path, bsize, dfree, dsize))
597 disk_norm(bsize,dfree,dsize);
598 return(((*bsize)/1024)*(*dfree));
600 #endif
603 /* possibly use system() to get the result */
604 if (df_command && *df_command)
606 int ret;
607 pstring syscmd;
608 pstring outfile;
610 sprintf(outfile,"%s/dfree.smb.%d",tmpdir(),(int)getpid());
611 sprintf(syscmd,"%s %s",df_command,path);
612 standard_sub_basic(syscmd);
614 ret = smbrun(syscmd,outfile,False);
615 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
618 FILE *f = fopen(outfile,"r");
619 *dsize = 0;
620 *dfree = 0;
621 *bsize = 1024;
622 if (f)
624 fscanf(f,"%d %d %d",dsize,dfree,bsize);
625 fclose(f);
627 else
628 DEBUG(0,("Can't open %s\n",outfile));
631 unlink(outfile);
632 disk_norm(bsize,dfree,dsize);
633 return(((*bsize)/1024)*(*dfree));
636 #ifdef NO_STATFS
637 DEBUG(1,("Warning - no statfs function\n"));
638 return(1);
639 #else
640 #ifdef STATFS4
641 if (statfs(path,&fs,sizeof(fs),0) != 0)
642 #else
643 #ifdef USE_STATVFS
644 if (statvfs(path, &fs))
645 #else
646 #ifdef STATFS3
647 if (statfs(path,&fs,sizeof(fs)) == -1)
648 #else
649 if (statfs(path,&fs) == -1)
650 #endif /* STATFS3 */
651 #endif /* USE_STATVFS */
652 #endif /* STATFS4 */
654 DEBUG(3,("dfree call failed code errno=%d\n",errno));
655 *bsize = 1024;
656 *dfree = 1;
657 *dsize = 1;
658 return(((*bsize)/1024)*(*dfree));
661 #ifdef ULTRIX
662 *bsize = 1024;
663 *dfree = fs.fd_req.bfree;
664 *dsize = fs.fd_req.btot;
665 #else
666 #ifdef USE_STATVFS
667 *bsize = fs.f_frsize;
668 #else
669 #ifdef USE_F_FSIZE
670 /* eg: osf1 has f_fsize = fundamental filesystem block size,
671 f_bsize = optimal transfer block size (MX: 94-04-19) */
672 *bsize = fs.f_fsize;
673 #else
674 *bsize = fs.f_bsize;
675 #endif /* STATFS3 */
676 #endif /* USE_STATVFS */
678 #ifdef STATFS4
679 *dfree = fs.f_bfree;
680 #else
681 *dfree = fs.f_bavail;
682 #endif /* STATFS4 */
683 *dsize = fs.f_blocks;
684 #endif /* ULTRIX */
686 #if defined(SCO) || defined(ISC) || defined(MIPS)
687 *bsize = 512;
688 #endif
690 /* handle rediculous bsize values - some OSes are broken */
691 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
693 disk_norm(bsize,dfree,dsize);
695 if (*bsize < 256)
696 *bsize = 512;
697 if ((*dsize)<1)
699 DEBUG(0,("dfree seems to be broken on your system\n"));
700 *dsize = 20*1024*1024/(*bsize);
701 *dfree = MAX(1,*dfree);
703 return(((*bsize)/1024)*(*dfree));
704 #endif
708 /****************************************************************************
709 wrap it to get filenames right
710 ****************************************************************************/
711 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
713 return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
718 /****************************************************************************
719 check a filename - possibly caling reducename
721 This is called by every routine before it allows an operation on a filename.
722 It does any final confirmation necessary to ensure that the filename is
723 a valid one for the user to access.
724 ****************************************************************************/
725 BOOL check_name(char *name,int cnum)
727 BOOL ret;
729 errno = 0;
731 if( is_vetoed_path(name))
733 DEBUG(5,("file path name %s vetoed\n",name));
734 return(0);
737 ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
738 if (!ret)
739 DEBUG(5,("check_name on %s failed\n",name));
741 return(ret);
744 /****************************************************************************
745 check a filename - possibly caling reducename
746 ****************************************************************************/
747 static void check_for_pipe(char *fname)
749 /* special case of pipe opens */
750 char s[10];
751 StrnCpy(s,fname,9);
752 strlower(s);
753 if (strstr(s,"pipe/"))
755 DEBUG(3,("Rejecting named pipe open for %s\n",fname));
756 unix_ERR_class = ERRSRV;
757 unix_ERR_code = ERRaccess;
761 /****************************************************************************
762 fd support routines - attempt to do a sys_open
763 ****************************************************************************/
765 int fd_attempt_open(char *fname, int flags, int mode)
767 int fd = sys_open(fname,flags,mode);
769 /* Fix for files ending in '.' */
770 if((fd == -1) && (errno == ENOENT) &&
771 (strchr(fname,'.')==NULL))
773 strcat(fname,".");
774 fd = sys_open(fname,flags,mode);
777 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
778 if ((fd == -1) && (errno == ENAMETOOLONG))
780 int max_len;
781 char *p = strrchr(fname, '/');
783 if (p == fname) /* name is "/xxx" */
785 max_len = pathconf("/", _PC_NAME_MAX);
786 p++;
788 else if ((p == NULL) || (p == fname))
790 p = fname;
791 max_len = pathconf(".", _PC_NAME_MAX);
793 else
795 *p = '\0';
796 max_len = pathconf(fname, _PC_NAME_MAX);
797 *p = '/';
798 p++;
800 if (strlen(p) > max_len)
802 char tmp = p[max_len];
804 p[max_len] = '\0';
805 if ((fd = sys_open(fname,flags,mode)) == -1)
806 p[max_len] = tmp;
809 #endif
810 return fd;
813 /****************************************************************************
814 fd support routines - attempt to find an already open file by dev
815 and inode - increments the ref_count of the returned file_fd_struct *.
816 ****************************************************************************/
817 file_fd_struct *fd_get_already_open(struct stat *sbuf)
819 int i;
820 file_fd_struct *fd_ptr;
822 if(sbuf == 0)
823 return 0;
825 for(i = 0; i <= max_file_fd_used; i++) {
826 fd_ptr = &FileFd[i];
827 if((fd_ptr->ref_count > 0) &&
828 (((int32)sbuf->st_dev) == fd_ptr->dev) &&
829 (((int32)sbuf->st_ino) == fd_ptr->inode)) {
830 fd_ptr->ref_count++;
831 DEBUG(3,
832 ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n",
833 i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count));
834 return fd_ptr;
837 return 0;
840 /****************************************************************************
841 fd support routines - attempt to find a empty slot in the FileFd array.
842 Increments the ref_count of the returned entry.
843 ****************************************************************************/
844 file_fd_struct *fd_get_new()
846 int i;
847 file_fd_struct *fd_ptr;
849 for(i = 0; i < MAX_OPEN_FILES; i++) {
850 fd_ptr = &FileFd[i];
851 if(fd_ptr->ref_count == 0) {
852 fd_ptr->dev = (int32)-1;
853 fd_ptr->inode = (int32)-1;
854 fd_ptr->fd = -1;
855 fd_ptr->fd_readonly = -1;
856 fd_ptr->fd_writeonly = -1;
857 fd_ptr->real_open_flags = -1;
858 fd_ptr->ref_count++;
859 /* Increment max used counter if neccessary, cuts down
860 on search time when re-using */
861 if(i > max_file_fd_used)
862 max_file_fd_used = i;
863 DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n",
864 i, fd_ptr->dev, fd_ptr->inode));
865 return fd_ptr;
868 DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\
869 n"));
870 return 0;
873 /****************************************************************************
874 fd support routines - attempt to re-open an already open fd as O_RDWR.
875 Save the already open fd (we cannot close due to POSIX file locking braindamage.
876 ****************************************************************************/
878 void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
880 int fd = sys_open( fname, O_RDWR, mode);
882 if(fd == -1)
883 return;
885 if(fd_ptr->real_open_flags == O_RDONLY)
886 fd_ptr->fd_readonly = fd_ptr->fd;
887 if(fd_ptr->real_open_flags == O_WRONLY)
888 fd_ptr->fd_writeonly = fd_ptr->fd;
890 fd_ptr->fd = fd;
891 fd_ptr->real_open_flags = O_RDWR;
894 /****************************************************************************
895 fd support routines - attempt to close the file referenced by this fd.
896 Decrements the ref_count and returns it.
897 ****************************************************************************/
898 int fd_attempt_close(file_fd_struct *fd_ptr)
900 DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n",
901 fd_ptr - &FileFd[0],
902 fd_ptr->fd, fd_ptr->dev, fd_ptr->inode,
903 fd_ptr->real_open_flags,
904 fd_ptr->ref_count));
905 if(fd_ptr->ref_count > 0) {
906 fd_ptr->ref_count--;
907 if(fd_ptr->ref_count == 0) {
908 if(fd_ptr->fd != -1)
909 close(fd_ptr->fd);
910 if(fd_ptr->fd_readonly != -1)
911 close(fd_ptr->fd_readonly);
912 if(fd_ptr->fd_writeonly != -1)
913 close(fd_ptr->fd_writeonly);
914 fd_ptr->fd = -1;
915 fd_ptr->fd_readonly = -1;
916 fd_ptr->fd_writeonly = -1;
917 fd_ptr->real_open_flags = -1;
918 fd_ptr->dev = -1;
919 fd_ptr->inode = -1;
922 return fd_ptr->ref_count;
925 /****************************************************************************
926 open a file
927 ****************************************************************************/
928 void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf)
930 extern struct current_user current_user;
931 pstring fname;
932 struct stat statbuf;
933 file_fd_struct *fd_ptr;
935 Files[fnum].open = False;
936 Files[fnum].fd_ptr = 0;
937 errno = EPERM;
939 strcpy(fname,fname1);
941 /* check permissions */
942 if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
944 DEBUG(3,("Permission denied opening %s\n",fname));
945 check_for_pipe(fname);
946 return;
949 /* this handles a bug in Win95 - it doesn't say to create the file when it
950 should */
951 if (Connections[cnum].printer)
952 flags |= O_CREAT;
955 if (flags == O_WRONLY)
956 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
959 #if UTIME_WORKAROUND
960 /* XXXX - is this OK?? */
961 /* this works around a utime bug but can cause other problems */
962 if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
963 sys_unlink(fname);
964 #endif
967 * Ensure we have a valid struct stat so we can search the
968 * open fd table.
970 if(sbuf == 0) {
971 if(stat(fname, &statbuf) < 0) {
972 if(errno != ENOENT) {
973 DEBUG(3,("Error doing stat on file %s (%s)\n",
974 fname,strerror(errno)));
976 check_for_pipe(fname);
977 return;
979 sbuf = 0;
980 } else {
981 sbuf = &statbuf;
986 * Check to see if we have this file already
987 * open. If we do, just use the already open fd and increment the
988 * reference count (fd_get_already_open increments the ref_count).
990 if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
992 int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
994 /* File was already open. */
995 if((flags & O_CREAT) && (flags & O_EXCL)) {
996 fd_ptr->ref_count--;
997 errno = EEXIST;
998 return;
1002 * If not opened O_RDWR try
1003 * and do that here - a chmod may have been done
1004 * between the last open and now.
1006 if(fd_ptr->real_open_flags != O_RDWR)
1007 fd_attempt_reopen(fname, mode, fd_ptr);
1010 * Ensure that if we wanted write access
1011 * it has been opened for write, and if we wanted read it
1012 * was open for read.
1014 if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) ||
1015 ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) ||
1016 ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) {
1017 DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n",
1018 fd_ptr->real_open_flags, fname,strerror(EACCES),flags));
1019 check_for_pipe(fname);
1020 fd_ptr->ref_count--;
1021 return;
1025 * If O_TRUNC was set, ensure we truncate the file.
1026 * open_file_shared explicitly clears this flag before
1027 * calling open_file, so we can safely do this here.
1029 if(flags & O_TRUNC)
1030 ftruncate(fd_ptr->fd, 0);
1032 } else {
1033 int open_flags;
1034 /* We need to allocate a new file_fd_struct (this increments the
1035 ref_count). */
1036 if((fd_ptr = fd_get_new()) == 0)
1037 return;
1039 * Whatever the requested flags, attempt read/write access,
1040 * as we don't know what flags future file opens may require.
1041 * If this fails, try again with the required flags.
1042 * Even if we open read/write when only read access was
1043 * requested the setting of the can_write flag in
1044 * the file_struct will protect us from errant
1045 * write requests. We never need to worry about O_APPEND
1046 * as this is not set anywhere in Samba.
1048 fd_ptr->real_open_flags = O_RDWR;
1049 /* Set the flags as needed without the read/write modes. */
1050 open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY);
1051 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode);
1052 if((fd_ptr->fd == -1) && (errno == EACCES)) {
1053 if(flags & O_WRONLY) {
1054 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode);
1055 fd_ptr->real_open_flags = O_WRONLY;
1056 } else {
1057 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode);
1058 fd_ptr->real_open_flags = O_RDONLY;
1063 if ((fd_ptr->fd >=0) &&
1064 Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
1065 pstring dname;
1066 int dum1,dum2,dum3;
1067 char *p;
1068 strcpy(dname,fname);
1069 p = strrchr(dname,'/');
1070 if (p) *p = 0;
1071 if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
1072 lp_minprintspace(SNUM(cnum))) {
1073 fd_attempt_close(fd_ptr);
1074 Files[fnum].fd_ptr = 0;
1075 if(fd_ptr->ref_count == 0)
1076 sys_unlink(fname);
1077 errno = ENOSPC;
1078 return;
1082 if (fd_ptr->fd < 0)
1084 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
1085 fname,strerror(errno),flags));
1086 /* Ensure the ref_count is decremented. */
1087 fd_attempt_close(fd_ptr);
1088 check_for_pipe(fname);
1089 return;
1092 if (fd_ptr->fd >= 0)
1094 if(sbuf == 0) {
1095 /* Do the fstat */
1096 if(fstat(fd_ptr->fd, &statbuf) == -1) {
1097 /* Error - backout !! */
1098 DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
1099 fd_ptr->fd, fname,strerror(errno)));
1100 /* Ensure the ref_count is decremented. */
1101 fd_attempt_close(fd_ptr);
1102 return;
1104 sbuf = &statbuf;
1106 /* Set the correct entries in fd_ptr. */
1107 fd_ptr->dev = (int32)sbuf->st_dev;
1108 fd_ptr->inode = (int32)sbuf->st_ino;
1110 Files[fnum].fd_ptr = fd_ptr;
1111 Connections[cnum].num_files_open++;
1112 Files[fnum].mode = sbuf->st_mode;
1113 GetTimeOfDay(&Files[fnum].open_time);
1114 Files[fnum].uid = current_user.id;
1115 Files[fnum].size = 0;
1116 Files[fnum].pos = -1;
1117 Files[fnum].open = True;
1118 Files[fnum].mmap_ptr = NULL;
1119 Files[fnum].mmap_size = 0;
1120 Files[fnum].can_lock = True;
1121 Files[fnum].can_read = ((flags & O_WRONLY)==0);
1122 Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
1123 Files[fnum].share_mode = 0;
1124 Files[fnum].share_pending = False;
1125 Files[fnum].print_file = Connections[cnum].printer;
1126 Files[fnum].modified = False;
1127 Files[fnum].cnum = cnum;
1128 string_set(&Files[fnum].name,dos_to_unix(fname,False));
1129 Files[fnum].wbmpx_ptr = NULL;
1132 * If the printer is marked as postscript output a leading
1133 * file identifier to ensure the file is treated as a raw
1134 * postscript file.
1135 * This has a similar effect as CtrlD=0 in WIN.INI file.
1136 * tim@fsg.com 09/06/94
1138 if (Files[fnum].print_file && POSTSCRIPT(cnum) &&
1139 Files[fnum].can_write)
1141 DEBUG(3,("Writing postscript line\n"));
1142 write_file(fnum,"%!\n",3);
1145 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
1146 timestring(),Connections[cnum].user,fname,
1147 BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
1148 Connections[cnum].num_files_open,fnum));
1152 #if USE_MMAP
1153 /* mmap it if read-only */
1154 if (!Files[fnum].can_write)
1156 Files[fnum].mmap_size = file_size(fname);
1157 Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
1158 PROT_READ,MAP_SHARED,Files[fnum].fd,0);
1160 if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
1162 DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
1163 Files[fnum].mmap_ptr = NULL;
1166 #endif
1169 /*******************************************************************
1170 sync a file
1171 ********************************************************************/
1172 void sync_file(int fnum)
1174 #ifndef NO_FSYNC
1175 fsync(Files[fnum].fd_ptr->fd);
1176 #endif
1179 /****************************************************************************
1180 run a file if it is a magic script
1181 ****************************************************************************/
1182 static void check_magic(int fnum,int cnum)
1184 if (!*lp_magicscript(SNUM(cnum)))
1185 return;
1187 DEBUG(5,("checking magic for %s\n",Files[fnum].name));
1190 char *p;
1191 if (!(p = strrchr(Files[fnum].name,'/')))
1192 p = Files[fnum].name;
1193 else
1194 p++;
1196 if (!strequal(lp_magicscript(SNUM(cnum)),p))
1197 return;
1201 int ret;
1202 pstring magic_output;
1203 pstring fname;
1204 strcpy(fname,Files[fnum].name);
1206 if (*lp_magicoutput(SNUM(cnum)))
1207 strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
1208 else
1209 sprintf(magic_output,"%s.out",fname);
1211 chmod(fname,0755);
1212 ret = smbrun(fname,magic_output,False);
1213 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
1214 unlink(fname);
1219 /****************************************************************************
1220 close a file - possibly invalidating the read prediction
1221 ****************************************************************************/
1222 void close_file(int fnum)
1224 int cnum = Files[fnum].cnum;
1225 invalidate_read_prediction(Files[fnum].fd_ptr->fd);
1226 Files[fnum].open = False;
1227 Connections[cnum].num_files_open--;
1228 if(Files[fnum].wbmpx_ptr)
1230 free((char *)Files[fnum].wbmpx_ptr);
1231 Files[fnum].wbmpx_ptr = NULL;
1234 #if USE_MMAP
1235 if(Files[fnum].mmap_ptr)
1237 munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size);
1238 Files[fnum].mmap_ptr = NULL;
1240 #endif
1242 if (lp_share_modes(SNUM(cnum)))
1243 del_share_mode(fnum);
1245 fd_attempt_close(Files[fnum].fd_ptr);
1247 /* NT uses smbclose to start a print - weird */
1248 if (Files[fnum].print_file)
1249 print_file(fnum);
1251 /* check for magic scripts */
1252 check_magic(fnum,cnum);
1254 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
1255 timestring(),Connections[cnum].user,Files[fnum].name,
1256 Connections[cnum].num_files_open));
1259 enum {AFAIL,AREAD,AWRITE,AALL};
1261 /*******************************************************************
1262 reproduce the share mode access table
1263 ********************************************************************/
1264 static int access_table(int new_deny,int old_deny,int old_mode,
1265 int share_pid,char *fname)
1267 if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
1269 if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
1270 if (old_deny == new_deny && share_pid == getpid())
1271 return(AALL);
1273 if (old_mode == 0) return(AREAD);
1275 /* the new smbpub.zip spec says that if the file extension is
1276 .com, .dll, .exe or .sym then allow the open. I will force
1277 it to read-only as this seems sensible although the spec is
1278 a little unclear on this. */
1279 if ((fname = strrchr(fname,'.'))) {
1280 if (strequal(fname,".com") ||
1281 strequal(fname,".dll") ||
1282 strequal(fname,".exe") ||
1283 strequal(fname,".sym"))
1284 return(AREAD);
1287 return(AFAIL);
1290 switch (new_deny)
1292 case DENY_WRITE:
1293 if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1294 if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1295 if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1296 return(AFAIL);
1297 case DENY_READ:
1298 if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1299 if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1300 if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1301 return(AFAIL);
1302 case DENY_NONE:
1303 if (old_deny==DENY_WRITE) return(AREAD);
1304 if (old_deny==DENY_READ) return(AWRITE);
1305 if (old_deny==DENY_NONE) return(AALL);
1306 return(AFAIL);
1308 return(AFAIL);
1311 /*******************************************************************
1312 check if the share mode on a file allows it to be deleted or unlinked
1313 return True if sharing doesn't prevent the operation
1314 ********************************************************************/
1315 BOOL check_file_sharing(int cnum,char *fname)
1317 int pid=0;
1318 int share_mode = get_share_mode_byname(cnum,fname,&pid);
1320 if (!pid || !share_mode) return(True);
1322 if (share_mode == DENY_DOS)
1323 return(pid == getpid());
1325 /* XXXX exactly what share mode combinations should be allowed for
1326 deleting/renaming? */
1327 return(False);
1330 /****************************************************************************
1331 C. Hoch 11/22/95
1332 Helper for open_file_shared.
1333 Truncate a file after checking locking; close file if locked.
1334 **************************************************************************/
1335 static void truncate_unless_locked(int fnum, int cnum)
1337 if (Files[fnum].can_write){
1338 if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1339 close_file(fnum);
1340 errno = EACCES;
1341 unix_ERR_class = ERRDOS;
1342 unix_ERR_code = ERRlock;
1344 else
1345 ftruncate(Files[fnum].fd_ptr->fd,0);
1350 /****************************************************************************
1351 open a file with a share mode
1352 ****************************************************************************/
1353 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1354 int mode,int *Access,int *action)
1356 int flags=0;
1357 int flags2=0;
1358 int deny_mode = (share_mode>>4)&7;
1359 struct stat sbuf;
1360 BOOL file_existed = file_exist(fname,&sbuf);
1361 BOOL fcbopen = False;
1362 int share_pid=0;
1364 Files[fnum].open = False;
1365 Files[fnum].fd_ptr = 0;
1367 /* this is for OS/2 EAs - try and say we don't support them */
1368 if (strstr(fname,".+,;=[].")) {
1369 unix_ERR_class = ERRDOS;
1370 unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1371 return;
1374 if ((ofun & 0x3) == 0 && file_existed) {
1375 errno = EEXIST;
1376 return;
1379 if (ofun & 0x10)
1380 flags2 |= O_CREAT;
1381 if ((ofun & 0x3) == 2)
1382 flags2 |= O_TRUNC;
1384 /* note that we ignore the append flag as
1385 append does not mean the same thing under dos and unix */
1387 switch (share_mode&0xF)
1389 case 1:
1390 flags = O_WRONLY;
1391 break;
1392 case 0xF:
1393 fcbopen = True;
1394 flags = O_RDWR;
1395 break;
1396 case 2:
1397 flags = O_RDWR;
1398 break;
1399 default:
1400 flags = O_RDONLY;
1401 break;
1404 if (flags != O_RDONLY && file_existed &&
1405 (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) {
1406 if (!fcbopen) {
1407 errno = EACCES;
1408 return;
1410 flags = O_RDONLY;
1413 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) {
1414 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1415 errno = EINVAL;
1416 return;
1419 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1421 if (lp_share_modes(SNUM(cnum))) {
1422 int old_share=0;
1424 if (file_existed)
1425 old_share = get_share_mode(cnum,&sbuf,&share_pid);
1427 if (share_pid) {
1428 /* someone else has a share lock on it, check to see
1429 if we can too */
1430 int old_open_mode = old_share&0xF;
1431 int old_deny_mode = (old_share>>4)&7;
1433 if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) {
1434 DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
1435 deny_mode,old_deny_mode,old_open_mode,fname));
1436 errno = EACCES;
1437 unix_ERR_class = ERRDOS;
1438 unix_ERR_code = ERRbadshare;
1439 return;
1443 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1444 share_pid,fname);
1446 if ((access_allowed == AFAIL) ||
1447 (!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) ||
1448 (access_allowed == AREAD && flags == O_WRONLY) ||
1449 (access_allowed == AWRITE && flags == O_RDONLY)) {
1450 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1451 deny_mode,old_deny_mode,old_open_mode,
1452 share_pid,fname,
1453 access_allowed));
1454 errno = EACCES;
1455 unix_ERR_class = ERRDOS;
1456 unix_ERR_code = ERRbadshare;
1457 return;
1460 if (access_allowed == AREAD)
1461 flags = O_RDONLY;
1463 if (access_allowed == AWRITE)
1464 flags = O_WRONLY;
1469 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1470 flags,flags2,mode));
1472 open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
1473 if (!Files[fnum].open && flags==O_RDWR && errno!=ENOENT && fcbopen) {
1474 flags = O_RDONLY;
1475 open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 );
1478 if (Files[fnum].open) {
1479 int open_mode=0;
1480 switch (flags) {
1481 case O_RDONLY:
1482 open_mode = 0;
1483 break;
1484 case O_RDWR:
1485 open_mode = 2;
1486 break;
1487 case O_WRONLY:
1488 open_mode = 1;
1489 break;
1492 Files[fnum].share_mode = (deny_mode<<4) | open_mode;
1493 Files[fnum].share_pending = True;
1495 if (Access) {
1496 (*Access) = open_mode;
1499 if (action) {
1500 if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1501 if (!file_existed) *action = 2;
1502 if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1505 if (!share_pid)
1506 share_mode_pending = True;
1508 if ((flags2&O_TRUNC) && file_existed)
1509 truncate_unless_locked(fnum,cnum);
1515 /*******************************************************************
1516 check for files that we should now set our share modes on
1517 ********************************************************************/
1518 static void check_share_modes(void)
1520 int i;
1521 for (i=0;i<MAX_OPEN_FILES;i++)
1522 if(Files[i].open && Files[i].share_pending) {
1523 if (lp_share_modes(SNUM(Files[i].cnum))) {
1524 int pid=0;
1525 get_share_mode_by_fnum(Files[i].cnum,i,&pid);
1526 if (!pid) {
1527 set_share_mode(i,Files[i].share_mode);
1528 Files[i].share_pending = False;
1530 } else {
1531 Files[i].share_pending = False;
1537 /****************************************************************************
1538 seek a file. Try to avoid the seek if possible
1539 ****************************************************************************/
1540 int seek_file(int fnum,int pos)
1542 int offset = 0;
1543 if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1544 offset = 3;
1546 Files[fnum].pos = lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET) - offset;
1547 return(Files[fnum].pos);
1550 /****************************************************************************
1551 read from a file
1552 ****************************************************************************/
1553 int read_file(int fnum,char *data,int pos,int n)
1555 int ret=0,readret;
1557 if (!Files[fnum].can_write)
1559 ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n);
1561 data += ret;
1562 n -= ret;
1563 pos += ret;
1566 #if USE_MMAP
1567 if (Files[fnum].mmap_ptr)
1569 int num = MIN(n,Files[fnum].mmap_size-pos);
1570 if (num > 0)
1572 memcpy(data,Files[fnum].mmap_ptr+pos,num);
1573 data += num;
1574 pos += num;
1575 n -= num;
1576 ret += num;
1579 #endif
1581 if (n <= 0)
1582 return(ret);
1584 if (seek_file(fnum,pos) != pos)
1586 DEBUG(3,("Failed to seek to %d\n",pos));
1587 return(ret);
1590 if (n > 0) {
1591 readret = read(Files[fnum].fd_ptr->fd,data,n);
1592 if (readret > 0) ret += readret;
1595 return(ret);
1599 /****************************************************************************
1600 write to a file
1601 ****************************************************************************/
1602 int write_file(int fnum,char *data,int n)
1604 if (!Files[fnum].can_write) {
1605 errno = EPERM;
1606 return(0);
1609 if (!Files[fnum].modified) {
1610 struct stat st;
1611 Files[fnum].modified = True;
1612 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) {
1613 int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1614 if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {
1615 dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1620 return(write_data(Files[fnum].fd_ptr->fd,data,n));
1624 /****************************************************************************
1625 load parameters specific to a connection/service
1626 ****************************************************************************/
1627 BOOL become_service(int cnum,BOOL do_chdir)
1629 extern char magic_char;
1630 static int last_cnum = -1;
1631 int snum;
1633 if (!OPEN_CNUM(cnum))
1635 last_cnum = -1;
1636 return(False);
1639 Connections[cnum].lastused = smb_last_time;
1641 snum = SNUM(cnum);
1643 if (do_chdir &&
1644 ChDir(Connections[cnum].connectpath) != 0 &&
1645 ChDir(Connections[cnum].origpath) != 0)
1647 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1648 Connections[cnum].connectpath,cnum));
1649 return(False);
1652 if (cnum == last_cnum)
1653 return(True);
1655 last_cnum = cnum;
1657 case_default = lp_defaultcase(snum);
1658 case_preserve = lp_preservecase(snum);
1659 short_case_preserve = lp_shortpreservecase(snum);
1660 case_mangle = lp_casemangle(snum);
1661 case_sensitive = lp_casesensitive(snum);
1662 magic_char = lp_magicchar(snum);
1663 use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1664 return(True);
1668 /****************************************************************************
1669 find a service entry
1670 ****************************************************************************/
1671 int find_service(char *service)
1673 int iService;
1675 string_sub(service,"\\","/");
1677 iService = lp_servicenumber(service);
1679 /* now handle the special case of a home directory */
1680 if (iService < 0)
1682 char *phome_dir = get_home_dir(service);
1683 DEBUG(3,("checking for home directory %s gave %s\n",service,
1684 phome_dir?phome_dir:"(NULL)"));
1685 if (phome_dir)
1687 int iHomeService;
1688 if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1690 lp_add_home(service,iHomeService,phome_dir);
1691 iService = lp_servicenumber(service);
1696 /* If we still don't have a service, attempt to add it as a printer. */
1697 if (iService < 0)
1699 int iPrinterService;
1701 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1703 char *pszTemp;
1705 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1706 pszTemp = PRINTCAP;
1707 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
1709 DEBUG(3,("%s is a valid printer name\n", service));
1710 DEBUG(3,("adding %s as a printer service\n", service));
1711 lp_add_printer(service,iPrinterService);
1712 iService = lp_servicenumber(service);
1713 if (iService < 0)
1714 DEBUG(0,("failed to add %s as a printer service!\n", service));
1716 else
1717 DEBUG(3,("%s is not a valid printer name\n", service));
1721 /* just possibly it's a default service? */
1722 if (iService < 0)
1724 char *defservice = lp_defaultservice();
1725 if (defservice && *defservice && !strequal(defservice,service)) {
1726 iService = find_service(defservice);
1727 if (iService >= 0) {
1728 string_sub(service,"_","/");
1729 iService = lp_add_service(service,iService);
1734 if (iService >= 0)
1735 if (!VALID_SNUM(iService))
1737 DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1738 iService = -1;
1741 if (iService < 0)
1742 DEBUG(3,("find_service() failed to find service %s\n", service));
1744 return (iService);
1748 /****************************************************************************
1749 create an error packet from a cached error.
1750 ****************************************************************************/
1751 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
1753 write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
1755 int32 eclass = wbmpx->wr_errclass;
1756 int32 err = wbmpx->wr_error;
1758 /* We can now delete the auxiliary struct */
1759 free((char *)wbmpx);
1760 Files[fnum].wbmpx_ptr = NULL;
1761 return error_packet(inbuf,outbuf,eclass,err,line);
1765 struct
1767 int unixerror;
1768 int smbclass;
1769 int smbcode;
1770 } unix_smb_errmap[] =
1772 {EPERM,ERRDOS,ERRnoaccess},
1773 {EACCES,ERRDOS,ERRnoaccess},
1774 {ENOENT,ERRDOS,ERRbadfile},
1775 {EIO,ERRHRD,ERRgeneral},
1776 {EBADF,ERRSRV,ERRsrverror},
1777 {EINVAL,ERRSRV,ERRsrverror},
1778 {EEXIST,ERRDOS,ERRfilexists},
1779 {ENFILE,ERRDOS,ERRnofids},
1780 {EMFILE,ERRDOS,ERRnofids},
1781 {ENOSPC,ERRHRD,ERRdiskfull},
1782 #ifdef EDQUOT
1783 {EDQUOT,ERRHRD,ERRdiskfull},
1784 #endif
1785 #ifdef ENOTEMPTY
1786 {ENOTEMPTY,ERRDOS,ERRnoaccess},
1787 #endif
1788 #ifdef EXDEV
1789 {EXDEV,ERRDOS,ERRdiffdevice},
1790 #endif
1791 {EROFS,ERRHRD,ERRnowrite},
1792 {0,0,0}
1796 /****************************************************************************
1797 create an error packet from errno
1798 ****************************************************************************/
1799 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
1801 int eclass=def_class;
1802 int ecode=def_code;
1803 int i=0;
1805 if (unix_ERR_class != SUCCESS)
1807 eclass = unix_ERR_class;
1808 ecode = unix_ERR_code;
1809 unix_ERR_class = SUCCESS;
1810 unix_ERR_code = 0;
1812 else
1814 while (unix_smb_errmap[i].smbclass != 0)
1816 if (unix_smb_errmap[i].unixerror == errno)
1818 eclass = unix_smb_errmap[i].smbclass;
1819 ecode = unix_smb_errmap[i].smbcode;
1820 break;
1822 i++;
1826 return(error_packet(inbuf,outbuf,eclass,ecode,line));
1830 /****************************************************************************
1831 create an error packet. Normally called using the ERROR() macro
1832 ****************************************************************************/
1833 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
1835 int outsize = set_message(outbuf,0,0,True);
1836 int cmd;
1837 cmd = CVAL(inbuf,smb_com);
1839 CVAL(outbuf,smb_rcls) = error_class;
1840 SSVAL(outbuf,smb_err,error_code);
1842 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
1843 timestring(),
1844 line,
1845 (int)CVAL(inbuf,smb_com),
1846 smb_fn_name(CVAL(inbuf,smb_com)),
1847 error_class,
1848 error_code));
1850 if (errno != 0)
1851 DEBUG(3,("error string = %s\n",strerror(errno)));
1853 return(outsize);
1857 #ifndef SIGCLD_IGNORE
1858 /****************************************************************************
1859 this prevents zombie child processes
1860 ****************************************************************************/
1861 static int sig_cld()
1863 static int depth = 0;
1864 if (depth != 0)
1866 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
1867 depth=0;
1868 return(0);
1870 depth++;
1872 BlockSignals(True,SIGCLD);
1873 DEBUG(5,("got SIGCLD\n"));
1875 #ifdef USE_WAITPID
1876 while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
1877 #endif
1879 /* Stop zombies */
1880 /* Stevens, Adv. Unix Prog. says that on system V you must call
1881 wait before reinstalling the signal handler, because the kernel
1882 calls the handler from within the signal-call when there is a
1883 child that has exited. This would lead to an infinite recursion
1884 if done vice versa. */
1886 #ifndef DONT_REINSTALL_SIG
1887 #ifdef SIGCLD_IGNORE
1888 signal(SIGCLD, SIG_IGN);
1889 #else
1890 signal(SIGCLD, SIGNAL_CAST sig_cld);
1891 #endif
1892 #endif
1894 #ifndef USE_WAITPID
1895 while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
1896 #endif
1897 depth--;
1898 BlockSignals(False,SIGCLD);
1899 return 0;
1901 #endif
1903 /****************************************************************************
1904 this is called when the client exits abruptly
1905 **************************************************************************/
1906 static int sig_pipe()
1908 extern int password_client;
1909 BlockSignals(True,SIGPIPE);
1911 if (password_client != -1) {
1912 DEBUG(3,("lost connection to password server\n"));
1913 close(password_client);
1914 password_client = -1;
1915 #ifndef DONT_REINSTALL_SIG
1916 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1917 #endif
1918 BlockSignals(False,SIGPIPE);
1919 return 0;
1922 exit_server("Got sigpipe\n");
1923 return(0);
1926 /****************************************************************************
1927 open the socket communication
1928 ****************************************************************************/
1929 static BOOL open_sockets(BOOL is_daemon,int port)
1931 extern int Client;
1933 if (is_daemon)
1935 int s;
1936 struct sockaddr addr;
1937 int in_addrlen = sizeof(addr);
1939 /* Stop zombies */
1940 #ifdef SIGCLD_IGNORE
1941 signal(SIGCLD, SIG_IGN);
1942 #else
1943 signal(SIGCLD, SIGNAL_CAST sig_cld);
1944 #endif
1946 /* open an incoming socket */
1947 s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
1948 if (s == -1)
1949 return(False);
1951 /* ready to listen */
1952 if (listen(s, 5) == -1)
1954 DEBUG(0,("listen: %s",strerror(errno)));
1955 close(s);
1956 return False;
1959 if(atexit_set == 0)
1960 atexit(killkids);
1962 /* now accept incoming connections - forking a new process
1963 for each incoming connection */
1964 DEBUG(2,("waiting for a connection\n"));
1965 while (1)
1967 Client = accept(s,&addr,&in_addrlen);
1969 if (Client == -1 && errno == EINTR)
1970 continue;
1972 if (Client == -1)
1974 DEBUG(0,("accept: %s",strerror(errno)));
1975 continue;
1978 #ifdef NO_FORK_DEBUG
1979 #ifndef NO_SIGNAL_TEST
1980 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1981 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
1982 #endif
1983 return True;
1984 #else
1985 if (Client != -1 && fork()==0)
1987 #ifndef NO_SIGNAL_TEST
1988 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1989 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
1990 #endif
1991 /* close the listening socket */
1992 close(s);
1994 /* close our standard file descriptors */
1995 close_low_fds();
1996 am_parent = 0;
1998 set_socket_options(Client,"SO_KEEPALIVE");
1999 set_socket_options(Client,user_socket_options);
2001 return True;
2003 close(Client); /* The parent doesn't need this socket */
2004 #endif
2007 else
2009 /* We will abort gracefully when the client or remote system
2010 goes away */
2011 #ifndef NO_SIGNAL_TEST
2012 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2013 #endif
2014 Client = dup(0);
2016 /* close our standard file descriptors */
2017 close_low_fds();
2019 set_socket_options(Client,"SO_KEEPALIVE");
2020 set_socket_options(Client,user_socket_options);
2023 return True;
2027 /****************************************************************************
2028 check if a snum is in use
2029 ****************************************************************************/
2030 BOOL snum_used(int snum)
2032 int i;
2033 for (i=0;i<MAX_CONNECTIONS;i++)
2034 if (OPEN_CNUM(i) && (SNUM(i) == snum))
2035 return(True);
2036 return(False);
2039 /****************************************************************************
2040 reload the services file
2041 **************************************************************************/
2042 BOOL reload_services(BOOL test)
2044 BOOL ret;
2046 if (lp_loaded())
2048 pstring fname;
2049 strcpy(fname,lp_configfile());
2050 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
2052 strcpy(servicesf,fname);
2053 test = False;
2057 reopen_logs();
2059 if (test && !lp_file_list_changed())
2060 return(True);
2062 lp_killunused(snum_used);
2064 ret = lp_load(servicesf,False);
2066 /* perhaps the config filename is now set */
2067 if (!test)
2068 reload_services(True);
2070 reopen_logs();
2072 load_interfaces();
2075 extern int Client;
2076 if (Client != -1) {
2077 set_socket_options(Client,"SO_KEEPALIVE");
2078 set_socket_options(Client,user_socket_options);
2082 create_mangled_stack(lp_mangledstack());
2084 /* this forces service parameters to be flushed */
2085 become_service(-1,True);
2087 return(ret);
2092 /****************************************************************************
2093 this prevents zombie child processes
2094 ****************************************************************************/
2095 static int sig_hup()
2097 BlockSignals(True,SIGHUP);
2098 DEBUG(0,("Got SIGHUP\n"));
2099 reload_services(False);
2100 #ifndef DONT_REINSTALL_SIG
2101 signal(SIGHUP,SIGNAL_CAST sig_hup);
2102 #endif
2103 BlockSignals(False,SIGHUP);
2104 return(0);
2107 /****************************************************************************
2108 Setup the groups a user belongs to.
2109 ****************************************************************************/
2110 int setup_groups(char *user, int uid, int gid, int *p_ngroups,
2111 int **p_igroups, gid_t **p_groups)
2113 if (-1 == initgroups(user,gid))
2115 if (getuid() == 0)
2117 DEBUG(0,("Unable to initgroups!\n"));
2118 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
2119 DEBUG(0,("This is probably a problem with the account %s\n",user));
2122 else
2124 int i,ngroups;
2125 int *igroups;
2126 gid_t grp = 0;
2127 ngroups = getgroups(0,&grp);
2128 if (ngroups <= 0)
2129 ngroups = 32;
2130 igroups = (int *)malloc(sizeof(int)*ngroups);
2131 for (i=0;i<ngroups;i++)
2132 igroups[i] = 0x42424242;
2133 ngroups = getgroups(ngroups,(gid_t *)igroups);
2135 if (igroups[0] == 0x42424242)
2136 ngroups = 0;
2138 *p_ngroups = ngroups;
2140 /* The following bit of code is very strange. It is due to the
2141 fact that some OSes use int* and some use gid_t* for
2142 getgroups, and some (like SunOS) use both, one in prototypes,
2143 and one in man pages and the actual code. Thus we detect it
2144 dynamically using some very ugly code */
2145 if (ngroups > 0)
2147 /* does getgroups return ints or gid_t ?? */
2148 static BOOL groups_use_ints = True;
2150 if (groups_use_ints &&
2151 ngroups == 1 &&
2152 SVAL(igroups,2) == 0x4242)
2153 groups_use_ints = False;
2155 for (i=0;groups_use_ints && i<ngroups;i++)
2156 if (igroups[i] == 0x42424242)
2157 groups_use_ints = False;
2159 if (groups_use_ints)
2161 *p_igroups = igroups;
2162 *p_groups = (gid_t *)igroups;
2164 else
2166 gid_t *groups = (gid_t *)igroups;
2167 igroups = (int *)malloc(sizeof(int)*ngroups);
2168 for (i=0;i<ngroups;i++)
2169 igroups[i] = groups[i];
2170 *p_igroups = igroups;
2171 *p_groups = (gid_t *)groups;
2174 DEBUG(3,("%s is in %d groups\n",user,ngroups));
2175 for (i=0;i<ngroups;i++)
2176 DEBUG(3,("%d ",igroups[i]));
2177 DEBUG(3,("\n"));
2179 return 0;
2182 /****************************************************************************
2183 make a connection to a service
2184 ****************************************************************************/
2185 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid)
2187 int cnum;
2188 int snum;
2189 struct passwd *pass = NULL;
2190 connection_struct *pcon;
2191 BOOL guest = False;
2192 BOOL force = False;
2193 static BOOL first_connection = True;
2195 strlower(service);
2197 snum = find_service(service);
2198 if (snum < 0)
2200 if (strequal(service,"IPC$"))
2202 DEBUG(3,("%s refusing IPC connection\n",timestring()));
2203 return(-3);
2206 DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
2207 return(-2);
2210 if (strequal(service,HOMES_NAME))
2212 if (*user && Get_Pwnam(user,True))
2213 return(make_connection(user,user,password,pwlen,dev,vuid));
2215 if (validated_username(vuid))
2217 strcpy(user,validated_username(vuid));
2218 return(make_connection(user,user,password,pwlen,dev,vuid));
2222 if (!lp_snum_ok(snum) || !check_access(snum)) {
2223 return(-4);
2226 /* you can only connect to the IPC$ service as an ipc device */
2227 if (strequal(service,"IPC$"))
2228 strcpy(dev,"IPC");
2230 if (*dev == '?' || !*dev)
2232 if (lp_print_ok(snum))
2233 strcpy(dev,"LPT1:");
2234 else
2235 strcpy(dev,"A:");
2238 /* if the request is as a printer and you can't print then refuse */
2239 strupper(dev);
2240 if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
2241 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
2242 return(-6);
2245 /* lowercase the user name */
2246 strlower(user);
2248 /* add it as a possible user name */
2249 add_session_user(service);
2251 /* shall we let them in? */
2252 if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
2254 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
2255 return(-1);
2258 cnum = find_free_connection(str_checksum(service) + str_checksum(user));
2259 if (cnum < 0)
2261 DEBUG(0,("%s couldn't find free connection\n",timestring()));
2262 return(-1);
2265 pcon = &Connections[cnum];
2266 bzero((char *)pcon,sizeof(*pcon));
2268 /* find out some info about the user */
2269 pass = Get_Pwnam(user,True);
2271 if (pass == NULL)
2273 DEBUG(0,("%s couldn't find account %s\n",timestring(),user));
2274 return(-7);
2277 pcon->read_only = lp_readonly(snum);
2280 pstring list;
2281 StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
2282 string_sub(list,"%S",service);
2284 if (user_in_list(user,list))
2285 pcon->read_only = True;
2287 StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
2288 string_sub(list,"%S",service);
2290 if (user_in_list(user,list))
2291 pcon->read_only = False;
2294 /* admin user check */
2295 if (user_in_list(user,lp_admin_users(snum)) &&
2296 !pcon->read_only)
2298 pcon->admin_user = True;
2299 DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2301 else
2302 pcon->admin_user = False;
2304 pcon->force_user = force;
2305 pcon->vuid = vuid;
2306 pcon->uid = pass->pw_uid;
2307 pcon->gid = pass->pw_gid;
2308 pcon->num_files_open = 0;
2309 pcon->lastused = time(NULL);
2310 pcon->service = snum;
2311 pcon->used = True;
2312 pcon->printer = (strncmp(dev,"LPT",3) == 0);
2313 pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2314 pcon->dirptr = NULL;
2315 string_set(&pcon->dirpath,"");
2316 string_set(&pcon->user,user);
2318 #if HAVE_GETGRNAM
2319 if (*lp_force_group(snum))
2321 struct group *gptr;
2322 pstring gname;
2324 StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1);
2325 /* default service may be a group name */
2326 string_sub(gname,"%S",service);
2327 gptr = (struct group *)getgrnam(gname);
2329 if (gptr)
2331 pcon->gid = gptr->gr_gid;
2332 DEBUG(3,("Forced group %s\n",gname));
2334 else
2335 DEBUG(1,("Couldn't find group %s\n",gname));
2337 #endif
2339 if (*lp_force_user(snum))
2341 struct passwd *pass2;
2342 fstring fuser;
2343 strcpy(fuser,lp_force_user(snum));
2344 pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2345 if (pass2)
2347 pcon->uid = pass2->pw_uid;
2348 string_set(&pcon->user,fuser);
2349 strcpy(user,fuser);
2350 pcon->force_user = True;
2351 DEBUG(3,("Forced user %s\n",fuser));
2353 else
2354 DEBUG(1,("Couldn't find user %s\n",fuser));
2358 pstring s;
2359 strcpy(s,lp_pathname(snum));
2360 standard_sub(cnum,s);
2361 string_set(&pcon->connectpath,s);
2362 DEBUG(3,("Connect path is %s\n",s));
2365 /* groups stuff added by ih */
2366 pcon->ngroups = 0;
2367 pcon->groups = NULL;
2369 if (!IS_IPC(cnum))
2371 /* Find all the groups this uid is in and store them. Used by become_user() */
2372 setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2374 /* check number of connections */
2375 if (!claim_connection(cnum,
2376 lp_servicename(SNUM(cnum)),
2377 lp_max_connections(SNUM(cnum)),False))
2379 DEBUG(1,("too many connections - rejected\n"));
2380 return(-8);
2383 if (lp_status(SNUM(cnum)))
2384 claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2386 first_connection = False;
2387 } /* IS_IPC */
2389 pcon->open = True;
2391 /* execute any "root preexec = " line */
2392 if (*lp_rootpreexec(SNUM(cnum)))
2394 pstring cmd;
2395 strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2396 standard_sub(cnum,cmd);
2397 DEBUG(5,("cmd=%s\n",cmd));
2398 smbrun(cmd,NULL,False);
2401 if (!become_user(cnum,pcon->vuid))
2403 DEBUG(0,("Can't become connected user!\n"));
2404 pcon->open = False;
2405 if (!IS_IPC(cnum)) {
2406 yield_connection(cnum,
2407 lp_servicename(SNUM(cnum)),
2408 lp_max_connections(SNUM(cnum)));
2409 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2411 return(-1);
2414 if (ChDir(pcon->connectpath) != 0)
2416 DEBUG(0,("Can't change directory to %s (%s)\n",
2417 pcon->connectpath,strerror(errno)));
2418 pcon->open = False;
2419 unbecome_user();
2420 if (!IS_IPC(cnum)) {
2421 yield_connection(cnum,
2422 lp_servicename(SNUM(cnum)),
2423 lp_max_connections(SNUM(cnum)));
2424 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2426 return(-5);
2429 string_set(&pcon->origpath,pcon->connectpath);
2431 #if SOFTLINK_OPTIMISATION
2432 /* resolve any soft links early */
2434 pstring s;
2435 strcpy(s,pcon->connectpath);
2436 GetWd(s);
2437 string_set(&pcon->connectpath,s);
2438 ChDir(pcon->connectpath);
2440 #endif
2442 num_connections_open++;
2443 add_session_user(user);
2445 /* execute any "preexec = " line */
2446 if (*lp_preexec(SNUM(cnum)))
2448 pstring cmd;
2449 strcpy(cmd,lp_preexec(SNUM(cnum)));
2450 standard_sub(cnum,cmd);
2451 smbrun(cmd,NULL,False);
2454 /* we've finished with the sensitive stuff */
2455 unbecome_user();
2458 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2459 timestring(),
2460 remote_machine,
2461 client_addr(),
2462 lp_servicename(SNUM(cnum)),user,
2463 pcon->uid,
2464 pcon->gid,
2465 (int)getpid()));
2468 return(cnum);
2472 /****************************************************************************
2473 find first available file slot
2474 ****************************************************************************/
2475 int find_free_file(void )
2477 int i;
2478 /* we start at 1 here for an obscure reason I can't now remember,
2479 but I think is important :-) */
2480 for (i=1;i<MAX_OPEN_FILES;i++)
2481 if (!Files[i].open)
2482 return(i);
2483 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2484 return(-1);
2487 /****************************************************************************
2488 find first available connection slot, starting from a random position.
2489 The randomisation stops problems with the server dieing and clients
2490 thinking the server is still available.
2491 ****************************************************************************/
2492 static int find_free_connection(int hash )
2494 int i;
2495 BOOL used=False;
2496 hash = (hash % (MAX_CONNECTIONS-2))+1;
2498 again:
2500 for (i=hash+1;i!=hash;)
2502 if (!Connections[i].open && Connections[i].used == used)
2504 DEBUG(3,("found free connection number %d\n",i));
2505 return(i);
2507 i++;
2508 if (i == MAX_CONNECTIONS)
2509 i = 1;
2512 if (!used)
2514 used = !used;
2515 goto again;
2518 DEBUG(1,("ERROR! Out of connection structures\n"));
2519 return(-1);
2523 /****************************************************************************
2524 reply for the core protocol
2525 ****************************************************************************/
2526 int reply_corep(char *outbuf)
2528 int outsize = set_message(outbuf,1,0,True);
2530 Protocol = PROTOCOL_CORE;
2532 return outsize;
2536 /****************************************************************************
2537 reply for the coreplus protocol
2538 ****************************************************************************/
2539 int reply_coreplus(char *outbuf)
2541 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2542 int outsize = set_message(outbuf,13,0,True);
2543 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2544 readbraw and writebraw (possibly) */
2545 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2546 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
2548 Protocol = PROTOCOL_COREPLUS;
2550 return outsize;
2554 /****************************************************************************
2555 reply for the lanman 1.0 protocol
2556 ****************************************************************************/
2557 int reply_lanman1(char *outbuf)
2559 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2560 int secword=0;
2561 BOOL doencrypt = SMBENCRYPT();
2562 time_t t = time(NULL);
2564 if (lp_security()>=SEC_USER) secword |= 1;
2565 if (doencrypt) secword |= 2;
2567 set_message(outbuf,13,doencrypt?8:0,True);
2568 SSVAL(outbuf,smb_vwv1,secword);
2569 #ifdef SMB_PASSWD
2570 /* Create a token value and add it to the outgoing packet. */
2571 if (doencrypt)
2572 generate_next_challenge(smb_buf(outbuf));
2573 #endif
2575 Protocol = PROTOCOL_LANMAN1;
2577 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2578 DEBUG(3,("using password server validation\n"));
2579 #ifdef SMB_PASSWD
2580 if (doencrypt) set_challenge(smb_buf(outbuf));
2581 #endif
2584 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2585 SSVAL(outbuf,smb_vwv2,maxxmit);
2586 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2587 SSVAL(outbuf,smb_vwv4,1);
2588 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2589 readbraw writebraw (possibly) */
2590 SIVAL(outbuf,smb_vwv6,getpid());
2591 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2593 put_dos_date(outbuf,smb_vwv8,t);
2595 return (smb_len(outbuf)+4);
2599 /****************************************************************************
2600 reply for the lanman 2.0 protocol
2601 ****************************************************************************/
2602 int reply_lanman2(char *outbuf)
2604 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2605 int secword=0;
2606 BOOL doencrypt = SMBENCRYPT();
2607 time_t t = time(NULL);
2609 if (lp_security()>=SEC_USER) secword |= 1;
2610 if (doencrypt) secword |= 2;
2612 set_message(outbuf,13,doencrypt?8:0,True);
2613 SSVAL(outbuf,smb_vwv1,secword);
2614 #ifdef SMB_PASSWD
2615 /* Create a token value and add it to the outgoing packet. */
2616 if (doencrypt)
2617 generate_next_challenge(smb_buf(outbuf));
2618 #endif
2620 SIVAL(outbuf,smb_vwv6,getpid());
2622 Protocol = PROTOCOL_LANMAN2;
2624 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2625 DEBUG(3,("using password server validation\n"));
2626 #ifdef SMB_PASSWD
2627 if (doencrypt) set_challenge(smb_buf(outbuf));
2628 #endif
2631 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2632 SSVAL(outbuf,smb_vwv2,maxxmit);
2633 SSVAL(outbuf,smb_vwv3,lp_maxmux());
2634 SSVAL(outbuf,smb_vwv4,1);
2635 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2636 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2637 put_dos_date(outbuf,smb_vwv8,t);
2639 return (smb_len(outbuf)+4);
2642 /****************************************************************************
2643 reply for the nt protocol
2644 ****************************************************************************/
2645 int reply_nt1(char *outbuf)
2647 int capabilities=0x300; /* has dual names + lock_and_read */
2648 int secword=0;
2649 BOOL doencrypt = SMBENCRYPT();
2650 time_t t = time(NULL);
2652 if (lp_security()>=SEC_USER) secword |= 1;
2653 if (doencrypt) secword |= 2;
2655 set_message(outbuf,17,doencrypt?8:0,True);
2656 CVAL(outbuf,smb_vwv1) = secword;
2657 #ifdef SMB_PASSWD
2658 /* Create a token value and add it to the outgoing packet. */
2659 if (doencrypt) {
2660 generate_next_challenge(smb_buf(outbuf));
2661 /* Tell the nt machine how long the challenge is. */
2662 SSVALS(outbuf,smb_vwv16+1,8);
2664 #endif
2666 SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2668 Protocol = PROTOCOL_NT1;
2670 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2671 DEBUG(3,("using password server validation\n"));
2672 #ifdef SMB_PASSWD
2673 if (doencrypt) set_challenge(smb_buf(outbuf));
2674 #endif
2677 if (lp_readraw() && lp_writeraw())
2678 capabilities |= 1;
2680 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2681 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2682 SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */
2683 SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */
2684 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2685 put_long_date(outbuf+smb_vwv11+1,t);
2686 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
2688 return (smb_len(outbuf)+4);
2692 /* these are the protocol lists used for auto architecture detection:
2694 WinNT 3.51:
2695 protocol [PC NETWORK PROGRAM 1.0]
2696 protocol [XENIX CORE]
2697 protocol [MICROSOFT NETWORKS 1.03]
2698 protocol [LANMAN1.0]
2699 protocol [Windows for Workgroups 3.1a]
2700 protocol [LM1.2X002]
2701 protocol [LANMAN2.1]
2702 protocol [NT LM 0.12]
2704 Win95:
2705 protocol [PC NETWORK PROGRAM 1.0]
2706 protocol [XENIX CORE]
2707 protocol [MICROSOFT NETWORKS 1.03]
2708 protocol [LANMAN1.0]
2709 protocol [Windows for Workgroups 3.1a]
2710 protocol [LM1.2X002]
2711 protocol [LANMAN2.1]
2712 protocol [NT LM 0.12]
2714 OS/2:
2715 protocol [PC NETWORK PROGRAM 1.0]
2716 protocol [XENIX CORE]
2717 protocol [LANMAN1.0]
2718 protocol [LM1.2X002]
2719 protocol [LANMAN2.1]
2723 * Modified to recognize the architecture of the remote machine better.
2725 * This appears to be the matrix of which protocol is used by which
2726 * MS product.
2727 Protocol WfWg Win95 WinNT OS/2
2728 PC NETWORK PROGRAM 1.0 1 1 1 1
2729 XENIX CORE 2 2
2730 MICROSOFT NETWORKS 3.0 2 2
2731 DOS LM1.2X002 3 3
2732 MICROSOFT NETWORKS 1.03 3
2733 DOS LANMAN2.1 4 4
2734 LANMAN1.0 4 3
2735 Windows for Workgroups 3.1a 5 5 5
2736 LM1.2X002 6 4
2737 LANMAN2.1 7 5
2738 NT LM 0.12 6 8
2740 * tim@fsg.com 09/29/95
2743 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
2744 #define ARCH_WIN95 0x2
2745 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
2746 #define ARCH_WINNT 0x8
2747 #define ARCH_SAMBA 0x10
2749 #define ARCH_ALL 0x1F
2751 /* List of supported protocols, most desired first */
2752 struct {
2753 char *proto_name;
2754 char *short_name;
2755 int (*proto_reply_fn)(char *);
2756 int protocol_level;
2757 } supported_protocols[] = {
2758 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
2759 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
2760 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2761 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2762 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2763 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2764 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2765 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
2766 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
2767 {NULL,NULL},
2771 /****************************************************************************
2772 reply to a negprot
2773 ****************************************************************************/
2774 static int reply_negprot(char *inbuf,char *outbuf)
2776 extern fstring remote_arch;
2777 int outsize = set_message(outbuf,1,0,True);
2778 int Index=0;
2779 int choice= -1;
2780 int protocol;
2781 char *p;
2782 int bcc = SVAL(smb_buf(inbuf),-2);
2783 int arch = ARCH_ALL;
2785 p = smb_buf(inbuf)+1;
2786 while (p < (smb_buf(inbuf) + bcc))
2788 Index++;
2789 DEBUG(3,("Requested protocol [%s]\n",p));
2790 if (strcsequal(p,"Windows for Workgroups 3.1a"))
2791 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
2792 else if (strcsequal(p,"DOS LM1.2X002"))
2793 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2794 else if (strcsequal(p,"DOS LANMAN2.1"))
2795 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2796 else if (strcsequal(p,"NT LM 0.12"))
2797 arch &= ( ARCH_WIN95 | ARCH_WINNT );
2798 else if (strcsequal(p,"LANMAN2.1"))
2799 arch &= ( ARCH_WINNT | ARCH_OS2 );
2800 else if (strcsequal(p,"LM1.2X002"))
2801 arch &= ( ARCH_WINNT | ARCH_OS2 );
2802 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
2803 arch &= ARCH_WINNT;
2804 else if (strcsequal(p,"XENIX CORE"))
2805 arch &= ( ARCH_WINNT | ARCH_OS2 );
2806 else if (strcsequal(p,"Samba")) {
2807 arch = ARCH_SAMBA;
2808 break;
2811 p += strlen(p) + 2;
2814 switch ( arch ) {
2815 case ARCH_SAMBA:
2816 strcpy(remote_arch,"Samba");
2817 break;
2818 case ARCH_WFWG:
2819 strcpy(remote_arch,"WfWg");
2820 break;
2821 case ARCH_WIN95:
2822 strcpy(remote_arch,"Win95");
2823 break;
2824 case ARCH_WINNT:
2825 strcpy(remote_arch,"WinNT");
2826 break;
2827 case ARCH_OS2:
2828 strcpy(remote_arch,"OS2");
2829 break;
2830 default:
2831 strcpy(remote_arch,"UNKNOWN");
2832 break;
2835 /* possibly reload - change of architecture */
2836 reload_services(True);
2838 /* a special case to stop password server loops */
2839 if (Index == 1 && strequal(remote_machine,myhostname) &&
2840 lp_security()==SEC_SERVER)
2841 exit_server("Password server loop!");
2843 /* Check for protocols, most desirable first */
2844 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
2846 p = smb_buf(inbuf)+1;
2847 Index = 0;
2848 if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
2849 while (p < (smb_buf(inbuf) + bcc))
2851 if (strequal(p,supported_protocols[protocol].proto_name))
2852 choice = Index;
2853 Index++;
2854 p += strlen(p) + 2;
2856 if(choice != -1)
2857 break;
2860 SSVAL(outbuf,smb_vwv0,choice);
2861 if(choice != -1) {
2862 extern fstring remote_proto;
2863 strcpy(remote_proto,supported_protocols[protocol].short_name);
2864 reload_services(True);
2865 outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
2866 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
2868 else {
2869 DEBUG(0,("No protocol supported !\n"));
2871 SSVAL(outbuf,smb_vwv0,choice);
2873 DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
2875 return(outsize);
2879 /****************************************************************************
2880 close all open files for a connection
2881 ****************************************************************************/
2882 static void close_open_files(int cnum)
2884 int i;
2885 for (i=0;i<MAX_OPEN_FILES;i++)
2886 if( Files[i].cnum == cnum && Files[i].open) {
2887 close_file(i);
2893 /****************************************************************************
2894 close a cnum
2895 ****************************************************************************/
2896 void close_cnum(int cnum, uint16 vuid)
2898 DirCacheFlush(SNUM(cnum));
2900 unbecome_user();
2902 if (!OPEN_CNUM(cnum))
2904 DEBUG(0,("Can't close cnum %d\n",cnum));
2905 return;
2908 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
2909 timestring(),
2910 remote_machine,client_addr(),
2911 lp_servicename(SNUM(cnum))));
2913 yield_connection(cnum,
2914 lp_servicename(SNUM(cnum)),
2915 lp_max_connections(SNUM(cnum)));
2917 if (lp_status(SNUM(cnum)))
2918 yield_connection(cnum,"STATUS.",MAXSTATUS);
2920 close_open_files(cnum);
2921 dptr_closecnum(cnum);
2923 /* execute any "postexec = " line */
2924 if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid))
2926 pstring cmd;
2927 strcpy(cmd,lp_postexec(SNUM(cnum)));
2928 standard_sub(cnum,cmd);
2929 smbrun(cmd,NULL,False);
2930 unbecome_user();
2933 unbecome_user();
2934 /* execute any "root postexec = " line */
2935 if (*lp_rootpostexec(SNUM(cnum)))
2937 pstring cmd;
2938 strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
2939 standard_sub(cnum,cmd);
2940 smbrun(cmd,NULL,False);
2943 Connections[cnum].open = False;
2944 num_connections_open--;
2945 if (Connections[cnum].ngroups && Connections[cnum].groups)
2947 if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
2948 free(Connections[cnum].groups);
2949 free(Connections[cnum].igroups);
2950 Connections[cnum].groups = NULL;
2951 Connections[cnum].igroups = NULL;
2952 Connections[cnum].ngroups = 0;
2955 string_set(&Connections[cnum].user,"");
2956 string_set(&Connections[cnum].dirpath,"");
2957 string_set(&Connections[cnum].connectpath,"");
2961 /****************************************************************************
2962 simple routines to do connection counting
2963 ****************************************************************************/
2964 BOOL yield_connection(int cnum,char *name,int max_connections)
2966 struct connect_record crec;
2967 pstring fname;
2968 FILE *f;
2969 int mypid = getpid();
2970 int i;
2972 DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
2974 if (max_connections <= 0)
2975 return(True);
2977 bzero(&crec,sizeof(crec));
2979 strcpy(fname,lp_lockdir());
2980 standard_sub(cnum,fname);
2981 trim_string(fname,"","/");
2983 strcat(fname,"/");
2984 strcat(fname,name);
2985 strcat(fname,".LCK");
2987 f = fopen(fname,"r+");
2988 if (!f)
2990 DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
2991 return(False);
2994 fseek(f,0,SEEK_SET);
2996 /* find a free spot */
2997 for (i=0;i<max_connections;i++)
2999 if (fread(&crec,sizeof(crec),1,f) != 1)
3001 DEBUG(2,("Entry not found in lock file %s\n",fname));
3002 fclose(f);
3003 return(False);
3005 if (crec.pid == mypid && crec.cnum == cnum)
3006 break;
3009 if (crec.pid != mypid || crec.cnum != cnum)
3011 fclose(f);
3012 DEBUG(2,("Entry not found in lock file %s\n",fname));
3013 return(False);
3016 bzero((void *)&crec,sizeof(crec));
3018 /* remove our mark */
3019 if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3020 fwrite(&crec,sizeof(crec),1,f) != 1)
3022 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
3023 fclose(f);
3024 return(False);
3027 DEBUG(3,("Yield successful\n"));
3029 fclose(f);
3030 return(True);
3034 /****************************************************************************
3035 simple routines to do connection counting
3036 ****************************************************************************/
3037 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
3039 struct connect_record crec;
3040 pstring fname;
3041 FILE *f;
3042 int snum = SNUM(cnum);
3043 int i,foundi= -1;
3044 int total_recs;
3046 if (max_connections <= 0)
3047 return(True);
3049 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
3051 strcpy(fname,lp_lockdir());
3052 standard_sub(cnum,fname);
3053 trim_string(fname,"","/");
3055 if (!directory_exist(fname,NULL))
3056 mkdir(fname,0755);
3058 strcat(fname,"/");
3059 strcat(fname,name);
3060 strcat(fname,".LCK");
3062 if (!file_exist(fname,NULL))
3064 int oldmask = umask(022);
3065 f = fopen(fname,"w");
3066 if (f) fclose(f);
3067 umask(oldmask);
3070 total_recs = file_size(fname) / sizeof(crec);
3072 f = fopen(fname,"r+");
3074 if (!f)
3076 DEBUG(1,("couldn't open lock file %s\n",fname));
3077 return(False);
3080 /* find a free spot */
3081 for (i=0;i<max_connections;i++)
3084 if (i>=total_recs ||
3085 fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3086 fread(&crec,sizeof(crec),1,f) != 1)
3088 if (foundi < 0) foundi = i;
3089 break;
3092 if (Clear && crec.pid && !process_exists(crec.pid))
3094 fseek(f,i*sizeof(crec),SEEK_SET);
3095 bzero((void *)&crec,sizeof(crec));
3096 fwrite(&crec,sizeof(crec),1,f);
3097 if (foundi < 0) foundi = i;
3098 continue;
3100 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
3102 foundi=i;
3103 if (!Clear) break;
3107 if (foundi < 0)
3109 DEBUG(3,("no free locks in %s\n",fname));
3110 fclose(f);
3111 return(False);
3114 /* fill in the crec */
3115 bzero((void *)&crec,sizeof(crec));
3116 crec.magic = 0x280267;
3117 crec.pid = getpid();
3118 crec.cnum = cnum;
3119 crec.uid = Connections[cnum].uid;
3120 crec.gid = Connections[cnum].gid;
3121 StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
3122 crec.start = time(NULL);
3124 StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
3125 StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1);
3127 /* make our mark */
3128 if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
3129 fwrite(&crec,sizeof(crec),1,f) != 1)
3131 fclose(f);
3132 return(False);
3135 fclose(f);
3136 return(True);
3139 #if DUMP_CORE
3140 /*******************************************************************
3141 prepare to dump a core file - carefully!
3142 ********************************************************************/
3143 static BOOL dump_core(void)
3145 char *p;
3146 pstring dname;
3147 strcpy(dname,debugf);
3148 if ((p=strrchr(dname,'/'))) *p=0;
3149 strcat(dname,"/corefiles");
3150 mkdir(dname,0700);
3151 sys_chown(dname,getuid(),getgid());
3152 chmod(dname,0700);
3153 if (chdir(dname)) return(False);
3154 umask(~(0700));
3156 #ifndef NO_GETRLIMIT
3157 #ifdef RLIMIT_CORE
3159 struct rlimit rlp;
3160 getrlimit(RLIMIT_CORE, &rlp);
3161 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
3162 setrlimit(RLIMIT_CORE, &rlp);
3163 getrlimit(RLIMIT_CORE, &rlp);
3164 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
3166 #endif
3167 #endif
3170 DEBUG(0,("Dumping core in %s\n",dname));
3171 return(True);
3173 #endif
3175 /****************************************************************************
3176 exit the server
3177 ****************************************************************************/
3178 void exit_server(char *reason)
3180 static int firsttime=1;
3181 int i;
3183 if (!firsttime) exit(0);
3184 firsttime = 0;
3186 unbecome_user();
3187 DEBUG(2,("Closing connections\n"));
3188 for (i=0;i<MAX_CONNECTIONS;i++)
3189 if (Connections[i].open)
3190 close_cnum(i,-1);
3191 #ifdef DFS_AUTH
3192 if (dcelogin_atmost_once)
3193 dfs_unlogin();
3194 #endif
3195 if (!reason) {
3196 int oldlevel = DEBUGLEVEL;
3197 DEBUGLEVEL = 10;
3198 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
3199 if (last_inbuf)
3200 show_msg(last_inbuf);
3201 DEBUGLEVEL = oldlevel;
3202 DEBUG(0,("===============================================================\n"));
3203 #if DUMP_CORE
3204 if (dump_core()) return;
3205 #endif
3208 #if FAST_SHARE_MODES
3209 stop_share_mode_mgmt();
3210 #endif
3212 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
3213 exit(0);
3216 /****************************************************************************
3217 do some standard substitutions in a string
3218 ****************************************************************************/
3219 void standard_sub(int cnum,char *s)
3221 if (!strchr(s,'%')) return;
3223 if (VALID_CNUM(cnum))
3225 string_sub(s,"%S",lp_servicename(Connections[cnum].service));
3226 string_sub(s,"%P",Connections[cnum].connectpath);
3227 string_sub(s,"%u",Connections[cnum].user);
3228 if (strstr(s,"%H")) {
3229 char *home = get_home_dir(Connections[cnum].user);
3230 if (home) string_sub(s,"%H",home);
3232 string_sub(s,"%g",gidtoname(Connections[cnum].gid));
3234 standard_sub_basic(s);
3238 These flags determine some of the permissions required to do an operation
3240 Note that I don't set NEED_WRITE on some write operations because they
3241 are used by some brain-dead clients when printing, and I don't want to
3242 force write permissions on print services.
3244 #define AS_USER (1<<0)
3245 #define NEED_WRITE (1<<1)
3246 #define TIME_INIT (1<<2)
3247 #define CAN_IPC (1<<3)
3248 #define AS_GUEST (1<<5)
3252 define a list of possible SMB messages and their corresponding
3253 functions. Any message that has a NULL function is unimplemented -
3254 please feel free to contribute implementations!
3256 struct smb_message_struct
3258 int code;
3259 char *name;
3260 int (*fn)();
3261 int flags;
3262 #if PROFILING
3263 unsigned long time;
3264 #endif
3266 smb_messages[] = {
3268 /* CORE PROTOCOL */
3270 {SMBnegprot,"SMBnegprot",reply_negprot,0},
3271 {SMBtcon,"SMBtcon",reply_tcon,0},
3272 {SMBtdis,"SMBtdis",reply_tdis,0},
3273 {SMBexit,"SMBexit",reply_exit,0},
3274 {SMBioctl,"SMBioctl",reply_ioctl,0},
3275 {SMBecho,"SMBecho",reply_echo,0},
3276 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
3277 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
3278 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
3279 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3280 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3281 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3282 {SMBsearch,"SMBsearch",reply_search,AS_USER},
3283 {SMBopen,"SMBopen",reply_open,AS_USER},
3285 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3286 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3287 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
3289 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3290 {SMBread,"SMBread",reply_read,AS_USER},
3291 {SMBwrite,"SMBwrite",reply_write,AS_USER},
3292 {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
3293 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3294 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3295 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3296 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3298 /* this is a Pathworks specific call, allowing the
3299 changing of the root path */
3300 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
3302 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3303 {SMBflush,"SMBflush",reply_flush,AS_USER},
3304 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3305 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3306 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3307 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST},
3308 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3309 {SMBlock,"SMBlock",reply_lock,AS_USER},
3310 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3312 /* CORE+ PROTOCOL FOLLOWS */
3314 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3315 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3316 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3317 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3318 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3320 /* LANMAN1.0 PROTOCOL FOLLOWS */
3322 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3323 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3324 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3325 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3326 {SMBwritec,"SMBwritec",NULL,AS_USER},
3327 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3328 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3329 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3330 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3331 {SMBioctls,"SMBioctls",NULL,AS_USER},
3332 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3333 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3335 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC},
3336 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3337 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3338 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3340 {SMBffirst,"SMBffirst",reply_search,AS_USER},
3341 {SMBfunique,"SMBfunique",reply_search,AS_USER},
3342 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3344 /* LANMAN2.0 PROTOCOL FOLLOWS */
3345 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3346 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3347 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3348 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3350 /* messaging routines */
3351 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3352 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3353 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3354 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3356 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3358 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3359 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3360 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3361 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3364 /****************************************************************************
3365 return a string containing the function name of a SMB command
3366 ****************************************************************************/
3367 char *smb_fn_name(int type)
3369 static char *unknown_name = "SMBunknown";
3370 static int num_smb_messages =
3371 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3372 int match;
3374 for (match=0;match<num_smb_messages;match++)
3375 if (smb_messages[match].code == type)
3376 break;
3378 if (match == num_smb_messages)
3379 return(unknown_name);
3381 return(smb_messages[match].name);
3385 /****************************************************************************
3386 do a switch on the message type, and return the response size
3387 ****************************************************************************/
3388 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3390 static int pid= -1;
3391 int outsize = 0;
3392 static int num_smb_messages =
3393 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3394 int match;
3396 #if PROFILING
3397 struct timeval msg_start_time;
3398 struct timeval msg_end_time;
3399 static unsigned long total_time = 0;
3401 GetTimeOfDay(&msg_start_time);
3402 #endif
3404 if (pid == -1)
3405 pid = getpid();
3407 errno = 0;
3408 last_message = type;
3410 /* make sure this is an SMB packet */
3411 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3413 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3414 return(-1);
3417 for (match=0;match<num_smb_messages;match++)
3418 if (smb_messages[match].code == type)
3419 break;
3421 if (match == num_smb_messages)
3423 DEBUG(0,("Unknown message type %d!\n",type));
3424 outsize = reply_unknown(inbuf,outbuf);
3426 else
3428 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3429 if (smb_messages[match].fn)
3431 int cnum = SVAL(inbuf,smb_tid);
3432 int flags = smb_messages[match].flags;
3433 uint16 session_tag = SVAL(inbuf,smb_uid);
3435 /* does this protocol need to be run as root? */
3436 if (!(flags & AS_USER))
3437 unbecome_user();
3439 /* does this protocol need to be run as the connected user? */
3440 if ((flags & AS_USER) && !become_user(cnum,session_tag)) {
3441 if (flags & AS_GUEST)
3442 flags &= ~AS_USER;
3443 else
3444 return(ERROR(ERRSRV,ERRinvnid));
3446 /* this code is to work around a bug is MS client 3 without
3447 introducing a security hole - it needs to be able to do
3448 print queue checks as guest if it isn't logged in properly */
3449 if (flags & AS_USER)
3450 flags &= ~AS_GUEST;
3452 /* does it need write permission? */
3453 if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3454 return(ERROR(ERRSRV,ERRaccess));
3456 /* ipc services are limited */
3457 if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3458 return(ERROR(ERRSRV,ERRaccess));
3460 /* load service specific parameters */
3461 if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3462 return(ERROR(ERRSRV,ERRaccess));
3464 /* does this protocol need to be run as guest? */
3465 if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3466 return(ERROR(ERRSRV,ERRaccess));
3468 last_inbuf = inbuf;
3470 outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3472 else
3474 outsize = reply_unknown(inbuf,outbuf);
3478 #if PROFILING
3479 GetTimeOfDay(&msg_end_time);
3480 if (!(smb_messages[match].flags & TIME_INIT))
3482 smb_messages[match].time = 0;
3483 smb_messages[match].flags |= TIME_INIT;
3486 unsigned long this_time =
3487 (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3488 (msg_end_time.tv_usec - msg_start_time.tv_usec);
3489 smb_messages[match].time += this_time;
3490 total_time += this_time;
3492 DEBUG(2,("TIME %s %d usecs %g pct\n",
3493 smb_fn_name(type),smb_messages[match].time,
3494 (100.0*smb_messages[match].time) / total_time));
3495 #endif
3497 return(outsize);
3501 /****************************************************************************
3502 construct a chained reply and add it to the already made reply
3503 **************************************************************************/
3504 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
3506 static char *orig_inbuf;
3507 static char *orig_outbuf;
3508 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
3509 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
3510 char *inbuf2, *outbuf2;
3511 int outsize2;
3512 char inbuf_saved[smb_wct];
3513 char outbuf_saved[smb_wct];
3514 extern int chain_size;
3515 int wct = CVAL(outbuf,smb_wct);
3516 int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
3518 /* maybe its not chained */
3519 if (smb_com2 == 0xFF) {
3520 CVAL(outbuf,smb_vwv0) = 0xFF;
3521 return outsize;
3524 if (chain_size == 0) {
3525 /* this is the first part of the chain */
3526 orig_inbuf = inbuf;
3527 orig_outbuf = outbuf;
3530 /* we need to tell the client where the next part of the reply will be */
3531 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
3532 CVAL(outbuf,smb_vwv0) = smb_com2;
3534 /* remember how much the caller added to the chain, only counting stuff
3535 after the parameter words */
3536 chain_size += outsize - smb_wct;
3538 /* work out pointers into the original packets. The
3539 headers on these need to be filled in */
3540 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
3541 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
3543 /* remember the original command type */
3544 smb_com1 = CVAL(orig_inbuf,smb_com);
3546 /* save the data which will be overwritten by the new headers */
3547 memcpy(inbuf_saved,inbuf2,smb_wct);
3548 memcpy(outbuf_saved,outbuf2,smb_wct);
3550 /* give the new packet the same header as the last part of the SMB */
3551 memmove(inbuf2,inbuf,smb_wct);
3553 /* create the in buffer */
3554 CVAL(inbuf2,smb_com) = smb_com2;
3556 /* create the out buffer */
3557 bzero(outbuf2,smb_size);
3558 set_message(outbuf2,0,0,True);
3559 CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com);
3561 memcpy(outbuf2+4,inbuf2+4,4);
3562 CVAL(outbuf2,smb_rcls) = SUCCESS;
3563 CVAL(outbuf2,smb_reh) = 0;
3564 CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set
3565 means a reply */
3566 SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */
3567 SSVAL(outbuf2,smb_err,SUCCESS);
3568 SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid));
3569 SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid));
3570 SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid));
3571 SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid));
3573 DEBUG(3,("Chained message\n"));
3574 show_msg(inbuf2);
3576 /* process the request */
3577 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
3578 bufsize-chain_size);
3580 /* copy the new reply and request headers over the old ones, but
3581 preserve the smb_com field */
3582 memmove(orig_outbuf,outbuf2,smb_wct);
3583 CVAL(orig_outbuf,smb_com) = smb_com1;
3585 /* restore the saved data, being careful not to overwrite any
3586 data from the reply header */
3587 memcpy(inbuf2,inbuf_saved,smb_wct);
3589 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
3590 if (ofs < 0) ofs = 0;
3591 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
3594 return outsize2;
3599 /****************************************************************************
3600 construct a reply to the incoming packet
3601 ****************************************************************************/
3602 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3604 int type = CVAL(inbuf,smb_com);
3605 int outsize = 0;
3606 int msg_type = CVAL(inbuf,0);
3607 extern int chain_size;
3609 smb_last_time = time(NULL);
3611 chain_size = 0;
3612 chain_fnum = -1;
3614 bzero(outbuf,smb_size);
3616 if (msg_type != 0)
3617 return(reply_special(inbuf,outbuf));
3619 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3620 set_message(outbuf,0,0,True);
3622 memcpy(outbuf+4,inbuf+4,4);
3623 CVAL(outbuf,smb_rcls) = SUCCESS;
3624 CVAL(outbuf,smb_reh) = 0;
3625 CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
3626 means a reply */
3627 SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3628 SSVAL(outbuf,smb_err,SUCCESS);
3629 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3630 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3631 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3632 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3634 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3636 outsize += chain_size;
3638 if(outsize > 4)
3639 smb_setlen(outbuf,outsize - 4);
3640 return(outsize);
3644 /****************************************************************************
3645 process commands from the client
3646 ****************************************************************************/
3647 static void process(void)
3649 static int trans_num = 0;
3650 int nread;
3651 extern int Client;
3653 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3654 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3655 if ((InBuffer == NULL) || (OutBuffer == NULL))
3656 return;
3658 InBuffer += SMB_ALIGNMENT;
3659 OutBuffer += SMB_ALIGNMENT;
3661 #if PRIME_NMBD
3662 DEBUG(3,("priming nmbd\n"));
3664 struct in_addr ip;
3665 ip = *interpret_addr2("localhost");
3666 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3667 *OutBuffer = 0;
3668 send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
3670 #endif
3672 while (True)
3674 int32 len;
3675 int msg_type;
3676 int msg_flags;
3677 int type;
3678 int deadtime = lp_deadtime()*60;
3679 int counter;
3680 int last_keepalive=0;
3682 if (deadtime <= 0)
3683 deadtime = DEFAULT_SMBD_TIMEOUT;
3685 if (lp_readprediction())
3686 do_read_prediction();
3689 extern pstring share_del_pending;
3690 if (*share_del_pending) {
3691 unbecome_user();
3692 if (!unlink(share_del_pending))
3693 DEBUG(3,("Share file deleted %s\n",share_del_pending));
3694 else
3695 DEBUG(2,("Share del failed of %s\n",share_del_pending));
3696 share_del_pending[0] = 0;
3700 if (share_mode_pending) {
3701 unbecome_user();
3702 check_share_modes();
3703 share_mode_pending=False;
3706 errno = 0;
3708 for (counter=SMBD_SELECT_LOOP;
3709 !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000);
3710 counter += SMBD_SELECT_LOOP)
3712 int i;
3713 time_t t;
3714 BOOL allidle = True;
3715 extern int keepalive;
3717 if (smb_read_error == READ_EOF) {
3718 DEBUG(3,("end of file from client\n"));
3719 return;
3722 if (smb_read_error == READ_ERROR) {
3723 DEBUG(3,("receive_smb error (%s) exiting\n",
3724 strerror(errno)));
3725 return;
3728 t = time(NULL);
3730 /* become root again if waiting */
3731 unbecome_user();
3733 /* check for smb.conf reload */
3734 if (!(counter%SMBD_RELOAD_CHECK))
3735 reload_services(True);
3737 /* check the share modes every 10 secs */
3738 if (!(counter%SHARE_MODES_CHECK))
3739 check_share_modes();
3741 /* clean the share modes every 5 minutes */
3742 if (!(counter%SHARE_MODES_CLEAN))
3743 clean_share_modes();
3745 /* automatic timeout if all connections are closed */
3746 if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3747 DEBUG(2,("%s Closing idle connection\n",timestring()));
3748 return;
3751 if (keepalive && (counter-last_keepalive)>keepalive) {
3752 extern int password_client;
3753 if (!send_keepalive(Client)) {
3754 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3755 return;
3757 /* also send a keepalive to the password server if its still
3758 connected */
3759 if (password_client != -1)
3760 send_keepalive(password_client);
3761 last_keepalive = counter;
3764 /* check for connection timeouts */
3765 for (i=0;i<MAX_CONNECTIONS;i++)
3766 if (Connections[i].open)
3768 /* close dirptrs on connections that are idle */
3769 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
3770 dptr_idlecnum(i);
3772 if (Connections[i].num_files_open > 0 ||
3773 (t-Connections[i].lastused)<deadtime)
3774 allidle = False;
3777 if (allidle && num_connections_open>0) {
3778 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
3779 return;
3783 msg_type = CVAL(InBuffer,0);
3784 msg_flags = CVAL(InBuffer,1);
3785 type = CVAL(InBuffer,smb_com);
3787 len = smb_len(InBuffer);
3789 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
3791 nread = len + 4;
3793 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
3795 #ifdef WITH_VTP
3796 if(trans_num == 1 && VT_Check(InBuffer)) {
3797 VT_Process();
3798 return;
3800 #endif
3803 if (msg_type == 0)
3804 show_msg(InBuffer);
3806 nread = construct_reply(InBuffer,OutBuffer,nread,maxxmit);
3808 if(nread > 0) {
3809 if (CVAL(OutBuffer,0) == 0)
3810 show_msg(OutBuffer);
3812 if (nread != smb_len(OutBuffer) + 4)
3814 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
3815 nread,
3816 smb_len(OutBuffer)));
3818 else
3819 send_smb(Client,OutBuffer);
3821 trans_num++;
3826 /****************************************************************************
3827 initialise connect, service and file structs
3828 ****************************************************************************/
3829 static void init_structs(void )
3831 int i;
3832 get_myname(myhostname,NULL);
3834 for (i=0;i<MAX_CONNECTIONS;i++)
3836 Connections[i].open = False;
3837 Connections[i].num_files_open=0;
3838 Connections[i].lastused=0;
3839 Connections[i].used=False;
3840 string_init(&Connections[i].user,"");
3841 string_init(&Connections[i].dirpath,"");
3842 string_init(&Connections[i].connectpath,"");
3843 string_init(&Connections[i].origpath,"");
3846 for (i=0;i<MAX_OPEN_FILES;i++)
3848 Files[i].open = False;
3849 string_init(&Files[i].name,"");
3853 for (i=0;i<MAX_OPEN_FILES;i++)
3855 file_fd_struct *fd_ptr = &FileFd[i];
3856 fd_ptr->ref_count = 0;
3857 fd_ptr->dev = (int32)-1;
3858 fd_ptr->inode = (int32)-1;
3859 fd_ptr->fd = -1;
3860 fd_ptr->fd_readonly = -1;
3861 fd_ptr->fd_writeonly = -1;
3862 fd_ptr->real_open_flags = -1;
3865 init_dptrs();
3868 /****************************************************************************
3869 usage on the program
3870 ****************************************************************************/
3871 static void usage(char *pname)
3873 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
3875 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
3876 printf("Version %s\n",VERSION);
3877 printf("\t-D become a daemon\n");
3878 printf("\t-p port listen on the specified port\n");
3879 printf("\t-d debuglevel set the debuglevel\n");
3880 printf("\t-l log basename. Basename for log/debug files\n");
3881 printf("\t-s services file. Filename of services file\n");
3882 printf("\t-P passive only\n");
3883 printf("\t-a overwrite log file, don't append\n");
3884 printf("\n");
3888 /****************************************************************************
3889 main program
3890 ****************************************************************************/
3891 int main(int argc,char *argv[])
3893 extern BOOL append_log;
3894 /* shall I run as a daemon */
3895 BOOL is_daemon = False;
3896 int port = SMB_PORT;
3897 int opt;
3898 extern char *optarg;
3899 char pidFile[100] = { 0 };
3901 #ifdef NEED_AUTH_PARAMETERS
3902 set_auth_parameters(argc,argv);
3903 #endif
3905 #ifdef SecureWare
3906 setluid(0);
3907 #endif
3909 append_log = True;
3911 TimeInit();
3913 strcpy(debugf,SMBLOGFILE);
3915 setup_logging(argv[0],False);
3917 charset_initialise();
3919 /* make absolutely sure we run as root - to handle cases whre people
3920 are crazy enough to have it setuid */
3921 #ifdef USE_SETRES
3922 setresuid(0,0,0);
3923 #else
3924 setuid(0);
3925 seteuid(0);
3926 setuid(0);
3927 seteuid(0);
3928 #endif
3930 fault_setup(exit_server);
3931 signal(SIGTERM , SIGNAL_CAST dflt_sig);
3933 /* we want total control over the permissions on created files,
3934 so set our umask to 0 */
3935 umask(0);
3937 GetWd(OriginalDir);
3939 init_uid();
3941 /* this is for people who can't start the program correctly */
3942 while (argc > 1 && (*argv[1] != '-'))
3944 argv++;
3945 argc--;
3948 while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF)
3949 switch (opt)
3951 case 'f':
3952 strncpy(pidFile, optarg, sizeof(pidFile));
3953 break;
3954 case 'O':
3955 strcpy(user_socket_options,optarg);
3956 break;
3957 case 'i':
3958 strcpy(scope,optarg);
3959 break;
3960 case 'P':
3962 extern BOOL passive;
3963 passive = True;
3965 break;
3966 case 's':
3967 strcpy(servicesf,optarg);
3968 break;
3969 case 'l':
3970 strcpy(debugf,optarg);
3971 break;
3972 case 'a':
3974 extern BOOL append_log;
3975 append_log = !append_log;
3977 break;
3978 case 'D':
3979 is_daemon = True;
3980 break;
3981 case 'd':
3982 if (*optarg == 'A')
3983 DEBUGLEVEL = 10000;
3984 else
3985 DEBUGLEVEL = atoi(optarg);
3986 break;
3987 case 'p':
3988 port = atoi(optarg);
3989 break;
3990 case 'h':
3991 usage(argv[0]);
3992 exit(0);
3993 break;
3994 default:
3995 usage(argv[0]);
3996 exit(1);
3999 reopen_logs();
4001 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
4002 DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
4004 #ifndef NO_GETRLIMIT
4005 #ifdef RLIMIT_NOFILE
4007 struct rlimit rlp;
4008 getrlimit(RLIMIT_NOFILE, &rlp);
4009 rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
4010 setrlimit(RLIMIT_NOFILE, &rlp);
4011 getrlimit(RLIMIT_NOFILE, &rlp);
4012 DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
4014 #endif
4015 #endif
4018 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4019 getuid(),getgid(),geteuid(),getegid()));
4021 if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
4023 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
4024 exit(1);
4027 init_structs();
4029 if (!reload_services(False))
4030 return(-1);
4032 #ifndef NO_SIGNAL_TEST
4033 signal(SIGHUP,SIGNAL_CAST sig_hup);
4034 #endif
4036 DEBUG(3,("%s loaded services\n",timestring()));
4038 if (!is_daemon && !is_a_socket(0))
4040 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
4041 is_daemon = True;
4044 if (is_daemon)
4046 DEBUG(3,("%s becoming a daemon\n",timestring()));
4047 become_daemon();
4050 if (*pidFile)
4052 int fd;
4053 char buf[20];
4055 if ((fd = open(pidFile,
4056 O_NONBLOCK | O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
4058 DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
4059 exit(1);
4061 if(fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
4063 DEBUG(0,("ERROR: smbd is already running\n"));
4064 exit(1);
4066 sprintf(buf, "%u\n", (unsigned int) getpid());
4067 if (write(fd, buf, strlen(buf)) < 0)
4069 DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
4070 exit(1);
4072 /* Leave pid file open & locked for the duration... */
4075 if (!open_sockets(is_daemon,port))
4076 exit(1);
4078 #if FAST_SHARE_MODES
4079 if (!start_share_mode_mgmt())
4080 exit(1);
4081 #endif
4083 /* possibly reload the services file. */
4084 reload_services(True);
4086 maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE);
4088 if (*lp_rootdir())
4090 if (sys_chroot(lp_rootdir()) == 0)
4091 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4094 process();
4095 close_sockets();
4097 exit_server("normal exit");
4098 return(0);