2 Unix SMB/Netbios implementation.
4 Samba utility functions
5 Copyright (C) Andrew Tridgell 1992-1998
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.
24 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
25 #ifdef WITH_NISPLUS_HOME
26 #include <rpcsvc/nis.h>
28 #include "rpcsvc/ypclnt.h"
34 #undef Realloc /* SSLeay defines this and samba has a function of this name */
41 extern int DEBUGLEVEL;
43 int Protocol = PROTOCOL_COREPLUS;
45 /* a default finfo structure to ensure all fields are sensible */
46 file_info def_finfo = {-1,0,0,0,0,0,0,""};
48 /* the client file descriptor */
51 /* this is used by the chaining code */
57 case handling on filenames
59 int case_default = CASE_LOWER;
61 /* the following control case operations - they are put here so the
62 client can link easily */
65 BOOL use_mangled_map = False;
66 BOOL short_case_preserve;
69 fstring remote_machine="";
70 fstring local_machine="";
71 fstring remote_arch="UNKNOWN";
72 static enum remote_arch_types ra_type = RA_UNKNOWN;
73 fstring remote_proto="UNKNOWN";
74 pstring myhostname="";
75 pstring user_socket_options="";
77 pstring sesssetup_user="";
78 pstring samlogon_user="";
80 BOOL sam_logon_in_ssb = False;
82 pstring global_myname = "";
83 fstring global_myworkgroup = "";
84 char **my_netbios_names;
86 static char *filename_dos(char *path,char *buf);
90 /****************************************************************************
91 find a suitable temporary directory. The result should be copied immediately
92 as it may be overwritten by a subsequent call
93 ****************************************************************************/
97 if ((p = getenv("TMPDIR"))) {
103 /****************************************************************************
104 determine whether we are in the specified group
105 ****************************************************************************/
107 BOOL in_group(gid_t group, gid_t current_gid, int ngroups, gid_t *groups)
111 if (group == current_gid) return(True);
113 for (i=0;i<ngroups;i++)
114 if (group == groups[i])
121 /****************************************************************************
122 gets either a hex number (0xNNN) or decimal integer (NNN).
123 ****************************************************************************/
124 uint32 get_number(const char *tmp)
126 if (strnequal(tmp, "0x", 2))
128 return strtoul(tmp, (char**)NULL, 16);
132 return strtoul(tmp, (char**)NULL, 10);
136 /****************************************************************************
137 like atoi but gets the value up to the separater character
138 ****************************************************************************/
139 char *Atoic(char *p, int *n, char *c)
143 DEBUG(5, ("Atoic: malformed number\n"));
147 (*n) = (int)get_number(p);
149 if (strnequal(p, "0x", 2))
154 while ((*p) && isdigit(*p))
159 if (strchr(c, *p) == NULL)
161 DEBUG(5, ("Atoic: no separator characters (%s) not found\n", c));
168 uint32 *add_num_to_list(uint32 **num, int *count, int val)
170 (*num) = Realloc((*num), ((*count)+1) * sizeof(uint32));
175 (*num)[(*count)] = val;
181 /*************************************************************************
182 reads a list of numbers
183 *************************************************************************/
184 char *get_numlist(char *p, uint32 **num, int *count)
188 if (num == NULL || count == NULL)
196 while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':')
198 if (add_num_to_list(num, count, val) == NULL)
208 /*******************************************************************
209 copy an IP address from one buffer to another
210 ********************************************************************/
211 void putip(void *dest,void *src)
217 #define TRUNCATE_NETBIOS_NAME 1
219 /*******************************************************************
220 convert, possibly using a stupid microsoft-ism which has destroyed
221 the transport independence of netbios (for CIFS vendors that usually
222 use the Win95-type methods, not for NT to NT communication, which uses
223 DCE/RPC and therefore full-length unicode strings...) a dns name into
226 the netbios name (NOT necessarily null-terminated) is truncated to 15
229 ******************************************************************/
230 char *dns_to_netbios_name(char *dns_name)
232 static char netbios_name[16];
234 StrnCpy(netbios_name, dns_name, 15);
235 netbios_name[15] = 0;
237 #ifdef TRUNCATE_NETBIOS_NAME
238 /* ok. this is because of a stupid microsoft-ism. if the called host
239 name contains a '.', microsoft clients expect you to truncate the
240 netbios name up to and including the '.' this even applies, by
241 mistake, to workgroup (domain) names, which is _really_ daft.
243 for (i = 15; i >= 0; i--)
245 if (netbios_name[i] == '.')
251 #endif /* TRUNCATE_NETBIOS_NAME */
257 /****************************************************************************
258 interpret the weird netbios "name". Return the name type
259 ****************************************************************************/
260 static int name_interpret(char *in,char *out)
263 int len = (*in++) / 2;
267 if (len > 30 || len<1) return(0);
271 if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
275 *out = ((in[0]-'A')<<4) + (in[1]-'A');
283 /* Handle any scope names */
286 *out++ = '.'; /* Scope names are separated by periods */
287 len = *(unsigned char *)in++;
288 StrnCpy(out, in, len);
297 /****************************************************************************
298 mangle a name into netbios format
300 Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
301 ****************************************************************************/
302 int name_mangle( char *In, char *Out, char name_type )
310 /* Safely copy the input string, In, into buf[]. */
311 (void)memset( buf, 0, 20 );
312 if (strcmp(In,"*") == 0)
315 (void)slprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, name_type );
317 /* Place the length of the first field into the output buffer. */
321 /* Now convert the name to the rfc1001/1002 format. */
322 for( i = 0; i < 16; i++ )
324 c = toupper( buf[i] );
325 p[i*2] = ( (c >> 4) & 0x000F ) + 'A';
326 p[(i*2)+1] = (c & 0x000F) + 'A';
331 /* Add the scope string. */
332 for( i = 0, len = 0; NULL != scope; i++, len++ )
340 return( name_len(Out) );
352 return( name_len(Out) );
355 /*******************************************************************
356 check if a file exists
357 ********************************************************************/
358 BOOL file_exist(char *fname,SMB_STRUCT_STAT *sbuf)
361 if (!sbuf) sbuf = &st;
363 if (sys_stat(fname,sbuf) != 0)
366 return(S_ISREG(sbuf->st_mode));
369 /*******************************************************************
371 ********************************************************************/
372 int file_rename(char *from, char *to)
374 int rcode = rename (from, to);
378 /* Rename across filesystems needed. */
379 rcode = copy_reg (from, to);
384 /*******************************************************************
385 check a files mod time
386 ********************************************************************/
387 time_t file_modtime(char *fname)
391 if (sys_stat(fname,&st) != 0)
397 /*******************************************************************
398 check if a directory exists
399 ********************************************************************/
400 BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st)
407 if (sys_stat(dname,st) != 0)
410 ret = S_ISDIR(st->st_mode);
416 /*******************************************************************
417 returns the size in bytes of the named file
418 ********************************************************************/
419 SMB_OFF_T file_size(char *file_name)
423 if(sys_stat(file_name,&buf) != 0)
424 return (SMB_OFF_T)-1;
428 /*******************************************************************
429 return a string representing an attribute for a file
430 ********************************************************************/
431 char *attrib_string(uint16 mode)
433 static fstring attrstr;
437 if (mode & aVOLID) fstrcat(attrstr,"V");
438 if (mode & aDIR) fstrcat(attrstr,"D");
439 if (mode & aARCH) fstrcat(attrstr,"A");
440 if (mode & aHIDDEN) fstrcat(attrstr,"H");
441 if (mode & aSYSTEM) fstrcat(attrstr,"S");
442 if (mode & aRONLY) fstrcat(attrstr,"R");
447 /****************************************************************************
448 make a file into unix format
449 ****************************************************************************/
450 void unix_format(char *fname)
452 string_replace(fname,'\\','/');
455 /****************************************************************************
456 make a file into dos format
457 ****************************************************************************/
458 void dos_format(char *fname)
460 string_replace(fname,'/','\\');
463 /*******************************************************************
464 show a smb message structure
465 ********************************************************************/
466 void show_msg(char *buf)
471 if (DEBUGLEVEL < 5) return;
473 DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
475 (int)CVAL(buf,smb_com),
476 (int)CVAL(buf,smb_rcls),
477 (int)CVAL(buf,smb_reh),
478 (int)SVAL(buf,smb_err),
479 (int)CVAL(buf,smb_flg),
480 (int)SVAL(buf,smb_flg2)));
481 DEBUG(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n",
482 (int)SVAL(buf,smb_tid),
483 (int)SVAL(buf,smb_pid),
484 (int)SVAL(buf,smb_uid),
485 (int)SVAL(buf,smb_mid),
486 (int)CVAL(buf,smb_wct)));
488 for (i=0;i<(int)CVAL(buf,smb_wct);i++)
490 DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i,
491 SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
494 bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
496 DEBUG(5,("smb_bcc=%d\n",bcc));
498 if (DEBUGLEVEL < 10) return;
505 dump_data(10, smb_buf(buf), bcc);
507 /*******************************************************************
508 return the length of an smb packet
509 ********************************************************************/
510 int smb_len(char *buf)
512 return( PVAL(buf,3) | (PVAL(buf,2)<<8) | ((PVAL(buf,1)&1)<<16) );
515 /*******************************************************************
516 set the length of an smb packet
517 ********************************************************************/
518 void _smb_setlen(char *buf,int len)
521 buf[1] = (len&0x10000)>>16;
522 buf[2] = (len&0xFF00)>>8;
526 /*******************************************************************
527 set the length and marker of an smb packet
528 ********************************************************************/
529 void smb_setlen(char *buf,int len)
531 _smb_setlen(buf,len);
539 /*******************************************************************
540 setup the word count and byte count for a smb message
541 ********************************************************************/
542 int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
545 bzero(buf + smb_size,num_words*2 + num_bytes);
546 CVAL(buf,smb_wct) = num_words;
547 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
548 smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
549 return (smb_size + num_words*2 + num_bytes);
552 /*******************************************************************
553 return the number of smb words
554 ********************************************************************/
555 static int smb_numwords(char *buf)
557 return (CVAL(buf,smb_wct));
560 /*******************************************************************
561 return the size of the smb_buf region of a message
562 ********************************************************************/
563 int smb_buflen(char *buf)
565 return(SVAL(buf,smb_vwv0 + smb_numwords(buf)*2));
568 /*******************************************************************
569 return a pointer to the smb_buf data area
570 ********************************************************************/
571 static int smb_buf_ofs(char *buf)
573 return (smb_size + CVAL(buf,smb_wct)*2);
576 /*******************************************************************
577 return a pointer to the smb_buf data area
578 ********************************************************************/
579 char *smb_buf(char *buf)
581 return (buf + smb_buf_ofs(buf));
584 /*******************************************************************
585 return the SMB offset into an SMB buffer
586 ********************************************************************/
587 int smb_offset(char *p,char *buf)
589 return(PTR_DIFF(p,buf+4) + chain_size);
594 /*******************************************************************
595 reduce a file name, removing .. elements.
596 ********************************************************************/
597 void dos_clean_name(char *s)
601 DEBUG(3,("dos_clean_name [%s]\n",s));
603 /* remove any double slashes */
604 string_sub(s, "\\\\", "\\");
606 while ((p = strstr(s,"\\..\\")) != NULL)
613 if ((p=strrchr(s,'\\')) != NULL)
620 trim_string(s,NULL,"\\..");
622 string_sub(s, "\\.\\", "\\");
625 /*******************************************************************
626 reduce a file name, removing .. elements.
627 ********************************************************************/
628 void unix_clean_name(char *s)
632 DEBUG(3,("unix_clean_name [%s]\n",s));
634 /* remove any double slashes */
635 string_sub(s, "//","/");
637 /* Remove leading ./ characters */
638 if(strncmp(s, "./", 2) == 0) {
639 trim_string(s, "./", NULL);
644 while ((p = strstr(s,"/../")) != NULL)
651 if ((p=strrchr(s,'/')) != NULL)
658 trim_string(s,NULL,"/..");
661 /*******************************************************************
662 reduce a file name, removing .. elements and checking that
663 it is below dir in the heirachy. This uses GetWd() and so must be run
664 on the system that has the referenced file system.
666 widelinks are allowed if widelinks is true
667 ********************************************************************/
669 BOOL reduce_name(char *s,char *dir,BOOL widelinks)
679 BOOL relative = (*s != '/');
681 *dir2 = *wd = *base_name = *newname = 0;
686 /* can't have a leading .. */
687 if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
689 DEBUG(3,("Illegal file name? (%s)\n",s));
699 DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
701 /* remove any double slashes */
702 string_sub(s,"//","/");
704 pstrcpy(base_name,s);
705 p = strrchr(base_name,'/');
712 DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
716 if (dos_ChDir(dir) != 0)
718 DEBUG(0,("couldn't chdir to %s\n",dir));
722 if (!dos_GetWd(dir2))
724 DEBUG(0,("couldn't getwd for %s\n",dir));
730 if (p && (p != base_name))
733 if (strcmp(p+1,".")==0)
735 if (strcmp(p+1,"..")==0)
739 if (dos_ChDir(base_name) != 0)
742 DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name));
746 if (!dos_GetWd(newname))
749 DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
753 if (p && (p != base_name))
755 pstrcat(newname,"/");
756 pstrcat(newname,p+1);
760 size_t l = strlen(dir2);
761 if (dir2[l-1] == '/')
764 if (strncmp(newname,dir2,l) != 0)
767 DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,l));
773 if (newname[l] == '/')
774 pstrcpy(s,newname + l + 1);
776 pstrcpy(s,newname+l);
787 DEBUG(3,("reduced to %s\n",s));
792 /****************************************************************************
794 ****************************************************************************/
795 static void expand_one(char *Mask,int len)
798 while ((p1 = strchr(Mask,'*')) != NULL)
800 int lfill = (len+1) - strlen(Mask);
804 memset(tmp+l1,'?',lfill);
805 pstrcpy(tmp + l1 + lfill,Mask + l1 + 1);
810 /****************************************************************************
811 parse out a directory name from a path name. Assumes dos style filenames.
812 ****************************************************************************/
813 static void dirname_dos(char *path,char *buf)
815 split_at_last_component(path, buf, '\\', NULL);
819 /****************************************************************************
820 expand a wildcard expression, replacing *s with ?s
821 ****************************************************************************/
822 void expand_mask(char *Mask,BOOL doext)
829 BOOL absolute = (*Mask == '\\');
831 *mbeg = *mext = *dirpart = *filepart = 0;
833 /* parse the directory and filename */
834 if (strchr(Mask,'\\'))
835 dirname_dos(Mask,dirpart);
837 filename_dos(Mask,filepart);
839 pstrcpy(mbeg,filepart);
840 if ((p1 = strchr(mbeg,'.')) != NULL)
850 if (strlen(mbeg) > 8)
852 pstrcpy(mext,mbeg + 8);
858 pstrcpy(mbeg,"????????");
859 if ((*mext == 0) && doext && !hasdot)
862 if (strequal(mbeg,"*") && *mext==0)
870 pstrcpy(Mask,dirpart);
871 if (*dirpart || absolute) pstrcat(Mask,"\\");
876 DEBUG(6,("Mask expanded to [%s]\n",Mask));
881 /****************************************************************************
883 ****************************************************************************/
884 void make_dir_struct(char *buf,char *mask,char *fname,SMB_OFF_T size,int mode,time_t date)
891 if ((mode & aDIR) != 0)
894 memset(buf+1,' ',11);
895 if ((p = strchr(mask2,'.')) != NULL)
898 memcpy(buf+1,mask2,MIN(strlen(mask2),8));
899 memcpy(buf+9,p+1,MIN(strlen(p+1),3));
903 memcpy(buf+1,mask2,MIN(strlen(mask2),11));
905 bzero(buf+21,DIR_STRUCT_SIZE-21);
907 put_dos_date(buf,22,date);
908 SSVAL(buf,26,size & 0xFFFF);
909 SSVAL(buf,28,(size >> 16)&0xFFFF);
910 StrnCpy(buf+30,fname,12);
913 DEBUG(8,("put name [%s] into dir struct\n",buf+30));
917 /*******************************************************************
918 close the low 3 fd's and open dev/null in their place
919 ********************************************************************/
920 void close_low_fds(void)
924 close(0); close(1); close(2);
925 /* try and use up these file descriptors, so silly
926 library routines writing to stdout etc won't cause havoc */
928 fd = sys_open("/dev/null",O_RDWR,0);
929 if (fd < 0) fd = sys_open("/dev/null",O_WRONLY,0);
931 DEBUG(0,("Can't open /dev/null\n"));
935 DEBUG(0,("Didn't get file descriptor %d\n",i));
941 /****************************************************************************
942 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
946 ****************************************************************************/
947 int set_blocking(int fd, BOOL set)
951 #define FLAG_TO_SET O_NONBLOCK
954 #define FLAG_TO_SET O_NDELAY
956 #define FLAG_TO_SET FNDELAY
960 if((val = fcntl(fd, F_GETFL, 0)) == -1)
962 if(set) /* Turn blocking on - ie. clear nonblock flag */
966 return fcntl( fd, F_SETFL, val);
971 /*******************************************************************
972 find the difference in milliseconds between two struct timeval
974 ********************************************************************/
975 int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew)
977 return((tvalnew->tv_sec - tvalold->tv_sec)*1000 +
978 ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000);
983 /****************************************************************************
984 transfer some data between two fd's
985 ****************************************************************************/
986 SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n,char *header,int headlen,int align)
988 static char *buf=NULL;
993 DEBUG(4,("transfer_file n=%.0f (head=%d) called\n",(double)n,headlen));
996 size = lp_readsize();
997 size = MAX(size,1024);
1000 while (!buf && size>0) {
1001 buf = (char *)Realloc(buf,size+8);
1002 if (!buf) size /= 2;
1006 DEBUG(0,("Can't allocate transfer buffer!\n"));
1010 abuf = buf + (align%8);
1017 int s = (int)MIN(n,(SMB_OFF_T)size);
1022 if (header && (headlen >= MIN(s,1024))) {
1032 if (header && headlen > 0)
1034 ret = MIN(headlen,size);
1035 memcpy(buf1,header,ret);
1038 if (headlen <= 0) header = NULL;
1042 ret += read(infd,buf1+ret,s-ret);
1046 ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret);
1047 if (ret2 > 0) total += ret2;
1048 /* if we can't write then dump excess data */
1050 transfer_file(infd,-1,n-(ret+headlen),NULL,0,0);
1052 if (ret <= 0 || ret2 != ret)
1061 /****************************************************************************
1062 find a pointer to a netbios name
1063 ****************************************************************************/
1064 static char *name_ptr(char *buf,int ofs)
1066 unsigned char c = *(unsigned char *)(buf+ofs);
1068 if ((c & 0xC0) == 0xC0)
1072 memcpy(p,buf+ofs,2);
1075 DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
1082 /****************************************************************************
1083 extract a netbios name from a buf
1084 ****************************************************************************/
1085 int name_extract(char *buf,int ofs,char *name)
1087 char *p = name_ptr(buf,ofs);
1088 int d = PTR_DIFF(p,buf+ofs);
1090 if (d < -50 || d > 50) return(0);
1091 return(name_interpret(p,name));
1094 /****************************************************************************
1095 return the total storage length of a mangled name
1096 ****************************************************************************/
1097 int name_len(char *s1)
1099 /* NOTE: this argument _must_ be unsigned */
1100 unsigned char *s = (unsigned char *)s1;
1103 /* If the two high bits of the byte are set, return 2. */
1104 if (0xC0 == (*s & 0xC0))
1107 /* Add up the length bytes. */
1108 for (len = 1; (*s); s += (*s) + 1) {
1110 SMB_ASSERT(len < 80);
1117 /*******************************************************************
1118 sleep for a specified number of milliseconds
1119 ********************************************************************/
1123 struct timeval tval,t1,t2;
1130 tval.tv_sec = (t-tdiff)/1000;
1131 tval.tv_usec = 1000*((t-tdiff)%1000);
1135 sys_select(0,&fds,&tval);
1138 tdiff = TvalDiff(&t1,&t2);
1143 /*********************************************************
1144 * Recursive routine that is called by unix_mask_match.
1145 * Does the actual matching. This is the 'original code'
1146 * used by the unix matcher.
1147 *********************************************************/
1148 static BOOL unix_do_match(char *str, char *regexp, int case_sig)
1152 for( p = regexp; *p && *str; ) {
1159 /* Look for a character matching
1160 the one after the '*' */
1163 return True; /* Automatic match */
1165 while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
1167 if(unix_do_match(str,p,case_sig))
1181 if(toupper(*str) != toupper(*p))
1191 if (!*p && str[0] == '.' && str[1] == 0)
1194 if (!*str && *p == '?')
1196 while (*p == '?') p++;
1200 if(!*str && (*p == '*' && p[1] == '\0'))
1206 /*********************************************************
1207 * Routine to match a given string with a regexp - uses
1208 * simplified regexp that takes * and ? only. Case can be
1209 * significant or not.
1210 * This is the 'original code' used by the unix matcher.
1211 *********************************************************/
1213 static BOOL unix_mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
1217 fstring ebase,eext,sbase,sext;
1221 /* Make local copies of str and regexp */
1222 StrnCpy(p1,regexp,sizeof(pstring)-1);
1223 StrnCpy(p2,str,sizeof(pstring)-1);
1225 if (!strchr(p2,'.')) {
1229 /* Remove any *? and ** as they are meaningless */
1230 for(p = p1; *p; p++)
1231 while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
1232 (void)pstrcpy( &p[1], &p[2]);
1234 if (strequal(p1,"*")) return(True);
1236 DEBUG(8,("unix_mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
1242 if ((p=strrchr(p1,'.'))) {
1251 if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
1261 matched = unix_do_match(sbase,ebase,case_sig) &&
1262 (trans2 || unix_do_match(sext,eext,case_sig));
1264 DEBUG(8,("unix_mask_match returning %d\n", matched));
1269 /*********************************************************
1270 * Recursive routine that is called by mask_match.
1271 * Does the actual matching. Returns True if matched,
1272 * False if failed. This is the 'new' NT style matcher.
1273 *********************************************************/
1275 BOOL do_match(char *str, char *regexp, int case_sig)
1279 for( p = regexp; *p && *str; ) {
1286 /* Look for a character matching
1287 the one after the '*' */
1290 return True; /* Automatic match */
1292 while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
1294 /* Now eat all characters that match, as
1295 we want the *last* character to match. */
1296 while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str))))
1298 str--; /* We've eaten the match char after the '*' */
1299 if(do_match(str,p,case_sig)) {
1316 if(toupper(*str) != toupper(*p)) {
1328 if (!*p && str[0] == '.' && str[1] == 0) {
1332 if (!*str && *p == '?') {
1338 if(!*str && (*p == '*' && p[1] == '\0')) {
1346 /*********************************************************
1347 * Routine to match a given string with a regexp - uses
1348 * simplified regexp that takes * and ? only. Case can be
1349 * significant or not.
1350 * The 8.3 handling was rewritten by Ums Harald <Harald.Ums@pro-sieben.de>
1351 * This is the new 'NT style' matcher.
1352 *********************************************************/
1354 BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
1357 pstring t_pattern, t_filename, te_pattern, te_filename;
1358 fstring ebase,eext,sbase,sext;
1360 BOOL matched = False;
1362 /* Make local copies of str and regexp */
1363 pstrcpy(t_pattern,regexp);
1364 pstrcpy(t_filename,str);
1368 * Not sure if this is a good idea. JRA.
1370 if(trans2 && is_8_3(t_pattern,False) && is_8_3(t_filename,False))
1375 if (!strchr(t_filename,'.')) {
1376 pstrcat(t_filename,".");
1380 /* Remove any *? and ** as they are meaningless */
1381 string_sub(t_pattern, "*?", "*");
1382 string_sub(t_pattern, "**", "*");
1384 if (strequal(t_pattern,"*"))
1387 DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", t_filename, t_pattern, case_sig));
1391 * Match each component of the regexp, split up by '.'
1394 char *fp, *rp, *cp2, *cp1;
1395 BOOL last_wcard_was_star = False;
1396 int num_path_components, num_regexp_components;
1398 pstrcpy(te_pattern,t_pattern);
1399 pstrcpy(te_filename,t_filename);
1401 * Remove multiple "*." patterns.
1403 string_sub(te_pattern, "*.*.", "*.");
1404 num_regexp_components = count_chars(te_pattern, '.');
1405 num_path_components = count_chars(te_filename, '.');
1408 * Check for special 'hack' case of "DIR a*z". - needs to match a.b.c...z
1410 if(num_regexp_components == 0)
1411 matched = do_match( te_filename, te_pattern, case_sig);
1413 for( cp1 = te_pattern, cp2 = te_filename; cp1;) {
1414 fp = strchr(cp2, '.');
1417 rp = strchr(cp1, '.');
1421 if(cp1[strlen(cp1)-1] == '*')
1422 last_wcard_was_star = True;
1424 last_wcard_was_star = False;
1426 if(!do_match(cp2, cp1, case_sig))
1429 cp1 = rp ? rp + 1 : NULL;
1430 cp2 = fp ? fp + 1 : "";
1432 if(last_wcard_was_star || ((cp1 != NULL) && (*cp1 == '*'))) {
1433 /* Eat the extra path components. */
1436 for(i = 0; i < num_path_components - num_regexp_components; i++) {
1437 fp = strchr(cp2, '.');
1441 if((cp1 != NULL) && do_match( cp2, cp1, case_sig)) {
1442 cp2 = fp ? fp + 1 : "";
1445 cp2 = fp ? fp + 1 : "";
1447 num_path_components -= i;
1450 if(cp1 == NULL && ((*cp2 == '\0') || last_wcard_was_star))
1455 /* -------------------------------------------------
1456 * Behaviour of Win95
1457 * for 8.3 filenames and 8.3 Wildcards
1458 * -------------------------------------------------
1460 if (strequal (t_filename, ".")) {
1462 * Patterns: *.* *. ?. ? are valid
1465 if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
1466 strequal(t_pattern, "?.") || strequal(t_pattern, "?"))
1468 } else if (strequal (t_filename, "..")) {
1470 * Patterns: *.* *. ?. ? *.? are valid
1473 if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
1474 strequal(t_pattern, "?.") || strequal(t_pattern, "?") ||
1475 strequal(t_pattern, "*.?") || strequal(t_pattern, "?.*"))
1479 if ((p = strrchr (t_pattern, '.'))) {
1481 * Wildcard has a suffix.
1484 fstrcpy (ebase, t_pattern);
1486 fstrcpy (eext, p + 1);
1488 /* pattern ends in DOT: treat as if there is no DOT */
1490 if (strequal (ebase, "*"))
1495 * No suffix for wildcard.
1497 fstrcpy (ebase, t_pattern);
1501 p = strrchr (t_filename, '.');
1502 if (p && (p[1] == 0) ) {
1504 * Filename has an extension of '.' only.
1506 *p = 0; /* nuke dot at end of string */
1507 p = 0; /* and treat it as if there is no extension */
1512 * Filename has an extension.
1515 fstrcpy (sbase, t_filename);
1516 fstrcpy (sext, p + 1);
1518 matched = do_match(sbase, ebase, case_sig)
1519 && do_match(sext, eext, case_sig);
1521 /* pattern has no extension */
1522 /* Really: match complete filename with pattern ??? means exactly 3 chars */
1523 matched = do_match(str, ebase, case_sig);
1527 * Filename has no extension.
1529 fstrcpy (sbase, t_filename);
1532 /* pattern has extension */
1533 matched = do_match(sbase, ebase, case_sig)
1534 && do_match(sext, eext, case_sig);
1536 matched = do_match(sbase, ebase, case_sig);
1537 #ifdef EMULATE_WEIRD_W95_MATCHING
1539 * Even Microsoft has some problems
1540 * Behaviour Win95 -> local disk
1541 * is different from Win95 -> smb drive from Nt 4.0
1542 * This branch would reflect the Win95 local disk behaviour
1545 /* a? matches aa and a in w95 */
1546 fstrcat (sbase, ".");
1547 matched = do_match(sbase, ebase, case_sig);
1555 DEBUG(8,("mask_match returning %d\n", matched));
1560 /****************************************************************************
1561 become a daemon, discarding the controlling terminal
1562 ****************************************************************************/
1563 void become_daemon(void)
1569 /* detach from the terminal */
1572 #elif defined(TIOCNOTTY)
1574 int i = sys_open("/dev/tty", O_RDWR, 0);
1576 ioctl(i, (int) TIOCNOTTY, (char *)0);
1580 #endif /* HAVE_SETSID */
1582 /* Close fd's 0,1,2. Needed if started by rsh */
1587 /****************************************************************************
1588 put up a yes/no prompt
1589 ****************************************************************************/
1595 if (!fgets(ans,sizeof(ans)-1,stdin))
1598 if (*ans == 'y' || *ans == 'Y')
1606 /****************************************************************************
1607 set the length of a file from a filedescriptor.
1608 Returns 0 on success, -1 on failure.
1609 ****************************************************************************/
1610 int set_filelen(int fd, SMB_OFF_T len)
1612 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1613 extend a file with ftruncate. Provide alternate implementation
1616 #ifdef HAVE_FTRUNCATE_EXTEND
1617 return sys_ftruncate(fd, len);
1621 SMB_OFF_T currpos = sys_lseek(fd, (SMB_OFF_T)0, SEEK_CUR);
1625 /* Do an fstat to see if the file is longer than
1626 the requested size (call ftruncate),
1627 or shorter, in which case seek to len - 1 and write 1
1629 if(sys_fstat(fd, &st)<0)
1633 if (S_ISFIFO(st.st_mode)) return 0;
1636 if(st.st_size == len)
1638 if(st.st_size > len)
1639 return sys_ftruncate(fd, len);
1641 if(sys_lseek(fd, len-1, SEEK_SET) != len -1)
1643 if(write(fd, &c, 1)!=1)
1645 /* Seek to where we were */
1646 if(sys_lseek(fd, currpos, SEEK_SET) != currpos)
1654 /****************************************************************************
1655 this is a version of setbuffer() for those machines that only have setvbuf
1656 ****************************************************************************/
1657 void setbuffer(FILE *f,char *buf,int bufsize)
1659 setvbuf(f,buf,_IOFBF,bufsize);
1664 /****************************************************************************
1665 parse out a filename from a path name. Assumes dos style filenames.
1666 ****************************************************************************/
1667 static char *filename_dos(char *path,char *buf)
1669 char *p = strrchr(path,'\\');
1681 /****************************************************************************
1682 expand a pointer to be a particular size
1683 ****************************************************************************/
1684 void *Realloc(void *p,size_t size)
1690 DEBUG(5,("Realloc asked for 0 bytes\n"));
1695 ret = (void *)malloc(size);
1697 ret = (void *)realloc(p,size);
1702 smb_mem_write_info(ret, dbf);
1707 DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",size));
1713 /****************************************************************************
1714 get my own name and IP
1715 ****************************************************************************/
1716 BOOL get_myname(char *my_name,struct in_addr *ip)
1723 /* get my host name */
1724 if (gethostname(hostname, MAXHOSTNAMELEN) == -1)
1726 DEBUG(0,("gethostname failed\n"));
1731 if ((hp = Get_Hostbyname(hostname)) == 0)
1733 DEBUG(0,( "Get_Hostbyname: Unknown host %s\n",hostname));
1739 /* split off any parts after an initial . */
1740 char *p = strchr(hostname,'.');
1743 fstrcpy(my_name,hostname);
1747 putip((char *)ip,(char *)hp->h_addr);
1753 /****************************************************************************
1754 true if two IP addresses are equal
1755 ****************************************************************************/
1756 BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
1759 a1 = ntohl(ip1.s_addr);
1760 a2 = ntohl(ip2.s_addr);
1765 /****************************************************************************
1766 interpret a protocol description string, with a default
1767 ****************************************************************************/
1768 int interpret_protocol(char *str,int def)
1770 if (strequal(str,"NT1"))
1771 return(PROTOCOL_NT1);
1772 if (strequal(str,"LANMAN2"))
1773 return(PROTOCOL_LANMAN2);
1774 if (strequal(str,"LANMAN1"))
1775 return(PROTOCOL_LANMAN1);
1776 if (strequal(str,"CORE"))
1777 return(PROTOCOL_CORE);
1778 if (strequal(str,"COREPLUS"))
1779 return(PROTOCOL_COREPLUS);
1780 if (strequal(str,"CORE+"))
1781 return(PROTOCOL_COREPLUS);
1783 DEBUG(0,("Unrecognised protocol level %s\n",str));
1789 /****************************************************************************
1790 interpret an internet address or name into an IP address in 4 byte form
1791 ****************************************************************************/
1792 uint32 interpret_addr(char *str)
1797 BOOL pure_address = True;
1799 if (strcmp(str,"0.0.0.0") == 0) return(0);
1800 if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
1802 for (i=0; pure_address && str[i]; i++)
1803 if (!(isdigit((int)str[i]) || str[i] == '.'))
1804 pure_address = False;
1806 /* if it's in the form of an IP address then get the lib to interpret it */
1808 res = inet_addr(str);
1810 /* otherwise assume it's a network name of some sort and use
1812 if ((hp = Get_Hostbyname(str)) == 0) {
1813 DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
1816 if(hp->h_addr == NULL) {
1817 DEBUG(3,("Get_Hostbyname: host address is invalid for host %s\n",str));
1820 putip((char *)&res,(char *)hp->h_addr);
1823 if (res == (uint32)-1) return(0);
1828 /*******************************************************************
1829 a convenient addition to interpret_addr()
1830 ******************************************************************/
1831 struct in_addr *interpret_addr2(char *str)
1833 static struct in_addr ret;
1834 uint32 a = interpret_addr(str);
1839 /*******************************************************************
1840 check if an IP is the 0.0.0.0
1841 ******************************************************************/
1842 BOOL zero_ip(struct in_addr ip)
1845 putip((char *)&a,(char *)&ip);
1850 /*******************************************************************
1851 matchname - determine if host name matches IP address
1852 ******************************************************************/
1853 BOOL matchname(char *remotehost,struct in_addr addr)
1858 if ((hp = Get_Hostbyname(remotehost)) == 0) {
1859 DEBUG(0,("Get_Hostbyname(%s): lookup failure", remotehost));
1864 * Make sure that gethostbyname() returns the "correct" host name.
1865 * Unfortunately, gethostbyname("localhost") sometimes yields
1866 * "localhost.domain". Since the latter host name comes from the
1867 * local DNS, we just have to trust it (all bets are off if the local
1868 * DNS is perverted). We always check the address list, though.
1871 if (strcasecmp(remotehost, hp->h_name)
1872 && strcasecmp(remotehost, "localhost")) {
1873 DEBUG(0,("host name/name mismatch: %s != %s",
1874 remotehost, hp->h_name));
1878 /* Look up the host address in the address list we just got. */
1879 for (i = 0; hp->h_addr_list[i]; i++) {
1880 if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
1885 * The host name does not map to the original host address. Perhaps
1886 * someone has compromised a name server. More likely someone botched
1887 * it, but that could be dangerous, too.
1890 DEBUG(0,("host name/address mismatch: %s != %s",
1891 inet_ntoa(addr), hp->h_name));
1896 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1897 /******************************************************************
1898 Remove any mount options such as -rsize=2048,wsize=2048 etc.
1899 Based on a fix from <Thomas.Hepper@icem.de>.
1900 *******************************************************************/
1902 static void strip_mount_options( pstring *str)
1907 while(*p && !isspace(*p))
1909 while(*p && isspace(*p))
1914 pstrcpy(tmp_str, p);
1915 pstrcpy(*str, tmp_str);
1920 /*******************************************************************
1921 Patch from jkf@soton.ac.uk
1922 Split Luke's automount_server into YP lookup and string splitter
1923 so can easily implement automount_path().
1924 As we may end up doing both, cache the last YP result.
1925 *******************************************************************/
1927 #ifdef WITH_NISPLUS_HOME
1928 static char *automount_lookup(char *user_name)
1930 static fstring last_key = "";
1931 static pstring last_value = "";
1933 char *nis_map = (char *)lp_nis_home_map_name();
1935 char nis_domain[NIS_MAXNAMELEN + 1];
1936 char buffer[NIS_MAXATTRVAL + 1];
1941 strncpy(nis_domain, (char *)nis_local_directory(), NIS_MAXNAMELEN);
1942 nis_domain[NIS_MAXNAMELEN] = '\0';
1944 DEBUG(5, ("NIS+ Domain: %s\n", nis_domain));
1946 if (strcmp(user_name, last_key))
1948 slprintf(buffer, sizeof(buffer)-1, "[%s=%s]%s.%s", "key", user_name, nis_map, nis_domain);
1949 DEBUG(5, ("NIS+ querystring: %s\n", buffer));
1951 if (result = nis_list(buffer, RETURN_RESULT, NULL, NULL))
1953 if (result->status != NIS_SUCCESS)
1955 DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
1956 fstrcpy(last_key, ""); pstrcpy(last_value, "");
1960 object = result->objects.objects_val;
1961 if (object->zo_data.zo_type == ENTRY_OBJ)
1963 entry = &object->zo_data.objdata_u.en_data;
1964 DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
1965 DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
1967 pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
1968 string_sub(last_value, "&", user_name);
1969 fstrcpy(last_key, user_name);
1973 nis_freeresult(result);
1976 strip_mount_options(&last_value);
1978 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
1981 #else /* WITH_NISPLUS_HOME */
1982 static char *automount_lookup(char *user_name)
1984 static fstring last_key = "";
1985 static pstring last_value = "";
1987 int nis_error; /* returned by yp all functions */
1988 char *nis_result; /* yp_match inits this */
1989 int nis_result_len; /* and set this */
1990 char *nis_domain; /* yp_get_default_domain inits this */
1991 char *nis_map = (char *)lp_nis_home_map_name();
1993 if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
1995 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
1999 DEBUG(5, ("NIS Domain: %s\n", nis_domain));
2001 if (!strcmp(user_name, last_key))
2003 nis_result = last_value;
2004 nis_result_len = strlen(last_value);
2009 if ((nis_error = yp_match(nis_domain, nis_map,
2010 user_name, strlen(user_name),
2011 &nis_result, &nis_result_len)) != 0)
2013 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
2014 yperr_string(nis_error), user_name, nis_map));
2016 if (!nis_error && nis_result_len >= sizeof(pstring))
2018 nis_result_len = sizeof(pstring)-1;
2020 fstrcpy(last_key, user_name);
2021 strncpy(last_value, nis_result, nis_result_len);
2022 last_value[nis_result_len] = '\0';
2025 strip_mount_options(&last_value);
2027 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
2030 #endif /* WITH_NISPLUS_HOME */
2033 /*******************************************************************
2034 Patch from jkf@soton.ac.uk
2035 This is Luke's original function with the NIS lookup code
2036 moved out to a separate function.
2037 *******************************************************************/
2038 static char *automount_server(char *user_name)
2040 static pstring server_name;
2042 /* use the local machine name as the default */
2043 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
2044 pstrcpy(server_name, local_machine);
2046 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2048 if (lp_nis_home_map())
2050 int home_server_len;
2051 char *automount_value = automount_lookup(user_name);
2052 home_server_len = strcspn(automount_value,":");
2053 DEBUG(5, ("NIS lookup succeeded. Home server length: %d\n",home_server_len));
2054 if (home_server_len > sizeof(pstring))
2056 home_server_len = sizeof(pstring);
2058 strncpy(server_name, automount_value, home_server_len);
2059 server_name[home_server_len] = '\0';
2063 DEBUG(4,("Home server: %s\n", server_name));
2068 /*******************************************************************
2069 Patch from jkf@soton.ac.uk
2070 Added this to implement %p (NIS auto-map version of %H)
2071 *******************************************************************/
2072 static char *automount_path(char *user_name)
2074 static pstring server_path;
2076 /* use the passwd entry as the default */
2077 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
2078 /* pstrcpy() copes with get_home_dir() returning NULL */
2079 pstrcpy(server_path, get_home_dir(user_name));
2081 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2083 if (lp_nis_home_map())
2085 char *home_path_start;
2086 char *automount_value = automount_lookup(user_name);
2087 home_path_start = strchr(automount_value,':');
2088 if (home_path_start != NULL)
2090 DEBUG(5, ("NIS lookup succeeded. Home path is: %s\n",
2091 home_path_start?(home_path_start+1):""));
2092 pstrcpy(server_path, home_path_start+1);
2097 DEBUG(4,("Home server path: %s\n", server_path));
2103 /*******************************************************************
2104 sub strings with useful parameters
2105 Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
2106 Paul Rippin <pr3245@nopc.eurostat.cec.be>
2107 ********************************************************************/
2108 void standard_sub_basic(char *str)
2112 struct passwd *pass;
2113 char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user;
2115 for (s = str ; s && *s && (p = strchr(s,'%')); s = p )
2121 if ((pass = Get_Pwnam(username,False))!=NULL)
2123 string_sub(p,"%G",gidtoname(pass->pw_gid));
2131 case 'N' : string_sub(p,"%N", automount_server(username)); break;
2132 case 'I' : string_sub(p,"%I", client_addr(Client)); break;
2133 case 'L' : string_sub(p,"%L", local_machine); break;
2134 case 'M' : string_sub(p,"%M", client_name(Client)); break;
2135 case 'R' : string_sub(p,"%R", remote_proto); break;
2136 case 'T' : string_sub(p,"%T", timestring()); break;
2137 case 'U' : string_sub(p,"%U", username); break;
2138 case 'a' : string_sub(p,"%a", remote_arch); break;
2141 slprintf(pidstr,sizeof(pidstr) - 1, "%d",(int)getpid());
2142 string_sub(p,"%d", pidstr);
2145 case 'h' : string_sub(p,"%h", myhostname); break;
2146 case 'm' : string_sub(p,"%m", remote_machine); break;
2147 case 'v' : string_sub(p,"%v", VERSION); break;
2148 case '$' : /* Expand environment variables */
2150 /* Contributed by Branko Cibej <branko.cibej@hermes.si> */
2161 if ((q = strchr(p,')')) == NULL)
2163 DEBUG(0,("standard_sub_basic: Unterminated environment \
2164 variable [%s]\n", p));
2170 copylen = MIN((q-r),(sizeof(envname)-1));
2171 strncpy(envname,r,copylen);
2172 envname[copylen] = '\0';
2174 if ((envval = getenv(envname)) == NULL)
2176 DEBUG(0,("standard_sub_basic: Environment variable [%s] not set\n",
2182 copylen = MIN((q+1-p),(sizeof(envname)-1));
2183 strncpy(envname,p,copylen);
2184 envname[copylen] = '\0';
2185 string_sub(p,envname,envval);
2188 case '\0': p++; break; /* don't run off end if last character is % */
2189 default : p+=2; break;
2196 /****************************************************************************
2197 do some standard substitutions in a string
2198 ****************************************************************************/
2199 void standard_sub(connection_struct *conn,char *str)
2203 for (s=str; (p=strchr(s, '%'));s=p)
2208 if ((home = get_home_dir(conn->user)) != NULL) {
2209 string_sub(p,"%H",home);
2215 /* Patch from jkf@soton.ac.uk Left the %N (NIS
2216 * server name) in standard_sub_basic as it is
2217 * a feature for logon servers, hence uses the
2218 * username. The %p (NIS server path) code is
2219 * here as it is used instead of the default
2220 * "path =" string in [homes] and so needs the
2221 * service name, not the username. */
2222 case 'p': string_sub(p,"%p", automount_path(lp_servicename(SNUM(conn)))); break;
2223 case 'P': string_sub(p,"%P",conn->connectpath); break;
2224 case 'S': string_sub(p,"%S", lp_servicename(SNUM(conn))); break;
2225 case 'g': string_sub(p,"%g", gidtoname(conn->gid)); break;
2226 case 'u': string_sub(p,"%u", conn->user); break;
2228 case '\0': p++; break; /* don't run off the end of the string */
2229 default : p+=2; break;
2233 standard_sub_basic(str);
2238 /*******************************************************************
2239 are two IPs on the same subnet?
2240 ********************************************************************/
2241 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
2243 uint32 net1,net2,nmask;
2245 nmask = ntohl(mask.s_addr);
2246 net1 = ntohl(ip1.s_addr);
2247 net2 = ntohl(ip2.s_addr);
2249 return((net1 & nmask) == (net2 & nmask));
2253 /****************************************************************************
2254 a wrapper for gethostbyname() that tries with all lower and all upper case
2255 if the initial name fails
2256 ****************************************************************************/
2257 struct hostent *Get_Hostbyname(const char *name)
2259 char *name2 = strdup(name);
2260 struct hostent *ret;
2264 DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
2270 * This next test is redundent and causes some systems (with
2271 * broken isalnum() calls) problems.
2276 if (!isalnum(*name2))
2283 ret = sys_gethostbyname(name2);
2290 /* try with all lowercase */
2292 ret = sys_gethostbyname(name2);
2299 /* try with all uppercase */
2301 ret = sys_gethostbyname(name2);
2308 /* nothing works :-( */
2314 /****************************************************************************
2315 check if a process exists. Does this work on all unixes?
2316 ****************************************************************************/
2318 BOOL process_exists(int pid)
2320 return(kill(pid,0) == 0 || errno != ESRCH);
2324 /****************************************************************************
2325 Setup the groups a user belongs to.
2326 ****************************************************************************/
2327 int get_unixgroups(char *user, uid_t uid, gid_t gid, int *p_ngroups, gid_t **p_groups)
2331 gid_t *groups = NULL;
2333 if (-1 == initgroups(user,gid))
2337 DEBUG(0,("Unable to initgroups!\n"));
2338 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
2340 DEBUG(0,("This is probably a problem with the account %s\n", user));
2346 ngroups = sys_getgroups(0,&grp);
2352 if((groups = (gid_t *)malloc(sizeof(gid_t)*ngroups)) == NULL)
2354 DEBUG(0,("get_unixgroups malloc fail !\n"));
2358 ngroups = sys_getgroups(ngroups,groups);
2360 (*p_ngroups) = ngroups;
2361 (*p_groups) = groups;
2363 DEBUG( 3, ( "%s is in %d groups: ", user, ngroups ) );
2364 for (i = 0; i < ngroups; i++ )
2366 DEBUG( 3, ( "%s%d", (i ? ", " : ""), (int)groups[i] ) );
2368 DEBUG( 3, ( "\n" ) );
2373 /*******************************************************************
2374 turn a uid into a user name
2375 ********************************************************************/
2376 char *uidtoname(uid_t uid)
2378 static char name[40];
2379 struct passwd *pass = getpwuid(uid);
2380 if (pass) return(pass->pw_name);
2381 slprintf(name, sizeof(name) - 1, "%d",(int)uid);
2386 /*******************************************************************
2387 turn a gid into a group name
2388 ********************************************************************/
2390 char *gidtoname(gid_t gid)
2392 static char name[40];
2393 struct group *grp = getgrgid(gid);
2394 if (grp) return(grp->gr_name);
2395 slprintf(name,sizeof(name) - 1, "%d",(int)gid);
2399 /*******************************************************************
2400 turn a group name into a gid
2401 ********************************************************************/
2403 BOOL nametogid(const char *name, gid_t *gid)
2405 struct group *grp = getgrnam(name);
2411 else if (isdigit(name[0]))
2413 *gid = (gid_t)get_number(name);
2422 /*******************************************************************
2423 turn a user name into a uid
2424 ********************************************************************/
2425 BOOL nametouid(const char *name, uid_t *uid)
2427 struct passwd *pass = Get_Pwnam(name, False);
2430 *uid = pass->pw_uid;
2433 else if (isdigit(name[0]))
2435 *uid = (uid_t)get_number(name);
2444 /*******************************************************************
2445 something really nasty happened - panic!
2446 ********************************************************************/
2447 void smb_panic(char *why)
2449 char *cmd = lp_panic_action();
2453 DEBUG(0,("PANIC: %s\n", why));
2459 /*******************************************************************
2460 a readdir wrapper which just returns the file name
2461 ********************************************************************/
2462 char *readdirname(DIR *p)
2467 if (!p) return(NULL);
2469 ptr = (struct dirent *)readdir(p);
2470 if (!ptr) return(NULL);
2472 dname = ptr->d_name;
2475 if (telldir(p) < 0) return(NULL);
2478 #ifdef HAVE_BROKEN_READDIR
2479 /* using /usr/ucb/cc is BAD */
2485 memcpy(buf, dname, NAMLEN(ptr)+1);
2492 /*******************************************************************
2493 Utility function used to decide if the last component
2494 of a path matches a (possibly wildcarded) entry in a namelist.
2495 ********************************************************************/
2497 BOOL is_in_path(char *name, name_compare_entry *namelist)
2499 pstring last_component;
2502 DEBUG(8, ("is_in_path: %s\n", name));
2504 /* if we have no list it's obviously not in the path */
2505 if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL)))
2507 DEBUG(8,("is_in_path: no name list.\n"));
2511 /* Get the last component of the unix name. */
2512 p = strrchr(name, '/');
2513 strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
2514 last_component[sizeof(last_component)-1] = '\0';
2516 for(; namelist->name != NULL; namelist++)
2518 if(namelist->is_wild)
2521 * Look for a wildcard match. Use the old
2522 * 'unix style' mask match, rather than the
2525 if (unix_mask_match(last_component, namelist->name, case_sensitive, False))
2527 DEBUG(8,("is_in_path: mask match succeeded\n"));
2533 if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
2534 (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0)))
2536 DEBUG(8,("is_in_path: match succeeded\n"));
2541 DEBUG(8,("is_in_path: match not found\n"));
2546 /*******************************************************************
2547 Strip a '/' separated list into an array of
2548 name_compare_enties structures suitable for
2549 passing to is_in_path(). We do this for
2550 speed so we can pre-parse all the names in the list
2551 and don't do it for each call to is_in_path().
2552 namelist is modified here and is assumed to be
2553 a copy owned by the caller.
2554 We also check if the entry contains a wildcard to
2555 remove a potentially expensive call to mask_match
2557 ********************************************************************/
2559 void set_namearray(name_compare_entry **ppname_array, char *namelist)
2562 char *nameptr = namelist;
2563 int num_entries = 0;
2566 (*ppname_array) = NULL;
2568 if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0')))
2571 /* We need to make two passes over the string. The
2572 first to count the number of elements, the second
2577 if ( *nameptr == '/' )
2579 /* cope with multiple (useless) /s) */
2583 /* find the next / */
2584 name_end = strchr(nameptr, '/');
2586 /* oops - the last check for a / didn't find one. */
2587 if (name_end == NULL)
2590 /* next segment please */
2591 nameptr = name_end + 1;
2595 if(num_entries == 0)
2598 if(( (*ppname_array) = (name_compare_entry *)malloc(
2599 (num_entries + 1) * sizeof(name_compare_entry))) == NULL)
2601 DEBUG(0,("set_namearray: malloc fail\n"));
2605 /* Now copy out the names */
2610 if ( *nameptr == '/' )
2612 /* cope with multiple (useless) /s) */
2616 /* find the next / */
2617 if ((name_end = strchr(nameptr, '/')) != NULL)
2622 /* oops - the last check for a / didn't find one. */
2623 if(name_end == NULL)
2626 (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
2627 (strchr( nameptr, '*')!=NULL));
2628 if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
2630 DEBUG(0,("set_namearray: malloc fail (1)\n"));
2634 /* next segment please */
2635 nameptr = name_end + 1;
2639 (*ppname_array)[i].name = NULL;
2644 /****************************************************************************
2645 routine to free a namearray.
2646 ****************************************************************************/
2648 void free_namearray(name_compare_entry *name_array)
2653 if(name_array->name != NULL)
2654 free(name_array->name);
2656 free((char *)name_array);
2659 /****************************************************************************
2660 routine to do file locking
2661 ****************************************************************************/
2662 BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
2665 SMB_STRUCT_FLOCK lock;
2668 if(lp_ole_locking_compat()) {
2669 SMB_OFF_T mask = ((SMB_OFF_T)0xC) << (SMB_OFF_T_BITS-4);
2670 SMB_OFF_T mask2= ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4);
2672 /* make sure the count is reasonable, we might kill the lockd otherwise */
2675 /* the offset is often strange - remove 2 of its bits if either of
2676 the top two bits are set. Shift the top ones by two bits. This
2677 still allows OLE2 apps to operate, but should stop lockd from
2679 if ((offset & mask) != 0)
2680 offset = (offset & ~mask) | (((offset & mask) >> 2) & mask2);
2682 SMB_OFF_T mask = ((SMB_OFF_T)0x8) << (SMB_OFF_T_BITS-4);
2683 SMB_OFF_T neg_mask = ~mask;
2685 /* interpret negative counts as large numbers */
2689 /* no negative offsets */
2693 /* count + offset must be in range */
2694 while ((offset < 0 || (offset + count < 0)) && mask)
2697 mask = ((mask >> 1) & neg_mask);
2701 DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
2704 lock.l_whence = SEEK_SET;
2705 lock.l_start = offset;
2711 ret = fcntl(fd,op,&lock);
2716 dbgtext("fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count);
2717 dbgtext("a 'file too large' error. This can happen when using 64 bit lock offsets\n");
2718 dbgtext("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n");
2720 /* 32 bit NFS file system, retry with smaller offset */
2722 lock.l_len = count & 0xffffffff;
2723 ret = fcntl(fd,op,&lock);
2727 DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
2730 if (op == SMB_F_GETLK)
2733 (lock.l_type != F_UNLCK) &&
2734 (lock.l_pid != 0) &&
2735 (lock.l_pid != getpid()))
2737 DEBUG(3,("fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
2741 /* it must be not locked or locked by me */
2745 /* a lock set or unset */
2748 DEBUG(3,("lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
2749 (double)offset,(double)count,op,type,strerror(errno)));
2751 /* perhaps it doesn't support this sort of locking?? */
2752 if (errno == EINVAL)
2754 DEBUG(3,("locking not supported? returning True\n"));
2761 /* everything went OK */
2762 DEBUG(8,("Lock call successful\n"));
2770 /*******************************************************************
2771 is the name specified one of my netbios names
2772 returns true is it is equal, false otherwise
2773 ********************************************************************/
2774 BOOL is_myname(char *s)
2779 for (n=0; my_netbios_names[n]; n++) {
2780 if (strequal(my_netbios_names[n], s))
2783 DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
2787 /*******************************************************************
2788 set the horrid remote_arch string based on an enum.
2789 ********************************************************************/
2790 void set_remote_arch(enum remote_arch_types type)
2796 fstrcpy(remote_arch, "WfWg");
2799 fstrcpy(remote_arch, "OS2");
2802 fstrcpy(remote_arch, "Win95");
2805 fstrcpy(remote_arch, "WinNT");
2808 fstrcpy(remote_arch,"Samba");
2811 ra_type = RA_UNKNOWN;
2812 fstrcpy(remote_arch, "UNKNOWN");
2817 /*******************************************************************
2818 Get the remote_arch type.
2819 ********************************************************************/
2820 enum remote_arch_types get_remote_arch(void)
2826 /*******************************************************************
2827 align a pointer to a multiple of 2 bytes
2828 ********************************************************************/
2829 char *align2(char *q, char *base)
2838 void out_ascii(FILE *f, unsigned char *buf,int len)
2843 fprintf(f, "%c", isprint(buf[i])?buf[i]:'.');
2847 void out_data(FILE *f,char *buf1,int len, int per_line)
2849 unsigned char *buf = (unsigned char *)buf1;
2856 fprintf(f, "[%03X] ",i);
2859 fprintf(f, "%02X ",(int)buf[i]);
2861 if (i%(per_line/2) == 0) fprintf(f, " ");
2862 if (i%per_line == 0)
2864 out_ascii(f,&buf[i-per_line ],per_line/2); fprintf(f, " ");
2865 out_ascii(f,&buf[i-per_line/2],per_line/2); fprintf(f, "\n");
2866 if (i<len) fprintf(f, "[%03X] ",i);
2869 if ((i%per_line) != 0)
2873 n = per_line - (i%per_line);
2875 if (n>(per_line/2)) fprintf(f, " ");
2880 n = MIN(per_line/2,i%per_line);
2881 out_ascii(f,&buf[i-(i%per_line)],n); fprintf(f, " ");
2882 n = (i%per_line) - n;
2883 if (n>0) out_ascii(f,&buf[i-n],n);
2888 void print_asc(int level, unsigned char *buf,int len)
2892 DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
2895 void dump_data(int level,char *buf1,int len)
2897 unsigned char *buf = (unsigned char *)buf1;
2901 DEBUG(level,("[%03X] ",i));
2903 DEBUG(level,("%02X ",(int)buf[i]));
2905 if (i%8 == 0) DEBUG(level,(" "));
2907 print_asc(level,&buf[i-16],8); DEBUG(level,(" "));
2908 print_asc(level,&buf[i-8],8); DEBUG(level,("\n"));
2909 if (i<len) DEBUG(level,("[%03X] ",i));
2917 if (n>8) DEBUG(level,(" "));
2918 while (n--) DEBUG(level,(" "));
2921 print_asc(level,&buf[i-(i%16)],n); DEBUG(level,(" "));
2923 if (n>0) print_asc(level,&buf[i-n],n);
2924 DEBUG(level,("\n"));
2928 char *tab_depth(int depth)
2930 static pstring spaces;
2931 memset(spaces, ' ', depth * 4);
2932 spaces[depth * 4] = 0;
2936 /*****************************************************************************
2937 * Provide a checksum on a string
2939 * Input: s - the null-terminated character string for which the checksum
2940 * will be calculated.
2942 * Output: The checksum value calculated for s.
2944 * ****************************************************************************
2946 int str_checksum(const char *s)
2954 res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
2959 } /* str_checksum */
2963 /*****************************************************************
2964 zero a memory area then free it. Used to catch bugs faster
2965 *****************************************************************/
2966 void zero_free(void *p, size_t size)
2973 /*****************************************************************
2974 set our open file limit to a requested max and return the limit
2975 *****************************************************************/
2976 int set_maxfiles(int requested_max)
2978 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
2980 getrlimit(RLIMIT_NOFILE, &rlp);
2981 /* Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
2982 * account for the extra fd we need
2983 * as well as the log files and standard
2985 rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
2986 setrlimit(RLIMIT_NOFILE, &rlp);
2987 getrlimit(RLIMIT_NOFILE, &rlp);
2988 return rlp.rlim_cur;
2991 * No way to know - just guess...
2993 return requested_max;
2998 /*****************************************************************
2999 splits out the last subkey of a key
3000 *****************************************************************/
3001 void reg_get_subkey(char *full_keyname, char *key_name, char *subkey_name)
3003 split_at_last_component(full_keyname, key_name, '\\', subkey_name);
3006 /*****************************************************************
3007 splits out the start of the key (HKLM or HKU) and the rest of the key
3008 *****************************************************************/
3009 BOOL reg_split_key(char *full_keyname, uint32 *reg_type, char *key_name)
3013 if (!next_token(&full_keyname, tmp, "\\", sizeof(tmp)))
3020 DEBUG(10, ("reg_split_key: hive %s\n", tmp));
3022 if (strequal(tmp, "HKLM") || strequal(tmp, "HKEY_LOCAL_MACHINE"))
3024 (*reg_type) = HKEY_LOCAL_MACHINE;
3026 else if (strequal(tmp, "HKU") || strequal(tmp, "HKEY_USERS"))
3028 (*reg_type) = HKEY_USERS;
3032 DEBUG(10,("reg_split_key: unrecognised hive key %s\n", tmp));
3036 if (next_token(NULL, tmp, "\n\r", sizeof(tmp)))
3038 fstrcpy(key_name, tmp);
3045 DEBUG(10, ("reg_split_key: name %s\n", key_name));
3050 /****************************************************************************
3051 become the specified uid - permanently !
3052 ****************************************************************************/
3053 BOOL become_user_permanently(uid_t uid, gid_t gid)
3055 /* now completely lose our privilages. This is a fairly paranoid
3056 way of doing it, but it does work on all systems that I know of */
3058 #ifdef HAVE_SETRESUID
3060 * Firstly ensure all our uids are set to root.
3066 * Now ensure we change all our gids.
3068 setresgid(gid,gid,gid);
3071 * Now ensure all the uids are the user.
3073 setresuid(uid,uid,uid);
3076 * Firstly ensure all our uids are set to root.
3082 * Now ensure we change all our gids.
3088 * Now ensure all the uids are the user.
3094 if (getuid() != uid || geteuid() != uid ||
3095 getgid() != gid || getegid() != gid) {
3096 /* We failed to lose our privilages. */