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);
88 char *daynames[] = {"Mon","Tue","Wed","Thu","Fri","Sat","Sun"};
89 char *daynames_short[] = {"M", "Tu", "W", "Th", "F", "Sa", "Su"};
91 /*************************************************************
92 initialise password databases, domain names, domain sid.
93 **************************************************************/
94 BOOL init_myworkgroup(void)
96 fstrcpy(global_myworkgroup, lp_workgroup());
98 if (strequal(global_myworkgroup,"*"))
100 DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
106 /****************************************************************************
107 find a suitable temporary directory. The result should be copied immediately
108 as it may be overwritten by a subsequent call
109 ****************************************************************************/
113 if ((p = getenv("TMPDIR"))) {
119 /****************************************************************************
120 determine whether we are in the specified group
121 ****************************************************************************/
123 BOOL in_group(gid_t group, gid_t current_gid, int ngroups, gid_t *groups)
127 if (group == current_gid) return(True);
129 for (i=0;i<ngroups;i++)
130 if (group == groups[i])
137 /****************************************************************************
138 gets either a hex number (0xNNN) or decimal integer (NNN).
139 ****************************************************************************/
140 uint32 get_number(const char *tmp)
142 if (strnequal(tmp, "0x", 2))
144 return strtoul(tmp, (char**)NULL, 16);
148 return strtoul(tmp, (char**)NULL, 10);
152 /****************************************************************************
153 like atoi but gets the value up to the separater character
154 ****************************************************************************/
155 char *Atoic(char *p, int *n, char *c)
159 DEBUG(5, ("Atoic: malformed number\n"));
163 (*n) = (int)get_number(p);
165 if (strnequal(p, "0x", 2))
170 while ((*p) && isdigit(*p))
175 if (strchr(c, *p) == NULL)
177 DEBUG(5, ("Atoic: no separator characters (%s) not found\n", c));
184 uint32 *add_num_to_list(uint32 **num, int *count, int val)
186 (*num) = Realloc((*num), ((*count)+1) * sizeof(uint32));
191 (*num)[(*count)] = val;
197 /*************************************************************************
198 reads a list of numbers
199 *************************************************************************/
200 char *get_numlist(char *p, uint32 **num, int *count)
204 if (num == NULL || count == NULL)
212 while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':')
214 if (add_num_to_list(num, count, val) == NULL)
224 /*******************************************************************
225 copy an IP address from one buffer to another
226 ********************************************************************/
227 void putip(void *dest,void *src)
233 #define TRUNCATE_NETBIOS_NAME 1
235 /*******************************************************************
236 convert, possibly using a stupid microsoft-ism which has destroyed
237 the transport independence of netbios (for CIFS vendors that usually
238 use the Win95-type methods, not for NT to NT communication, which uses
239 DCE/RPC and therefore full-length unicode strings...) a dns name into
242 the netbios name (NOT necessarily null-terminated) is truncated to 15
245 ******************************************************************/
246 char *dns_to_netbios_name(char *dns_name)
248 static char netbios_name[16];
250 StrnCpy(netbios_name, dns_name, 15);
251 netbios_name[15] = 0;
253 #ifdef TRUNCATE_NETBIOS_NAME
254 /* ok. this is because of a stupid microsoft-ism. if the called host
255 name contains a '.', microsoft clients expect you to truncate the
256 netbios name up to and including the '.' this even applies, by
257 mistake, to workgroup (domain) names, which is _really_ daft.
259 for (i = 15; i >= 0; i--)
261 if (netbios_name[i] == '.')
267 #endif /* TRUNCATE_NETBIOS_NAME */
273 /****************************************************************************
274 interpret the weird netbios "name". Return the name type
275 ****************************************************************************/
276 static int name_interpret(char *in,char *out)
279 int len = (*in++) / 2;
283 if (len > 30 || len<1) return(0);
287 if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
291 *out = ((in[0]-'A')<<4) + (in[1]-'A');
299 /* Handle any scope names */
302 *out++ = '.'; /* Scope names are separated by periods */
303 len = *(unsigned char *)in++;
304 StrnCpy(out, in, len);
313 /****************************************************************************
314 mangle a name into netbios format
316 Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
317 ****************************************************************************/
318 int name_mangle( char *In, char *Out, char name_type )
326 /* Safely copy the input string, In, into buf[]. */
327 (void)memset( buf, 0, 20 );
328 if (strcmp(In,"*") == 0)
331 (void)slprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, name_type );
333 /* Place the length of the first field into the output buffer. */
337 /* Now convert the name to the rfc1001/1002 format. */
338 for( i = 0; i < 16; i++ )
340 c = toupper( buf[i] );
341 p[i*2] = ( (c >> 4) & 0x000F ) + 'A';
342 p[(i*2)+1] = (c & 0x000F) + 'A';
347 /* Add the scope string. */
348 for( i = 0, len = 0; NULL != scope; i++, len++ )
356 return( name_len(Out) );
368 return( name_len(Out) );
371 /*******************************************************************
372 check if a file exists
373 ********************************************************************/
374 BOOL file_exist(char *fname,SMB_STRUCT_STAT *sbuf)
377 if (!sbuf) sbuf = &st;
379 if (sys_stat(fname,sbuf) != 0)
382 return(S_ISREG(sbuf->st_mode));
385 /*******************************************************************
387 ********************************************************************/
388 int file_rename(char *from, char *to)
390 int rcode = rename (from, to);
394 /* Rename across filesystems needed. */
395 rcode = copy_reg (from, to);
400 /*******************************************************************
401 check a files mod time
402 ********************************************************************/
403 time_t file_modtime(char *fname)
407 if (sys_stat(fname,&st) != 0)
413 /*******************************************************************
414 check if a directory exists
415 ********************************************************************/
416 BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st)
423 if (sys_stat(dname,st) != 0)
426 ret = S_ISDIR(st->st_mode);
432 /*******************************************************************
433 returns the size in bytes of the named file
434 ********************************************************************/
435 SMB_OFF_T file_size(char *file_name)
439 if(sys_stat(file_name,&buf) != 0)
440 return (SMB_OFF_T)-1;
444 /*******************************************************************
445 return a string representing an attribute for a file
446 ********************************************************************/
447 char *attrib_string(uint16 mode)
449 static fstring attrstr;
453 if (mode & aVOLID) fstrcat(attrstr,"V");
454 if (mode & aDIR) fstrcat(attrstr,"D");
455 if (mode & aARCH) fstrcat(attrstr,"A");
456 if (mode & aHIDDEN) fstrcat(attrstr,"H");
457 if (mode & aSYSTEM) fstrcat(attrstr,"S");
458 if (mode & aRONLY) fstrcat(attrstr,"R");
463 /****************************************************************************
464 make a file into unix format
465 ****************************************************************************/
466 void unix_format(char *fname)
468 string_replace(fname,'\\','/');
471 /****************************************************************************
472 make a file into dos format
473 ****************************************************************************/
474 void dos_format(char *fname)
476 string_replace(fname,'/','\\');
479 /*******************************************************************
480 show a smb message structure
481 ********************************************************************/
482 void show_msg(char *buf)
487 if (DEBUGLEVEL < 5) return;
489 DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
491 (int)CVAL(buf,smb_com),
492 (int)CVAL(buf,smb_rcls),
493 (int)CVAL(buf,smb_reh),
494 (int)SVAL(buf,smb_err),
495 (int)CVAL(buf,smb_flg),
496 (int)SVAL(buf,smb_flg2)));
497 DEBUG(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n",
498 (int)SVAL(buf,smb_tid),
499 (int)SVAL(buf,smb_pid),
500 (int)SVAL(buf,smb_uid),
501 (int)SVAL(buf,smb_mid),
502 (int)CVAL(buf,smb_wct)));
504 for (i=0;i<(int)CVAL(buf,smb_wct);i++)
506 DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i,
507 SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
510 bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
512 DEBUG(5,("smb_bcc=%d\n",bcc));
514 if (DEBUGLEVEL < 10) return;
521 dump_data(10, smb_buf(buf), bcc);
523 /*******************************************************************
524 return the length of an smb packet
525 ********************************************************************/
526 int smb_len(char *buf)
528 return( PVAL(buf,3) | (PVAL(buf,2)<<8) | ((PVAL(buf,1)&1)<<16) );
531 /*******************************************************************
532 set the length of an smb packet
533 ********************************************************************/
534 void _smb_setlen(char *buf,int len)
537 buf[1] = (len&0x10000)>>16;
538 buf[2] = (len&0xFF00)>>8;
542 /*******************************************************************
543 set the length and marker of an smb packet
544 ********************************************************************/
545 void smb_setlen(char *buf,int len)
547 _smb_setlen(buf,len);
555 /*******************************************************************
556 setup the word count and byte count for a smb message
557 ********************************************************************/
558 int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
561 bzero(buf + smb_size,num_words*2 + num_bytes);
562 CVAL(buf,smb_wct) = num_words;
563 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
564 smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
565 return (smb_size + num_words*2 + num_bytes);
568 /*******************************************************************
569 return the number of smb words
570 ********************************************************************/
571 static int smb_numwords(char *buf)
573 return (CVAL(buf,smb_wct));
576 /*******************************************************************
577 return the size of the smb_buf region of a message
578 ********************************************************************/
579 int smb_buflen(char *buf)
581 return(SVAL(buf,smb_vwv0 + smb_numwords(buf)*2));
584 /*******************************************************************
585 return a pointer to the smb_buf data area
586 ********************************************************************/
587 static int smb_buf_ofs(char *buf)
589 return (smb_size + CVAL(buf,smb_wct)*2);
592 /*******************************************************************
593 return a pointer to the smb_buf data area
594 ********************************************************************/
595 char *smb_buf(char *buf)
597 return (buf + smb_buf_ofs(buf));
600 /*******************************************************************
601 return the SMB offset into an SMB buffer
602 ********************************************************************/
603 int smb_offset(char *p,char *buf)
605 return(PTR_DIFF(p,buf+4) + chain_size);
610 /*******************************************************************
611 reduce a file name, removing .. elements.
612 ********************************************************************/
613 void dos_clean_name(char *s)
617 DEBUG(3,("dos_clean_name [%s]\n",s));
619 /* remove any double slashes */
620 string_sub(s, "\\\\", "\\");
622 while ((p = strstr(s,"\\..\\")) != NULL)
629 if ((p=strrchr(s,'\\')) != NULL)
636 trim_string(s,NULL,"\\..");
638 string_sub(s, "\\.\\", "\\");
641 /*******************************************************************
642 reduce a file name, removing .. elements.
643 ********************************************************************/
644 void unix_clean_name(char *s)
648 DEBUG(3,("unix_clean_name [%s]\n",s));
650 /* remove any double slashes */
651 string_sub(s, "//","/");
653 /* Remove leading ./ characters */
654 if(strncmp(s, "./", 2) == 0) {
655 trim_string(s, "./", NULL);
660 while ((p = strstr(s,"/../")) != NULL)
667 if ((p=strrchr(s,'/')) != NULL)
674 trim_string(s,NULL,"/..");
677 /*******************************************************************
678 reduce a file name, removing .. elements and checking that
679 it is below dir in the heirachy. This uses GetWd() and so must be run
680 on the system that has the referenced file system.
682 widelinks are allowed if widelinks is true
683 ********************************************************************/
685 BOOL reduce_name(char *s,char *dir,BOOL widelinks)
695 BOOL relative = (*s != '/');
697 *dir2 = *wd = *base_name = *newname = 0;
702 /* can't have a leading .. */
703 if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
705 DEBUG(3,("Illegal file name? (%s)\n",s));
715 DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
717 /* remove any double slashes */
718 string_sub(s,"//","/");
720 pstrcpy(base_name,s);
721 p = strrchr(base_name,'/');
728 DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
732 if (dos_ChDir(dir) != 0)
734 DEBUG(0,("couldn't chdir to %s\n",dir));
738 if (!dos_GetWd(dir2))
740 DEBUG(0,("couldn't getwd for %s\n",dir));
746 if (p && (p != base_name))
749 if (strcmp(p+1,".")==0)
751 if (strcmp(p+1,"..")==0)
755 if (dos_ChDir(base_name) != 0)
758 DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name));
762 if (!dos_GetWd(newname))
765 DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
769 if (p && (p != base_name))
771 pstrcat(newname,"/");
772 pstrcat(newname,p+1);
776 size_t l = strlen(dir2);
777 if (dir2[l-1] == '/')
780 if (strncmp(newname,dir2,l) != 0)
783 DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,l));
789 if (newname[l] == '/')
790 pstrcpy(s,newname + l + 1);
792 pstrcpy(s,newname+l);
803 DEBUG(3,("reduced to %s\n",s));
808 /****************************************************************************
810 ****************************************************************************/
811 static void expand_one(char *Mask,int len)
814 while ((p1 = strchr(Mask,'*')) != NULL)
816 int lfill = (len+1) - strlen(Mask);
820 memset(tmp+l1,'?',lfill);
821 pstrcpy(tmp + l1 + lfill,Mask + l1 + 1);
826 /****************************************************************************
827 parse out a directory name from a path name. Assumes dos style filenames.
828 ****************************************************************************/
829 static void dirname_dos(char *path,char *buf)
831 split_at_last_component(path, buf, '\\', NULL);
835 /****************************************************************************
836 expand a wildcard expression, replacing *s with ?s
837 ****************************************************************************/
838 void expand_mask(char *Mask,BOOL doext)
845 BOOL absolute = (*Mask == '\\');
847 *mbeg = *mext = *dirpart = *filepart = 0;
849 /* parse the directory and filename */
850 if (strchr(Mask,'\\'))
851 dirname_dos(Mask,dirpart);
853 filename_dos(Mask,filepart);
855 pstrcpy(mbeg,filepart);
856 if ((p1 = strchr(mbeg,'.')) != NULL)
866 if (strlen(mbeg) > 8)
868 pstrcpy(mext,mbeg + 8);
874 pstrcpy(mbeg,"????????");
875 if ((*mext == 0) && doext && !hasdot)
878 if (strequal(mbeg,"*") && *mext==0)
886 pstrcpy(Mask,dirpart);
887 if (*dirpart || absolute) pstrcat(Mask,"\\");
892 DEBUG(6,("Mask expanded to [%s]\n",Mask));
897 /****************************************************************************
899 ****************************************************************************/
900 void make_dir_struct(char *buf,char *mask,char *fname,SMB_OFF_T size,int mode,time_t date)
907 if ((mode & aDIR) != 0)
910 memset(buf+1,' ',11);
911 if ((p = strchr(mask2,'.')) != NULL)
914 memcpy(buf+1,mask2,MIN(strlen(mask2),8));
915 memcpy(buf+9,p+1,MIN(strlen(p+1),3));
919 memcpy(buf+1,mask2,MIN(strlen(mask2),11));
921 bzero(buf+21,DIR_STRUCT_SIZE-21);
923 put_dos_date(buf,22,date);
924 SSVAL(buf,26,size & 0xFFFF);
925 SSVAL(buf,28,(size >> 16)&0xFFFF);
926 StrnCpy(buf+30,fname,12);
929 DEBUG(8,("put name [%s] into dir struct\n",buf+30));
933 /*******************************************************************
934 close the low 3 fd's and open dev/null in their place
935 ********************************************************************/
936 void close_low_fds(void)
940 close(0); close(1); close(2);
941 /* try and use up these file descriptors, so silly
942 library routines writing to stdout etc won't cause havoc */
944 fd = sys_open("/dev/null",O_RDWR,0);
945 if (fd < 0) fd = sys_open("/dev/null",O_WRONLY,0);
947 DEBUG(0,("Can't open /dev/null\n"));
951 DEBUG(0,("Didn't get file descriptor %d\n",i));
957 /****************************************************************************
958 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
962 ****************************************************************************/
963 int set_blocking(int fd, BOOL set)
967 #define FLAG_TO_SET O_NONBLOCK
970 #define FLAG_TO_SET O_NDELAY
972 #define FLAG_TO_SET FNDELAY
976 if((val = fcntl(fd, F_GETFL, 0)) == -1)
978 if(set) /* Turn blocking on - ie. clear nonblock flag */
982 return fcntl( fd, F_SETFL, val);
987 /*******************************************************************
988 find the difference in milliseconds between two struct timeval
990 ********************************************************************/
991 int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew)
993 return((tvalnew->tv_sec - tvalold->tv_sec)*1000 +
994 ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000);
999 /****************************************************************************
1000 transfer some data between two fd's
1001 ****************************************************************************/
1002 SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n,char *header,int headlen,int align)
1004 static char *buf=NULL;
1007 SMB_OFF_T total = 0;
1009 DEBUG(4,("transfer_file n=%.0f (head=%d) called\n",(double)n,headlen));
1012 size = lp_readsize();
1013 size = MAX(size,1024);
1016 while (!buf && size>0) {
1017 buf = (char *)Realloc(buf,size+8);
1018 if (!buf) size /= 2;
1022 DEBUG(0,("Can't allocate transfer buffer!\n"));
1026 abuf = buf + (align%8);
1033 int s = (int)MIN(n,(SMB_OFF_T)size);
1038 if (header && (headlen >= MIN(s,1024))) {
1048 if (header && headlen > 0)
1050 ret = MIN(headlen,size);
1051 memcpy(buf1,header,ret);
1054 if (headlen <= 0) header = NULL;
1058 ret += read(infd,buf1+ret,s-ret);
1062 ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret);
1063 if (ret2 > 0) total += ret2;
1064 /* if we can't write then dump excess data */
1066 transfer_file(infd,-1,n-(ret+headlen),NULL,0,0);
1068 if (ret <= 0 || ret2 != ret)
1077 /****************************************************************************
1078 find a pointer to a netbios name
1079 ****************************************************************************/
1080 static char *name_ptr(char *buf,int ofs)
1082 unsigned char c = *(unsigned char *)(buf+ofs);
1084 if ((c & 0xC0) == 0xC0)
1088 memcpy(p,buf+ofs,2);
1091 DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
1098 /****************************************************************************
1099 extract a netbios name from a buf
1100 ****************************************************************************/
1101 int name_extract(char *buf,int ofs,char *name)
1103 char *p = name_ptr(buf,ofs);
1104 int d = PTR_DIFF(p,buf+ofs);
1106 if (d < -50 || d > 50) return(0);
1107 return(name_interpret(p,name));
1110 /****************************************************************************
1111 return the total storage length of a mangled name
1112 ****************************************************************************/
1113 int name_len(char *s1)
1115 /* NOTE: this argument _must_ be unsigned */
1116 unsigned char *s = (unsigned char *)s1;
1119 /* If the two high bits of the byte are set, return 2. */
1120 if (0xC0 == (*s & 0xC0))
1123 /* Add up the length bytes. */
1124 for (len = 1; (*s); s += (*s) + 1) {
1126 SMB_ASSERT(len < 80);
1133 /*******************************************************************
1134 sleep for a specified number of milliseconds
1135 ********************************************************************/
1139 struct timeval tval,t1,t2;
1146 tval.tv_sec = (t-tdiff)/1000;
1147 tval.tv_usec = 1000*((t-tdiff)%1000);
1151 sys_select(0,&fds,&tval);
1154 tdiff = TvalDiff(&t1,&t2);
1159 /*********************************************************
1160 * Recursive routine that is called by unix_mask_match.
1161 * Does the actual matching. This is the 'original code'
1162 * used by the unix matcher.
1163 *********************************************************/
1164 static BOOL unix_do_match(char *str, char *regexp, int case_sig)
1168 for( p = regexp; *p && *str; ) {
1175 /* Look for a character matching
1176 the one after the '*' */
1179 return True; /* Automatic match */
1181 while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
1183 if(unix_do_match(str,p,case_sig))
1197 if(toupper(*str) != toupper(*p))
1207 if (!*p && str[0] == '.' && str[1] == 0)
1210 if (!*str && *p == '?')
1212 while (*p == '?') p++;
1216 if(!*str && (*p == '*' && p[1] == '\0'))
1222 /*********************************************************
1223 * Routine to match a given string with a regexp - uses
1224 * simplified regexp that takes * and ? only. Case can be
1225 * significant or not.
1226 * This is the 'original code' used by the unix matcher.
1227 *********************************************************/
1229 static BOOL unix_mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
1233 fstring ebase,eext,sbase,sext;
1237 /* Make local copies of str and regexp */
1238 StrnCpy(p1,regexp,sizeof(pstring)-1);
1239 StrnCpy(p2,str,sizeof(pstring)-1);
1241 if (!strchr(p2,'.')) {
1245 /* Remove any *? and ** as they are meaningless */
1246 for(p = p1; *p; p++)
1247 while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
1248 (void)pstrcpy( &p[1], &p[2]);
1250 if (strequal(p1,"*")) return(True);
1252 DEBUG(8,("unix_mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
1258 if ((p=strrchr(p1,'.'))) {
1267 if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
1277 matched = unix_do_match(sbase,ebase,case_sig) &&
1278 (trans2 || unix_do_match(sext,eext,case_sig));
1280 DEBUG(8,("unix_mask_match returning %d\n", matched));
1285 /*********************************************************
1286 * Recursive routine that is called by mask_match.
1287 * Does the actual matching. Returns True if matched,
1288 * False if failed. This is the 'new' NT style matcher.
1289 *********************************************************/
1291 BOOL do_match(char *str, char *regexp, int case_sig)
1295 for( p = regexp; *p && *str; ) {
1302 /* Look for a character matching
1303 the one after the '*' */
1306 return True; /* Automatic match */
1308 while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
1310 /* Now eat all characters that match, as
1311 we want the *last* character to match. */
1312 while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str))))
1314 str--; /* We've eaten the match char after the '*' */
1315 if(do_match(str,p,case_sig)) {
1332 if(toupper(*str) != toupper(*p)) {
1344 if (!*p && str[0] == '.' && str[1] == 0) {
1348 if (!*str && *p == '?') {
1354 if(!*str && (*p == '*' && p[1] == '\0')) {
1362 /*********************************************************
1363 * Routine to match a given string with a regexp - uses
1364 * simplified regexp that takes * and ? only. Case can be
1365 * significant or not.
1366 * The 8.3 handling was rewritten by Ums Harald <Harald.Ums@pro-sieben.de>
1367 * This is the new 'NT style' matcher.
1368 *********************************************************/
1370 BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
1373 pstring t_pattern, t_filename, te_pattern, te_filename;
1374 fstring ebase,eext,sbase,sext;
1376 BOOL matched = False;
1378 /* Make local copies of str and regexp */
1379 pstrcpy(t_pattern,regexp);
1380 pstrcpy(t_filename,str);
1384 * Not sure if this is a good idea. JRA.
1386 if(trans2 && is_8_3(t_pattern,False) && is_8_3(t_filename,False))
1391 if (!strchr(t_filename,'.')) {
1392 pstrcat(t_filename,".");
1396 /* Remove any *? and ** as they are meaningless */
1397 string_sub(t_pattern, "*?", "*");
1398 string_sub(t_pattern, "**", "*");
1400 if (strequal(t_pattern,"*"))
1403 DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", t_filename, t_pattern, case_sig));
1407 * Match each component of the regexp, split up by '.'
1410 char *fp, *rp, *cp2, *cp1;
1411 BOOL last_wcard_was_star = False;
1412 int num_path_components, num_regexp_components;
1414 pstrcpy(te_pattern,t_pattern);
1415 pstrcpy(te_filename,t_filename);
1417 * Remove multiple "*." patterns.
1419 string_sub(te_pattern, "*.*.", "*.");
1420 num_regexp_components = count_chars(te_pattern, '.');
1421 num_path_components = count_chars(te_filename, '.');
1424 * Check for special 'hack' case of "DIR a*z". - needs to match a.b.c...z
1426 if(num_regexp_components == 0)
1427 matched = do_match( te_filename, te_pattern, case_sig);
1429 for( cp1 = te_pattern, cp2 = te_filename; cp1;) {
1430 fp = strchr(cp2, '.');
1433 rp = strchr(cp1, '.');
1437 if(cp1[strlen(cp1)-1] == '*')
1438 last_wcard_was_star = True;
1440 last_wcard_was_star = False;
1442 if(!do_match(cp2, cp1, case_sig))
1445 cp1 = rp ? rp + 1 : NULL;
1446 cp2 = fp ? fp + 1 : "";
1448 if(last_wcard_was_star || ((cp1 != NULL) && (*cp1 == '*'))) {
1449 /* Eat the extra path components. */
1452 for(i = 0; i < num_path_components - num_regexp_components; i++) {
1453 fp = strchr(cp2, '.');
1457 if((cp1 != NULL) && do_match( cp2, cp1, case_sig)) {
1458 cp2 = fp ? fp + 1 : "";
1461 cp2 = fp ? fp + 1 : "";
1463 num_path_components -= i;
1466 if(cp1 == NULL && ((*cp2 == '\0') || last_wcard_was_star))
1471 /* -------------------------------------------------
1472 * Behaviour of Win95
1473 * for 8.3 filenames and 8.3 Wildcards
1474 * -------------------------------------------------
1476 if (strequal (t_filename, ".")) {
1478 * Patterns: *.* *. ?. ? are valid
1481 if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
1482 strequal(t_pattern, "?.") || strequal(t_pattern, "?"))
1484 } else if (strequal (t_filename, "..")) {
1486 * Patterns: *.* *. ?. ? *.? are valid
1489 if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
1490 strequal(t_pattern, "?.") || strequal(t_pattern, "?") ||
1491 strequal(t_pattern, "*.?") || strequal(t_pattern, "?.*"))
1495 if ((p = strrchr (t_pattern, '.'))) {
1497 * Wildcard has a suffix.
1500 fstrcpy (ebase, t_pattern);
1502 fstrcpy (eext, p + 1);
1504 /* pattern ends in DOT: treat as if there is no DOT */
1506 if (strequal (ebase, "*"))
1511 * No suffix for wildcard.
1513 fstrcpy (ebase, t_pattern);
1517 p = strrchr (t_filename, '.');
1518 if (p && (p[1] == 0) ) {
1520 * Filename has an extension of '.' only.
1522 *p = 0; /* nuke dot at end of string */
1523 p = 0; /* and treat it as if there is no extension */
1528 * Filename has an extension.
1531 fstrcpy (sbase, t_filename);
1532 fstrcpy (sext, p + 1);
1534 matched = do_match(sbase, ebase, case_sig)
1535 && do_match(sext, eext, case_sig);
1537 /* pattern has no extension */
1538 /* Really: match complete filename with pattern ??? means exactly 3 chars */
1539 matched = do_match(str, ebase, case_sig);
1543 * Filename has no extension.
1545 fstrcpy (sbase, t_filename);
1548 /* pattern has extension */
1549 matched = do_match(sbase, ebase, case_sig)
1550 && do_match(sext, eext, case_sig);
1552 matched = do_match(sbase, ebase, case_sig);
1553 #ifdef EMULATE_WEIRD_W95_MATCHING
1555 * Even Microsoft has some problems
1556 * Behaviour Win95 -> local disk
1557 * is different from Win95 -> smb drive from Nt 4.0
1558 * This branch would reflect the Win95 local disk behaviour
1561 /* a? matches aa and a in w95 */
1562 fstrcat (sbase, ".");
1563 matched = do_match(sbase, ebase, case_sig);
1571 DEBUG(8,("mask_match returning %d\n", matched));
1576 /****************************************************************************
1577 become a daemon, discarding the controlling terminal
1578 ****************************************************************************/
1579 void become_daemon(void)
1585 /* detach from the terminal */
1588 #elif defined(TIOCNOTTY)
1590 int i = sys_open("/dev/tty", O_RDWR, 0);
1592 ioctl(i, (int) TIOCNOTTY, (char *)0);
1596 #endif /* HAVE_SETSID */
1598 /* Close fd's 0,1,2. Needed if started by rsh */
1603 /****************************************************************************
1604 put up a yes/no prompt
1605 ****************************************************************************/
1611 if (!fgets(ans,sizeof(ans)-1,stdin))
1614 if (*ans == 'y' || *ans == 'Y')
1622 /****************************************************************************
1623 set the length of a file from a filedescriptor.
1624 Returns 0 on success, -1 on failure.
1625 ****************************************************************************/
1626 int set_filelen(int fd, SMB_OFF_T len)
1628 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1629 extend a file with ftruncate. Provide alternate implementation
1632 #ifdef HAVE_FTRUNCATE_EXTEND
1633 return sys_ftruncate(fd, len);
1637 SMB_OFF_T currpos = sys_lseek(fd, (SMB_OFF_T)0, SEEK_CUR);
1641 /* Do an fstat to see if the file is longer than
1642 the requested size (call ftruncate),
1643 or shorter, in which case seek to len - 1 and write 1
1645 if(sys_fstat(fd, &st)<0)
1649 if (S_ISFIFO(st.st_mode)) return 0;
1652 if(st.st_size == len)
1654 if(st.st_size > len)
1655 return sys_ftruncate(fd, len);
1657 if(sys_lseek(fd, len-1, SEEK_SET) != len -1)
1659 if(write(fd, &c, 1)!=1)
1661 /* Seek to where we were */
1662 if(sys_lseek(fd, currpos, SEEK_SET) != currpos)
1670 /****************************************************************************
1671 this is a version of setbuffer() for those machines that only have setvbuf
1672 ****************************************************************************/
1673 void setbuffer(FILE *f,char *buf,int bufsize)
1675 setvbuf(f,buf,_IOFBF,bufsize);
1680 /****************************************************************************
1681 parse out a filename from a path name. Assumes dos style filenames.
1682 ****************************************************************************/
1683 static char *filename_dos(char *path,char *buf)
1685 char *p = strrchr(path,'\\');
1697 /****************************************************************************
1698 expand a pointer to be a particular size
1699 ****************************************************************************/
1700 void *Realloc(void *p,size_t size)
1706 DEBUG(5,("Realloc asked for 0 bytes\n"));
1711 ret = (void *)malloc(size);
1713 ret = (void *)realloc(p,size);
1718 smb_mem_write_info(ret, dbf);
1723 DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",size));
1729 /****************************************************************************
1730 get my own name and IP
1731 ****************************************************************************/
1732 BOOL get_myname(char *my_name,struct in_addr *ip)
1739 /* get my host name */
1740 if (gethostname(hostname, MAXHOSTNAMELEN) == -1)
1742 DEBUG(0,("gethostname failed\n"));
1747 if ((hp = Get_Hostbyname(hostname)) == 0)
1749 DEBUG(0,( "Get_Hostbyname: Unknown host %s\n",hostname));
1755 /* split off any parts after an initial . */
1756 char *p = strchr(hostname,'.');
1759 fstrcpy(my_name,hostname);
1763 putip((char *)ip,(char *)hp->h_addr);
1769 /****************************************************************************
1770 true if two IP addresses are equal
1771 ****************************************************************************/
1772 BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
1775 a1 = ntohl(ip1.s_addr);
1776 a2 = ntohl(ip2.s_addr);
1781 /****************************************************************************
1782 interpret a protocol description string, with a default
1783 ****************************************************************************/
1784 int interpret_protocol(char *str,int def)
1786 if (strequal(str,"NT1"))
1787 return(PROTOCOL_NT1);
1788 if (strequal(str,"LANMAN2"))
1789 return(PROTOCOL_LANMAN2);
1790 if (strequal(str,"LANMAN1"))
1791 return(PROTOCOL_LANMAN1);
1792 if (strequal(str,"CORE"))
1793 return(PROTOCOL_CORE);
1794 if (strequal(str,"COREPLUS"))
1795 return(PROTOCOL_COREPLUS);
1796 if (strequal(str,"CORE+"))
1797 return(PROTOCOL_COREPLUS);
1799 DEBUG(0,("Unrecognised protocol level %s\n",str));
1805 /****************************************************************************
1806 interpret an internet address or name into an IP address in 4 byte form
1807 ****************************************************************************/
1808 uint32 interpret_addr(char *str)
1813 BOOL pure_address = True;
1815 if (strcmp(str,"0.0.0.0") == 0) return(0);
1816 if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
1818 for (i=0; pure_address && str[i]; i++)
1819 if (!(isdigit((int)str[i]) || str[i] == '.'))
1820 pure_address = False;
1822 /* if it's in the form of an IP address then get the lib to interpret it */
1824 res = inet_addr(str);
1826 /* otherwise assume it's a network name of some sort and use
1828 if ((hp = Get_Hostbyname(str)) == 0) {
1829 DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
1832 if(hp->h_addr == NULL) {
1833 DEBUG(3,("Get_Hostbyname: host address is invalid for host %s\n",str));
1836 putip((char *)&res,(char *)hp->h_addr);
1839 if (res == (uint32)-1) return(0);
1844 /*******************************************************************
1845 a convenient addition to interpret_addr()
1846 ******************************************************************/
1847 struct in_addr *interpret_addr2(char *str)
1849 static struct in_addr ret;
1850 uint32 a = interpret_addr(str);
1855 /*******************************************************************
1856 check if an IP is the 0.0.0.0
1857 ******************************************************************/
1858 BOOL zero_ip(struct in_addr ip)
1861 putip((char *)&a,(char *)&ip);
1866 /*******************************************************************
1867 matchname - determine if host name matches IP address
1868 ******************************************************************/
1869 BOOL matchname(char *remotehost,struct in_addr addr)
1874 if ((hp = Get_Hostbyname(remotehost)) == 0) {
1875 DEBUG(0,("Get_Hostbyname(%s): lookup failure", remotehost));
1880 * Make sure that gethostbyname() returns the "correct" host name.
1881 * Unfortunately, gethostbyname("localhost") sometimes yields
1882 * "localhost.domain". Since the latter host name comes from the
1883 * local DNS, we just have to trust it (all bets are off if the local
1884 * DNS is perverted). We always check the address list, though.
1887 if (strcasecmp(remotehost, hp->h_name)
1888 && strcasecmp(remotehost, "localhost")) {
1889 DEBUG(0,("host name/name mismatch: %s != %s",
1890 remotehost, hp->h_name));
1894 /* Look up the host address in the address list we just got. */
1895 for (i = 0; hp->h_addr_list[i]; i++) {
1896 if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
1901 * The host name does not map to the original host address. Perhaps
1902 * someone has compromised a name server. More likely someone botched
1903 * it, but that could be dangerous, too.
1906 DEBUG(0,("host name/address mismatch: %s != %s",
1907 inet_ntoa(addr), hp->h_name));
1912 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1913 /******************************************************************
1914 Remove any mount options such as -rsize=2048,wsize=2048 etc.
1915 Based on a fix from <Thomas.Hepper@icem.de>.
1916 *******************************************************************/
1918 static void strip_mount_options( pstring *str)
1923 while(*p && !isspace(*p))
1925 while(*p && isspace(*p))
1930 pstrcpy(tmp_str, p);
1931 pstrcpy(*str, tmp_str);
1936 /*******************************************************************
1937 Patch from jkf@soton.ac.uk
1938 Split Luke's automount_server into YP lookup and string splitter
1939 so can easily implement automount_path().
1940 As we may end up doing both, cache the last YP result.
1941 *******************************************************************/
1943 #ifdef WITH_NISPLUS_HOME
1944 static char *automount_lookup(char *user_name)
1946 static fstring last_key = "";
1947 static pstring last_value = "";
1949 char *nis_map = (char *)lp_nis_home_map_name();
1951 char nis_domain[NIS_MAXNAMELEN + 1];
1952 char buffer[NIS_MAXATTRVAL + 1];
1957 strncpy(nis_domain, (char *)nis_local_directory(), NIS_MAXNAMELEN);
1958 nis_domain[NIS_MAXNAMELEN] = '\0';
1960 DEBUG(5, ("NIS+ Domain: %s\n", nis_domain));
1962 if (strcmp(user_name, last_key))
1964 slprintf(buffer, sizeof(buffer)-1, "[%s=%s]%s.%s", "key", user_name, nis_map, nis_domain);
1965 DEBUG(5, ("NIS+ querystring: %s\n", buffer));
1967 if (result = nis_list(buffer, RETURN_RESULT, NULL, NULL))
1969 if (result->status != NIS_SUCCESS)
1971 DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
1972 fstrcpy(last_key, ""); pstrcpy(last_value, "");
1976 object = result->objects.objects_val;
1977 if (object->zo_data.zo_type == ENTRY_OBJ)
1979 entry = &object->zo_data.objdata_u.en_data;
1980 DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
1981 DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
1983 pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
1984 string_sub(last_value, "&", user_name);
1985 fstrcpy(last_key, user_name);
1989 nis_freeresult(result);
1992 strip_mount_options(&last_value);
1994 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
1997 #else /* WITH_NISPLUS_HOME */
1998 static char *automount_lookup(char *user_name)
2000 static fstring last_key = "";
2001 static pstring last_value = "";
2003 int nis_error; /* returned by yp all functions */
2004 char *nis_result; /* yp_match inits this */
2005 int nis_result_len; /* and set this */
2006 char *nis_domain; /* yp_get_default_domain inits this */
2007 char *nis_map = (char *)lp_nis_home_map_name();
2009 if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
2011 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
2015 DEBUG(5, ("NIS Domain: %s\n", nis_domain));
2017 if (!strcmp(user_name, last_key))
2019 nis_result = last_value;
2020 nis_result_len = strlen(last_value);
2025 if ((nis_error = yp_match(nis_domain, nis_map,
2026 user_name, strlen(user_name),
2027 &nis_result, &nis_result_len)) != 0)
2029 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
2030 yperr_string(nis_error), user_name, nis_map));
2032 if (!nis_error && nis_result_len >= sizeof(pstring))
2034 nis_result_len = sizeof(pstring)-1;
2036 fstrcpy(last_key, user_name);
2037 strncpy(last_value, nis_result, nis_result_len);
2038 last_value[nis_result_len] = '\0';
2041 strip_mount_options(&last_value);
2043 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
2046 #endif /* WITH_NISPLUS_HOME */
2049 /*******************************************************************
2050 Patch from jkf@soton.ac.uk
2051 This is Luke's original function with the NIS lookup code
2052 moved out to a separate function.
2053 *******************************************************************/
2054 static char *automount_server(char *user_name)
2056 static pstring server_name;
2058 /* use the local machine name as the default */
2059 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
2060 pstrcpy(server_name, local_machine);
2062 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2064 if (lp_nis_home_map())
2066 int home_server_len;
2067 char *automount_value = automount_lookup(user_name);
2068 home_server_len = strcspn(automount_value,":");
2069 DEBUG(5, ("NIS lookup succeeded. Home server length: %d\n",home_server_len));
2070 if (home_server_len > sizeof(pstring))
2072 home_server_len = sizeof(pstring);
2074 strncpy(server_name, automount_value, home_server_len);
2075 server_name[home_server_len] = '\0';
2079 DEBUG(4,("Home server: %s\n", server_name));
2084 /*******************************************************************
2085 Patch from jkf@soton.ac.uk
2086 Added this to implement %p (NIS auto-map version of %H)
2087 *******************************************************************/
2088 static char *automount_path(char *user_name)
2090 static pstring server_path;
2092 /* use the passwd entry as the default */
2093 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
2094 /* pstrcpy() copes with get_home_dir() returning NULL */
2095 pstrcpy(server_path, get_home_dir(user_name));
2097 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2099 if (lp_nis_home_map())
2101 char *home_path_start;
2102 char *automount_value = automount_lookup(user_name);
2103 home_path_start = strchr(automount_value,':');
2104 if (home_path_start != NULL)
2106 DEBUG(5, ("NIS lookup succeeded. Home path is: %s\n",
2107 home_path_start?(home_path_start+1):""));
2108 pstrcpy(server_path, home_path_start+1);
2113 DEBUG(4,("Home server path: %s\n", server_path));
2119 /*******************************************************************
2120 sub strings with useful parameters
2121 Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
2122 Paul Rippin <pr3245@nopc.eurostat.cec.be>
2123 ********************************************************************/
2124 void standard_sub_basic(char *str)
2128 const struct passwd *pass;
2129 char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user;
2131 for (s = str ; s && *s && (p = strchr(s,'%')); s = p )
2137 if ((pass = Get_Pwnam(username,False))!=NULL)
2139 string_sub(p,"%G",gidtoname(pass->pw_gid));
2147 case 'N' : string_sub(p,"%N", automount_server(username)); break;
2148 case 'I' : string_sub(p,"%I", client_addr(Client)); break;
2149 case 'L' : string_sub(p,"%L", local_machine); break;
2150 case 'M' : string_sub(p,"%M", client_name(Client)); break;
2151 case 'R' : string_sub(p,"%R", remote_proto); break;
2152 case 'T' : string_sub(p,"%T", timestring()); break;
2153 case 'U' : string_sub(p,"%U", username); break;
2154 case 'a' : string_sub(p,"%a", remote_arch); break;
2157 slprintf(pidstr,sizeof(pidstr) - 1, "%d",(int)getpid());
2158 string_sub(p,"%d", pidstr);
2161 case 'h' : string_sub(p,"%h", myhostname); break;
2162 case 'm' : string_sub(p,"%m", remote_machine); break;
2163 case 'v' : string_sub(p,"%v", VERSION); break;
2164 case '$' : /* Expand environment variables */
2166 /* Contributed by Branko Cibej <branko.cibej@hermes.si> */
2177 if ((q = strchr(p,')')) == NULL)
2179 DEBUG(0,("standard_sub_basic: Unterminated environment \
2180 variable [%s]\n", p));
2186 copylen = MIN((q-r),(sizeof(envname)-1));
2187 strncpy(envname,r,copylen);
2188 envname[copylen] = '\0';
2190 if ((envval = getenv(envname)) == NULL)
2192 DEBUG(0,("standard_sub_basic: Environment variable [%s] not set\n",
2198 copylen = MIN((q+1-p),(sizeof(envname)-1));
2199 strncpy(envname,p,copylen);
2200 envname[copylen] = '\0';
2201 string_sub(p,envname,envval);
2204 case '\0': p++; break; /* don't run off end if last character is % */
2205 default : p+=2; break;
2212 /****************************************************************************
2213 do some standard substitutions in a string
2214 ****************************************************************************/
2215 void standard_sub(connection_struct *conn,char *str)
2219 for (s=str; (p=strchr(s, '%'));s=p)
2224 if ((home = get_home_dir(conn->user)) != NULL) {
2225 string_sub(p,"%H",home);
2231 /* Patch from jkf@soton.ac.uk Left the %N (NIS
2232 * server name) in standard_sub_basic as it is
2233 * a feature for logon servers, hence uses the
2234 * username. The %p (NIS server path) code is
2235 * here as it is used instead of the default
2236 * "path =" string in [homes] and so needs the
2237 * service name, not the username. */
2238 case 'p': string_sub(p,"%p", automount_path(lp_servicename(SNUM(conn)))); break;
2239 case 'P': string_sub(p,"%P",conn->connectpath); break;
2240 case 'S': string_sub(p,"%S", lp_servicename(SNUM(conn))); break;
2241 case 'g': string_sub(p,"%g", gidtoname(conn->gid)); break;
2242 case 'u': string_sub(p,"%u", conn->user); break;
2244 case '\0': p++; break; /* don't run off the end of the string */
2245 default : p+=2; break;
2249 standard_sub_basic(str);
2254 /*******************************************************************
2255 are two IPs on the same subnet?
2256 ********************************************************************/
2257 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
2259 uint32 net1,net2,nmask;
2261 nmask = ntohl(mask.s_addr);
2262 net1 = ntohl(ip1.s_addr);
2263 net2 = ntohl(ip2.s_addr);
2265 return((net1 & nmask) == (net2 & nmask));
2269 /****************************************************************************
2270 a wrapper for gethostbyname() that tries with all lower and all upper case
2271 if the initial name fails
2272 ****************************************************************************/
2273 struct hostent *Get_Hostbyname(const char *name)
2275 char *name2 = strdup(name);
2276 struct hostent *ret;
2280 DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
2286 * This next test is redundent and causes some systems (with
2287 * broken isalnum() calls) problems.
2292 if (!isalnum(*name2))
2299 ret = sys_gethostbyname(name2);
2306 /* try with all lowercase */
2308 ret = sys_gethostbyname(name2);
2315 /* try with all uppercase */
2317 ret = sys_gethostbyname(name2);
2324 /* nothing works :-( */
2330 /****************************************************************************
2331 check if a process exists. Does this work on all unixes?
2332 ****************************************************************************/
2334 BOOL process_exists(int pid)
2336 return(kill(pid,0) == 0 || errno != ESRCH);
2340 /****************************************************************************
2341 Setup the groups a user belongs to.
2342 ****************************************************************************/
2343 int get_unixgroups(char *user, uid_t uid, gid_t gid, int *p_ngroups, gid_t **p_groups)
2347 gid_t *groups = NULL;
2349 if (-1 == initgroups(user,gid))
2353 DEBUG(0,("Unable to initgroups!\n"));
2354 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
2356 DEBUG(0,("This is probably a problem with the account %s\n", user));
2362 ngroups = sys_getgroups(0,&grp);
2368 if((groups = (gid_t *)malloc(sizeof(gid_t)*ngroups)) == NULL)
2370 DEBUG(0,("get_unixgroups malloc fail !\n"));
2374 ngroups = sys_getgroups(ngroups,groups);
2376 (*p_ngroups) = ngroups;
2377 (*p_groups) = groups;
2379 DEBUG( 3, ( "%s is in %d groups: ", user, ngroups ) );
2380 for (i = 0; i < ngroups; i++ )
2382 DEBUG( 3, ( "%s%d", (i ? ", " : ""), (int)groups[i] ) );
2384 DEBUG( 3, ( "\n" ) );
2389 /****************************************************************************
2390 get all unix groups. copying group members is hideous on memory, so it's
2391 NOT done here. however, names of unix groups _are_ string-allocated so
2392 free_unix_grps() must be called.
2393 ****************************************************************************/
2394 BOOL get_unix_grps(int *p_ngroups, struct group **p_groups)
2398 DEBUG(10,("get_unix_grps\n"));
2400 if (p_ngroups == NULL || p_groups == NULL)
2410 while ((grp = getgrent()) != NULL)
2412 struct group *copy_grp;
2414 (*p_groups) = (struct group*)Realloc((*p_groups), (size_t)((*p_ngroups)+1) * sizeof(struct group));
2415 if ((*p_groups) == NULL)
2423 copy_grp = &(*p_groups)[*p_ngroups];
2424 memcpy(copy_grp, grp, sizeof(*grp));
2425 copy_grp->gr_name = strdup(copy_grp->gr_name);
2426 copy_grp->gr_mem = NULL;
2433 DEBUG(10,("get_unix_grps: %d groups\n", (*p_ngroups)));
2437 /****************************************************************************
2438 free memory associated with unix groups.
2439 ****************************************************************************/
2440 void free_unix_grps(int ngroups, struct group *p_groups)
2444 if (p_groups == NULL)
2449 for (i = 0; i < ngroups; i++)
2451 if (p_groups[i].gr_name != NULL)
2453 free(p_groups[i].gr_name);
2460 /*******************************************************************
2461 turn a gid into a group name
2462 ********************************************************************/
2464 char *gidtoname(gid_t gid)
2466 static char name[40];
2467 struct group *grp = getgrgid(gid);
2468 if (grp) return(grp->gr_name);
2469 slprintf(name,sizeof(name) - 1, "%d",(int)gid);
2473 /*******************************************************************
2474 turn a group name into a gid
2475 ********************************************************************/
2477 BOOL nametogid(const char *name, gid_t *gid)
2479 struct group *grp = getgrnam(name);
2485 else if (isdigit(name[0]))
2487 *gid = (gid_t)get_number(name);
2496 /*******************************************************************
2497 turn a user name into a uid
2498 ********************************************************************/
2499 BOOL nametouid(const char *name, uid_t *uid)
2501 const struct passwd *pass = Get_Pwnam(name, False);
2504 *uid = pass->pw_uid;
2507 else if (isdigit(name[0]))
2509 *uid = (uid_t)get_number(name);
2518 /*******************************************************************
2519 something really nasty happened - panic!
2520 ********************************************************************/
2521 void smb_panic(char *why)
2523 char *cmd = lp_panic_action();
2527 DEBUG(0,("PANIC: %s\n", why));
2533 /*******************************************************************
2534 a readdir wrapper which just returns the file name
2535 ********************************************************************/
2536 char *readdirname(DIR *p)
2541 if (!p) return(NULL);
2543 ptr = (struct dirent *)readdir(p);
2544 if (!ptr) return(NULL);
2546 dname = ptr->d_name;
2549 if (telldir(p) < 0) return(NULL);
2552 #ifdef HAVE_BROKEN_READDIR
2553 /* using /usr/ucb/cc is BAD */
2559 memcpy(buf, dname, NAMLEN(ptr)+1);
2566 /*******************************************************************
2567 Utility function used to decide if the last component
2568 of a path matches a (possibly wildcarded) entry in a namelist.
2569 ********************************************************************/
2571 BOOL is_in_path(char *name, name_compare_entry *namelist)
2573 pstring last_component;
2576 DEBUG(8, ("is_in_path: %s\n", name));
2578 /* if we have no list it's obviously not in the path */
2579 if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL)))
2581 DEBUG(8,("is_in_path: no name list.\n"));
2585 /* Get the last component of the unix name. */
2586 p = strrchr(name, '/');
2587 strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
2588 last_component[sizeof(last_component)-1] = '\0';
2590 for(; namelist->name != NULL; namelist++)
2592 if(namelist->is_wild)
2595 * Look for a wildcard match. Use the old
2596 * 'unix style' mask match, rather than the
2599 if (unix_mask_match(last_component, namelist->name, case_sensitive, False))
2601 DEBUG(8,("is_in_path: mask match succeeded\n"));
2607 if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
2608 (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0)))
2610 DEBUG(8,("is_in_path: match succeeded\n"));
2615 DEBUG(8,("is_in_path: match not found\n"));
2620 /*******************************************************************
2621 Strip a '/' separated list into an array of
2622 name_compare_enties structures suitable for
2623 passing to is_in_path(). We do this for
2624 speed so we can pre-parse all the names in the list
2625 and don't do it for each call to is_in_path().
2626 namelist is modified here and is assumed to be
2627 a copy owned by the caller.
2628 We also check if the entry contains a wildcard to
2629 remove a potentially expensive call to mask_match
2631 ********************************************************************/
2633 void set_namearray(name_compare_entry **ppname_array, char *namelist)
2636 char *nameptr = namelist;
2637 int num_entries = 0;
2640 (*ppname_array) = NULL;
2642 if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0')))
2645 /* We need to make two passes over the string. The
2646 first to count the number of elements, the second
2651 if ( *nameptr == '/' )
2653 /* cope with multiple (useless) /s) */
2657 /* find the next / */
2658 name_end = strchr(nameptr, '/');
2660 /* oops - the last check for a / didn't find one. */
2661 if (name_end == NULL)
2664 /* next segment please */
2665 nameptr = name_end + 1;
2669 if(num_entries == 0)
2672 if(( (*ppname_array) = (name_compare_entry *)malloc(
2673 (num_entries + 1) * sizeof(name_compare_entry))) == NULL)
2675 DEBUG(0,("set_namearray: malloc fail\n"));
2679 /* Now copy out the names */
2684 if ( *nameptr == '/' )
2686 /* cope with multiple (useless) /s) */
2690 /* find the next / */
2691 if ((name_end = strchr(nameptr, '/')) != NULL)
2696 /* oops - the last check for a / didn't find one. */
2697 if(name_end == NULL)
2700 (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
2701 (strchr( nameptr, '*')!=NULL));
2702 if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
2704 DEBUG(0,("set_namearray: malloc fail (1)\n"));
2708 /* next segment please */
2709 nameptr = name_end + 1;
2713 (*ppname_array)[i].name = NULL;
2718 /****************************************************************************
2719 routine to free a namearray.
2720 ****************************************************************************/
2722 void free_namearray(name_compare_entry *name_array)
2727 if(name_array->name != NULL)
2728 free(name_array->name);
2730 free((char *)name_array);
2733 /****************************************************************************
2734 routine to do file locking
2735 ****************************************************************************/
2736 BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
2739 SMB_STRUCT_FLOCK lock;
2742 if(lp_ole_locking_compat()) {
2743 SMB_OFF_T mask2= ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4);
2744 SMB_OFF_T mask = (mask2<<2);
2746 /* make sure the count is reasonable, we might kill the lockd otherwise */
2749 /* the offset is often strange - remove 2 of its bits if either of
2750 the top two bits are set. Shift the top ones by two bits. This
2751 still allows OLE2 apps to operate, but should stop lockd from
2753 if ((offset & mask) != 0)
2754 offset = (offset & ~mask) | (((offset & mask) >> 2) & mask2);
2756 SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
2757 SMB_OFF_T mask = (mask2<<1);
2758 SMB_OFF_T neg_mask = ~mask;
2760 /* interpret negative counts as large numbers */
2764 /* no negative offsets */
2768 /* count + offset must be in range */
2769 while ((offset < 0 || (offset + count < 0)) && mask)
2772 mask = ((mask >> 1) & neg_mask);
2776 DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
2779 lock.l_whence = SEEK_SET;
2780 lock.l_start = offset;
2786 ret = fcntl(fd,op,&lock);
2791 dbgtext("fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count);
2792 dbgtext("a 'file too large' error. This can happen when using 64 bit lock offsets\n");
2793 dbgtext("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n");
2795 /* 32 bit NFS file system, retry with smaller offset */
2797 lock.l_len = count & 0xffffffff;
2798 ret = fcntl(fd,op,&lock);
2802 DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
2805 if (op == SMB_F_GETLK)
2808 (lock.l_type != F_UNLCK) &&
2809 (lock.l_pid != 0) &&
2810 (lock.l_pid != getpid()))
2812 DEBUG(3,("fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
2816 /* it must be not locked or locked by me */
2820 /* a lock set or unset */
2823 DEBUG(3,("lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
2824 (double)offset,(double)count,op,type,strerror(errno)));
2826 /* perhaps it doesn't support this sort of locking?? */
2827 if (errno == EINVAL)
2829 DEBUG(3,("locking not supported? returning True\n"));
2836 /* everything went OK */
2837 DEBUG(8,("Lock call successful\n"));
2845 /*******************************************************************
2846 is the name specified one of my netbios names
2847 returns true is it is equal, false otherwise
2848 ********************************************************************/
2849 BOOL is_myname(char *s)
2854 for (n=0; my_netbios_names[n]; n++) {
2855 if (strequal(my_netbios_names[n], s))
2858 DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
2862 /*******************************************************************
2863 set the horrid remote_arch string based on an enum.
2864 ********************************************************************/
2865 void set_remote_arch(enum remote_arch_types type)
2871 fstrcpy(remote_arch, "WfWg");
2874 fstrcpy(remote_arch, "OS2");
2877 fstrcpy(remote_arch, "Win95");
2880 fstrcpy(remote_arch, "WinNT");
2883 fstrcpy(remote_arch,"Samba");
2886 ra_type = RA_UNKNOWN;
2887 fstrcpy(remote_arch, "UNKNOWN");
2892 /*******************************************************************
2893 Get the remote_arch type.
2894 ********************************************************************/
2895 enum remote_arch_types get_remote_arch(void)
2901 /*******************************************************************
2902 align a pointer to a multiple of 4 bytes.
2903 ********************************************************************/
2904 char *align4(char *q, char *base)
2906 int mod = PTR_DIFF(q, base) & 3;
2913 /*******************************************************************
2914 align a pointer to a multiple of 2 bytes
2915 ********************************************************************/
2916 char *align2(char *q, char *base)
2918 if (PTR_DIFF(q, base) & 1)
2925 void out_ascii(FILE *f, const unsigned char *buf,int len)
2930 fprintf(f, "%c", isprint(buf[i])?buf[i]:'.');
2934 void out_struct(FILE *f, const char *buf1,int len, int per_line)
2936 const unsigned char *buf = (const unsigned char *)buf1;
2944 fprintf(f, "{\n\t");
2947 fprintf(f, "0x%02X",(int)buf[i]);
2953 if (i%per_line == 0 && i != len)
2958 fprintf(f, "\n};\n");
2961 void out_data(FILE *f, const char *buf1,int len, int per_line)
2963 const unsigned char *buf = (const unsigned char *)buf1;
2970 fprintf(f, "[%03X] ",i);
2973 fprintf(f, "%02X ",(int)buf[i]);
2975 if (i%(per_line/2) == 0) fprintf(f, " ");
2976 if (i%per_line == 0)
2978 out_ascii(f,&buf[i-per_line ],per_line/2); fprintf(f, " ");
2979 out_ascii(f,&buf[i-per_line/2],per_line/2); fprintf(f, "\n");
2980 if (i<len) fprintf(f, "[%03X] ",i);
2983 if ((i%per_line) != 0)
2987 n = per_line - (i%per_line);
2989 if (n>(per_line/2)) fprintf(f, " ");
2994 n = MIN(per_line/2,i%per_line);
2995 out_ascii(f,&buf[i-(i%per_line)],n); fprintf(f, " ");
2996 n = (i%per_line) - n;
2997 if (n>0) out_ascii(f,&buf[i-n],n);
3002 void print_asc(int level, unsigned char const *buf,int len)
3007 DEBUGADD(level,("%c", isprint(buf[i])?buf[i]:'.'));
3011 void dump_data(int level, const char *buf1, int len)
3013 unsigned char const *buf = (unsigned char const *)buf1;
3017 DEBUG(level,("[%03X] ",i));
3020 DEBUGADD(level,("%02X ",(int)buf[i]));
3022 if (i%8 == 0) DEBUGADD(level,(" "));
3025 print_asc(level,&buf[i-16],8); DEBUGADD(level,(" "));
3026 print_asc(level,&buf[i-8],8); DEBUGADD(level,("\n"));
3027 if (i<len) DEBUGADD(level,("[%03X] ",i));
3031 if (i%16 != 0) /* finish off a non-16-char-length row */
3036 DEBUGADD(level,(" "));
3037 if (n>8) DEBUGADD(level,(" "));
3038 while (n--) DEBUGADD(level,(" "));
3041 print_asc(level,&buf[i-(i%16)],n); DEBUGADD(level,(" "));
3043 if (n>0) print_asc(level,&buf[i-n],n);
3044 DEBUGADD(level,("\n"));
3048 char *tab_depth(int depth)
3050 static pstring spaces;
3051 memset(spaces, ' ', depth * 4);
3052 spaces[depth * 4] = 0;
3056 /*****************************************************************************
3057 * Provide a checksum on a string
3059 * Input: s - the null-terminated character string for which the checksum
3060 * will be calculated.
3062 * Output: The checksum value calculated for s.
3064 * ****************************************************************************
3066 int str_checksum(const char *s)
3074 res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
3079 } /* str_checksum */
3083 /*****************************************************************
3084 zero a memory area then free it. Used to catch bugs faster
3085 *****************************************************************/
3086 void zero_free(void *p, size_t size)
3093 /*****************************************************************
3094 set our open file limit to a requested max and return the limit
3095 *****************************************************************/
3096 int set_maxfiles(int requested_max)
3098 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
3100 getrlimit(RLIMIT_NOFILE, &rlp);
3101 /* Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
3102 * account for the extra fd we need
3103 * as well as the log files and standard
3105 rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
3106 setrlimit(RLIMIT_NOFILE, &rlp);
3107 getrlimit(RLIMIT_NOFILE, &rlp);
3108 return rlp.rlim_cur;
3111 * No way to know - just guess...
3113 return requested_max;
3118 /*****************************************************************
3119 splits out the last subkey of a key
3120 *****************************************************************/
3121 void reg_get_subkey(char *full_keyname, char *key_name, char *subkey_name)
3123 split_at_last_component(full_keyname, key_name, '\\', subkey_name);
3126 /*****************************************************************
3127 splits out the start of the key (HKLM or HKU) and the rest of the key
3128 *****************************************************************/
3129 BOOL reg_split_key(const char *full_keyname, uint32 *reg_type, char *key_name)
3133 if (!next_token((char**)(&full_keyname), tmp, "\\", sizeof(tmp)))
3140 DEBUG(10, ("reg_split_key: hive %s\n", tmp));
3142 if (strequal(tmp, "HKCR") || strequal(tmp, "HKEY_CLASSES_ROOT"))
3144 (*reg_type) = HKEY_CLASSES_ROOT;
3146 else if (strequal(tmp, "HKCU") || strequal(tmp, "HKEY_CURRENT_USER"))
3148 (*reg_type) = HKEY_CURRENT_USER;
3150 else if (strequal(tmp, "HKLM") || strequal(tmp, "HKEY_LOCAL_MACHINE"))
3152 (*reg_type) = HKEY_LOCAL_MACHINE;
3154 else if (strequal(tmp, "HKU") || strequal(tmp, "HKEY_USERS"))
3156 (*reg_type) = HKEY_USERS;
3160 DEBUG(10,("reg_split_key: unrecognised hive key %s\n", tmp));
3164 if (next_token(NULL, tmp, "\n\r", sizeof(tmp)))
3166 fstrcpy(key_name, tmp);
3173 DEBUG(10, ("reg_split_key: name %s\n", key_name));
3178 /****************************************************************************
3179 become the specified uid - permanently !
3180 ****************************************************************************/
3181 BOOL become_user_permanently(uid_t uid, gid_t gid)
3183 /* now completely lose our privilages. This is a fairly paranoid
3184 way of doing it, but it does work on all systems that I know of */
3186 #ifdef HAVE_SETRESUID
3188 * Firstly ensure all our uids are set to root.
3194 * Now ensure we change all our gids.
3196 setresgid(gid,gid,gid);
3199 * Now ensure all the uids are the user.
3201 setresuid(uid,uid,uid);
3204 * Firstly ensure all our uids are set to root.
3210 * Now ensure we change all our gids.
3216 * Now ensure all the uids are the user.
3222 if (getuid() != uid || geteuid() != uid ||
3223 getgid() != gid || getegid() != gid) {
3224 /* We failed to lose our privilages. */
3231 BOOL resolve_srv_name(const char* srv_name, fstring dest_host,
3234 DEBUG(10,("resolve_srv_name: %s\n", srv_name));
3236 if (srv_name == NULL || strequal("\\\\.", srv_name))
3238 fstrcpy(dest_host, global_myname);
3239 ip = interpret_addr2("127.0.0.1");
3243 if (!strnequal("\\\\", srv_name, 2))
3248 fstrcpy(dest_host, &srv_name[2]);
3249 return resolve_name(dest_host, ip, 0x20);