merge from HEAD - enable dynamic RPC modules
[jra/samba/.git] / source3 / lib / util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 2001-2002
6    Copyright (C) Simo Sorce 2001
7    Copyright (C) Anthony Liguori 2003
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
27 #ifdef WITH_NISPLUS_HOME
28 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
29 /*
30  * The following lines are needed due to buggy include files
31  * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
32  * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
33  * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
34  * an enum in /usr/include/rpcsvc/nis.h.
35  */
36
37 #if defined(GROUP)
38 #undef GROUP
39 #endif
40
41 #if defined(GROUP_OBJ)
42 #undef GROUP_OBJ
43 #endif
44
45 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
46
47 #include <rpcsvc/nis.h>
48
49 #else /* !WITH_NISPLUS_HOME */
50
51 #include "rpcsvc/ypclnt.h"
52
53 #endif /* WITH_NISPLUS_HOME */
54 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
55
56 int Protocol = PROTOCOL_COREPLUS;
57
58 /* a default finfo structure to ensure all fields are sensible */
59 file_info def_finfo = {-1,0,0,0,0,0,0,"",""};
60
61 /* this is used by the chaining code */
62 int chain_size = 0;
63
64 int trans_num = 0;
65
66 /*
67    case handling on filenames 
68 */
69 int case_default = CASE_LOWER;
70
71 /* the following control case operations - they are put here so the
72    client can link easily */
73 BOOL case_sensitive;
74 BOOL case_preserve;
75 BOOL use_mangled_map = False;
76 BOOL short_case_preserve;
77 BOOL case_mangle;
78
79 static enum remote_arch_types ra_type = RA_UNKNOWN;
80 pstring user_socket_options=DEFAULT_SOCKET_OPTIONS;   
81
82 /***********************************************************************
83  Definitions for all names.
84 ***********************************************************************/
85
86 static char *smb_myname;
87 static char *smb_myworkgroup;
88 static char *smb_scope;
89 static int smb_num_netbios_names;
90 static char **smb_my_netbios_names;
91
92 /***********************************************************************
93  Allocate and set myname. Ensure upper case.
94 ***********************************************************************/
95
96 BOOL set_global_myname(const char *myname)
97 {
98         SAFE_FREE(smb_myname);
99         smb_myname = strdup(myname);
100         if (!smb_myname)
101                 return False;
102         strupper(smb_myname);
103         return True;
104 }
105
106 const char *global_myname(void)
107 {
108         return smb_myname;
109 }
110
111 /***********************************************************************
112  Allocate and set myworkgroup. Ensure upper case.
113 ***********************************************************************/
114
115 BOOL set_global_myworkgroup(const char *myworkgroup)
116 {
117         SAFE_FREE(smb_myworkgroup);
118         smb_myworkgroup = strdup(myworkgroup);
119         if (!smb_myworkgroup)
120                 return False;
121         strupper(smb_myworkgroup);
122         return True;
123 }
124
125 const char *lp_workgroup(void)
126 {
127         return smb_myworkgroup;
128 }
129
130 /***********************************************************************
131  Allocate and set scope. Ensure upper case.
132 ***********************************************************************/
133
134 BOOL set_global_scope(const char *scope)
135 {
136         SAFE_FREE(smb_scope);
137         smb_scope = strdup(scope);
138         if (!smb_scope)
139                 return False;
140         strupper(smb_scope);
141         return True;
142 }
143
144 /*********************************************************************
145  Ensure scope is never null string.
146 *********************************************************************/
147
148 const char *global_scope(void)
149 {
150         if (!smb_scope)
151                 set_global_scope("");
152         return smb_scope;
153 }
154
155 static void free_netbios_names_array(void)
156 {
157         int i;
158
159         for (i = 0; i < smb_num_netbios_names; i++)
160                 SAFE_FREE(smb_my_netbios_names[i]);
161
162         SAFE_FREE(smb_my_netbios_names);
163         smb_num_netbios_names = 0;
164 }
165
166 static BOOL allocate_my_netbios_names_array(size_t number)
167 {
168         free_netbios_names_array();
169
170         smb_num_netbios_names = number + 1;
171         smb_my_netbios_names = (char **)malloc( sizeof(char *) * smb_num_netbios_names );
172
173         if (!smb_my_netbios_names)
174                 return False;
175
176         memset(smb_my_netbios_names, '\0', sizeof(char *) * smb_num_netbios_names);
177         return True;
178 }
179
180 static BOOL set_my_netbios_names(const char *name, int i)
181 {
182         SAFE_FREE(smb_my_netbios_names[i]);
183
184         smb_my_netbios_names[i] = strdup(name);
185         if (!smb_my_netbios_names[i])
186                 return False;
187         strupper(smb_my_netbios_names[i]);
188         return True;
189 }
190
191 const char *my_netbios_names(int i)
192 {
193         return smb_my_netbios_names[i];
194 }
195
196 BOOL set_netbios_aliases(const char **str_array)
197 {
198         size_t namecount;
199
200         /* Work out the max number of netbios aliases that we have */
201         for( namecount=0; str_array && (str_array[namecount] != NULL); namecount++ )
202                 ;
203
204         if ( global_myname() && *global_myname())
205                 namecount++;
206
207         /* Allocate space for the netbios aliases */
208         if (!allocate_my_netbios_names_array(namecount))
209                 return False;
210
211         /* Use the global_myname string first */
212         namecount=0;
213         if ( global_myname() && *global_myname()) {
214                 set_my_netbios_names( global_myname(), namecount );
215                 namecount++;
216         }
217
218         if (str_array) {
219                 size_t i;
220                 for ( i = 0; str_array[i] != NULL; i++) {
221                         size_t n;
222                         BOOL duplicate = False;
223
224                         /* Look for duplicates */
225                         for( n=0; n<namecount; n++ ) {
226                                 if( strequal( str_array[i], my_netbios_names(n) ) ) {
227                                         duplicate = True;
228                                         break;
229                                 }
230                         }
231                         if (!duplicate) {
232                                 if (!set_my_netbios_names(str_array[i], namecount))
233                                         return False;
234                                 namecount++;
235                         }
236                 }
237         }
238         return True;
239 }
240
241 /****************************************************************************
242   Common name initialization code.
243 ****************************************************************************/
244
245 BOOL init_names(void)
246 {
247         extern fstring local_machine;
248         char *p;
249         int n;
250
251         if (global_myname() == NULL || *global_myname() == '\0') {
252                 fstring name;
253
254                 fstrcpy( name, myhostname() );
255                 p = strchr( name, '.' );
256                 if (p)
257                         *p = 0;
258                 if (!set_global_myname(name)) {
259                         DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
260                         return False;
261                 }
262         }
263
264         if (!set_netbios_aliases(lp_netbios_aliases())) {
265                 DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
266                 return False;
267         }                       
268
269         fstrcpy( local_machine, global_myname() );
270         trim_string( local_machine, " ", " " );
271         p = strchr( local_machine, ' ' );
272         if (p)
273                 *p = 0;
274         strlower( local_machine );
275
276         DEBUG( 5, ("Netbios name list:-\n") );
277         for( n=0; my_netbios_names(n); n++ )
278                 DEBUGADD( 5, ( "my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names(n) ) );
279
280         return( True );
281 }
282
283 /**************************************************************************n
284  Find a suitable temporary directory. The result should be copied immediately
285  as it may be overwritten by a subsequent call.
286 ****************************************************************************/
287
288 const char *tmpdir(void)
289 {
290         char *p;
291         if ((p = getenv("TMPDIR")))
292                 return p;
293         return "/tmp";
294 }
295
296 /****************************************************************************
297  Determine whether we are in the specified group.
298 ****************************************************************************/
299
300 BOOL in_group(gid_t group, gid_t current_gid, int ngroups, const gid_t *groups)
301 {
302         int i;
303
304         if (group == current_gid)
305                 return(True);
306
307         for (i=0;i<ngroups;i++)
308                 if (group == groups[i])
309                         return(True);
310
311         return(False);
312 }
313
314 /****************************************************************************
315  Like atoi but gets the value up to the separator character.
316 ****************************************************************************/
317
318 static char *Atoic(char *p, int *n, char *c)
319 {
320         if (!isdigit((int)*p)) {
321                 DEBUG(5, ("Atoic: malformed number\n"));
322                 return NULL;
323         }
324
325         (*n) = atoi(p);
326
327         while ((*p) && isdigit((int)*p))
328                 p++;
329
330         if (strchr_m(c, *p) == NULL) {
331                 DEBUG(5, ("Atoic: no separator characters (%s) not found\n", c));
332                 return NULL;
333         }
334
335         return p;
336 }
337
338 /*************************************************************************
339  Reads a list of numbers.
340  *************************************************************************/
341
342 char *get_numlist(char *p, uint32 **num, int *count)
343 {
344         int val;
345
346         if (num == NULL || count == NULL)
347                 return NULL;
348
349         (*count) = 0;
350         (*num  ) = NULL;
351
352         while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':') {
353                 uint32 *tn;
354                 
355                 tn = Realloc((*num), ((*count)+1) * sizeof(uint32));
356                 if (tn == NULL) {
357                         SAFE_FREE(*num);
358                         return NULL;
359                 } else
360                         (*num) = tn;
361                 (*num)[(*count)] = val;
362                 (*count)++;
363                 p++;
364         }
365
366         return p;
367 }
368
369 /*******************************************************************
370  Check if a file exists - call vfs_file_exist for samba files.
371 ********************************************************************/
372
373 BOOL file_exist(const char *fname,SMB_STRUCT_STAT *sbuf)
374 {
375         SMB_STRUCT_STAT st;
376         if (!sbuf)
377                 sbuf = &st;
378   
379         if (sys_stat(fname,sbuf) != 0) 
380                 return(False);
381
382         return((S_ISREG(sbuf->st_mode)) || (S_ISFIFO(sbuf->st_mode)));
383 }
384
385 /*******************************************************************
386  Check a files mod time.
387 ********************************************************************/
388
389 time_t file_modtime(const char *fname)
390 {
391         SMB_STRUCT_STAT st;
392   
393         if (sys_stat(fname,&st) != 0) 
394                 return(0);
395
396         return(st.st_mtime);
397 }
398
399 /*******************************************************************
400  Check if a directory exists.
401 ********************************************************************/
402
403 BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st)
404 {
405         SMB_STRUCT_STAT st2;
406         BOOL ret;
407
408         if (!st)
409                 st = &st2;
410
411         if (sys_stat(dname,st) != 0) 
412                 return(False);
413
414         ret = S_ISDIR(st->st_mode);
415         if(!ret)
416                 errno = ENOTDIR;
417         return ret;
418 }
419
420 /*******************************************************************
421  Returns the size in bytes of the named file.
422 ********************************************************************/
423
424 SMB_OFF_T get_file_size(char *file_name)
425 {
426         SMB_STRUCT_STAT buf;
427         buf.st_size = 0;
428         if(sys_stat(file_name,&buf) != 0)
429                 return (SMB_OFF_T)-1;
430         return(buf.st_size);
431 }
432
433 /*******************************************************************
434  Return a string representing an attribute for a file.
435 ********************************************************************/
436
437 char *attrib_string(uint16 mode)
438 {
439         static fstring attrstr;
440
441         attrstr[0] = 0;
442
443         if (mode & aVOLID) fstrcat(attrstr,"V");
444         if (mode & aDIR) fstrcat(attrstr,"D");
445         if (mode & aARCH) fstrcat(attrstr,"A");
446         if (mode & aHIDDEN) fstrcat(attrstr,"H");
447         if (mode & aSYSTEM) fstrcat(attrstr,"S");
448         if (mode & aRONLY) fstrcat(attrstr,"R");          
449
450         return(attrstr);
451 }
452
453 /*******************************************************************
454  Show a smb message structure.
455 ********************************************************************/
456
457 void show_msg(char *buf)
458 {
459         int i;
460         int bcc=0;
461
462         if (!DEBUGLVL(5))
463                 return;
464         
465         DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
466                         smb_len(buf),
467                         (int)CVAL(buf,smb_com),
468                         (int)CVAL(buf,smb_rcls),
469                         (int)CVAL(buf,smb_reh),
470                         (int)SVAL(buf,smb_err),
471                         (int)CVAL(buf,smb_flg),
472                         (int)SVAL(buf,smb_flg2)));
473         DEBUGADD(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n",
474                         (int)SVAL(buf,smb_tid),
475                         (int)SVAL(buf,smb_pid),
476                         (int)SVAL(buf,smb_uid),
477                         (int)SVAL(buf,smb_mid)));
478         DEBUGADD(5,("smt_wct=%d\n",(int)CVAL(buf,smb_wct)));
479
480         for (i=0;i<(int)CVAL(buf,smb_wct);i++)
481                 DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i,
482                         SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
483         
484         bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
485
486         DEBUGADD(5,("smb_bcc=%d\n",bcc));
487
488         if (DEBUGLEVEL < 10)
489                 return;
490
491         if (DEBUGLEVEL < 50)
492                 bcc = MIN(bcc, 512);
493
494         dump_data(10, smb_buf(buf), bcc);       
495 }
496
497 /*******************************************************************
498  Set the length and marker of an smb packet.
499 ********************************************************************/
500
501 void smb_setlen(char *buf,int len)
502 {
503         _smb_setlen(buf,len);
504
505         SCVAL(buf,4,0xFF);
506         SCVAL(buf,5,'S');
507         SCVAL(buf,6,'M');
508         SCVAL(buf,7,'B');
509 }
510
511 /*******************************************************************
512  Setup the word count and byte count for a smb message.
513 ********************************************************************/
514
515 int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
516 {
517         if (zero)
518                 memset(buf + smb_size,'\0',num_words*2 + num_bytes);
519         SCVAL(buf,smb_wct,num_words);
520         SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);  
521         smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
522         return (smb_size + num_words*2 + num_bytes);
523 }
524
525 /*******************************************************************
526  Setup only the byte count for a smb message.
527 ********************************************************************/
528
529 int set_message_bcc(char *buf,int num_bytes)
530 {
531         int num_words = CVAL(buf,smb_wct);
532         SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);  
533         smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
534         return (smb_size + num_words*2 + num_bytes);
535 }
536
537 /*******************************************************************
538  Setup only the byte count for a smb message, using the end of the
539  message as a marker.
540 ********************************************************************/
541
542 int set_message_end(void *outbuf,void *end_ptr)
543 {
544         return set_message_bcc((char *)outbuf,PTR_DIFF(end_ptr,smb_buf((char *)outbuf)));
545 }
546
547 /*******************************************************************
548  Reduce a file name, removing .. elements.
549 ********************************************************************/
550
551 void dos_clean_name(char *s)
552 {
553         char *p=NULL;
554
555         DEBUG(3,("dos_clean_name [%s]\n",s));
556
557         /* remove any double slashes */
558         all_string_sub(s, "\\\\", "\\", 0);
559
560         while ((p = strstr(s,"\\..\\")) != NULL) {
561                 pstring s1;
562
563                 *p = 0;
564                 pstrcpy(s1,p+3);
565
566                 if ((p=strrchr_m(s,'\\')) != NULL)
567                         *p = 0;
568                 else
569                         *s = 0;
570                 pstrcat(s,s1);
571         }  
572
573         trim_string(s,NULL,"\\..");
574
575         all_string_sub(s, "\\.\\", "\\", 0);
576 }
577
578 /*******************************************************************
579  Reduce a file name, removing .. elements. 
580 ********************************************************************/
581
582 void unix_clean_name(char *s)
583 {
584         char *p=NULL;
585
586         DEBUG(3,("unix_clean_name [%s]\n",s));
587
588         /* remove any double slashes */
589         all_string_sub(s, "//","/", 0);
590
591         /* Remove leading ./ characters */
592         if(strncmp(s, "./", 2) == 0) {
593                 trim_string(s, "./", NULL);
594                 if(*s == 0)
595                         pstrcpy(s,"./");
596         }
597
598         while ((p = strstr(s,"/../")) != NULL) {
599                 pstring s1;
600
601                 *p = 0;
602                 pstrcpy(s1,p+3);
603
604                 if ((p=strrchr_m(s,'/')) != NULL)
605                         *p = 0;
606                 else
607                         *s = 0;
608                 pstrcat(s,s1);
609         }  
610
611         trim_string(s,NULL,"/..");
612 }
613
614 /*******************************************************************
615  Convert '\' to '/'.
616  Reduce a file name, removing or reducing /../ , /./ , // elements.
617  Remove also any trailing . and /
618  Return a new allocated string.
619 ********************************************************************/
620
621 smb_ucs2_t *unix_clean_path(const smb_ucs2_t *s)
622 {
623         smb_ucs2_t *ns;
624         smb_ucs2_t *p, *r, *t;
625
626         DEBUG(3, ("unix_clean_path\n")); /*  [%unicode]\n")); */
627         if(!s)
628                 return NULL;
629
630         /* convert '\' to '/' */
631         ns = strdup_w(s);
632         if (!ns)
633                 return NULL;
634         unix_format_w(ns);
635
636         /* remove all double slashes */
637         p = ns;
638         ns = all_string_sub_wa(p, "//", "/");
639         SAFE_FREE(p);
640         if (!ns)
641                 return NULL;
642
643         /* remove any /./ */
644         p = ns;
645         ns = all_string_sub_wa(p, "/./", "/");
646         SAFE_FREE(p);
647         if (!ns)
648                 return NULL;
649
650         /* reduce any /../ */
651         t = ns;
652         while (*t && (r = strstr_wa(t, "/.."))) {
653                 t = &(r[3]);
654                 if (*t == UCS2_CHAR('/') || *t == 0) {
655                         *r = 0;
656                         p = strrchr_w(ns, UCS2_CHAR('/'));
657                         if (!p)
658                                 p = ns;
659                         if (*t == 0)
660                                 *p = 0;
661                         else
662                                 memmove(p, t, (strlen_w(t) + 1) * sizeof(smb_ucs2_t));
663                         t = p;
664                 }
665         }
666
667         /* remove any leading ./ trailing /. */
668         trim_string_wa(ns, "./", "/.");
669
670         /* remove any leading and trailing / */
671         trim_string_wa(ns, "/", "/");
672
673         return ns;
674 }
675
676 /****************************************************************************
677  Make a dir struct.
678 ****************************************************************************/
679
680 void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T size,int mode,time_t date)
681 {  
682         char *p;
683         pstring mask2;
684
685         pstrcpy(mask2,mask);
686
687         if ((mode & aDIR) != 0)
688                 size = 0;
689
690         memset(buf+1,' ',11);
691         if ((p = strchr_m(mask2,'.')) != NULL) {
692                 *p = 0;
693                 push_ascii(buf+1,mask2,8, 0);
694                 push_ascii(buf+9,p+1,3, 0);
695                 *p = '.';
696         } else
697                 push_ascii(buf+1,mask2,11, 0);
698
699         memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
700         SCVAL(buf,21,mode);
701         put_dos_date(buf,22,date);
702         SSVAL(buf,26,size & 0xFFFF);
703         SSVAL(buf,28,(size >> 16)&0xFFFF);
704         push_ascii(buf+30,fname,12, case_sensitive ? 0 : STR_UPPER);
705         DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
706 }
707
708 /*******************************************************************
709  Close the low 3 fd's and open dev/null in their place.
710 ********************************************************************/
711
712 void close_low_fds(BOOL stderr_too)
713 {
714 #ifndef VALGRIND
715         int fd;
716         int i;
717
718         close(0);
719         close(1); 
720
721         if (stderr_too)
722                 close(2);
723
724         /* try and use up these file descriptors, so silly
725                 library routines writing to stdout etc won't cause havoc */
726         for (i=0;i<3;i++) {
727                 if (i == 2 && !stderr_too)
728                         continue;
729
730                 fd = sys_open("/dev/null",O_RDWR,0);
731                 if (fd < 0)
732                         fd = sys_open("/dev/null",O_WRONLY,0);
733                 if (fd < 0) {
734                         DEBUG(0,("Can't open /dev/null\n"));
735                         return;
736                 }
737                 if (fd != i) {
738                         DEBUG(0,("Didn't get file descriptor %d\n",i));
739                         return;
740                 }
741         }
742 #endif
743 }
744
745 /****************************************************************************
746  Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
747  else
748   if SYSV use O_NDELAY
749   if BSD use FNDELAY
750 ****************************************************************************/
751
752 int set_blocking(int fd, BOOL set)
753 {
754         int val;
755 #ifdef O_NONBLOCK
756 #define FLAG_TO_SET O_NONBLOCK
757 #else
758 #ifdef SYSV
759 #define FLAG_TO_SET O_NDELAY
760 #else /* BSD */
761 #define FLAG_TO_SET FNDELAY
762 #endif
763 #endif
764
765         if((val = sys_fcntl_long(fd, F_GETFL, 0)) == -1)
766                 return -1;
767         if(set) /* Turn blocking on - ie. clear nonblock flag */
768                 val &= ~FLAG_TO_SET;
769         else
770                 val |= FLAG_TO_SET;
771         return sys_fcntl_long( fd, F_SETFL, val);
772 #undef FLAG_TO_SET
773 }
774
775 /****************************************************************************
776  Transfer some data between two fd's.
777 ****************************************************************************/
778
779 #ifndef TRANSFER_BUF_SIZE
780 #define TRANSFER_BUF_SIZE 65536
781 #endif
782
783 ssize_t transfer_file_internal(int infd, int outfd, size_t n, ssize_t (*read_fn)(int, void *, size_t),
784                                                 ssize_t (*write_fn)(int, const void *, size_t))
785 {
786         char *buf;
787         size_t total = 0;
788         ssize_t read_ret;
789         ssize_t write_ret;
790         size_t num_to_read_thistime;
791         size_t num_written = 0;
792
793         if ((buf = malloc(TRANSFER_BUF_SIZE)) == NULL)
794                 return -1;
795
796         while (total < n) {
797                 num_to_read_thistime = MIN((n - total), TRANSFER_BUF_SIZE);
798
799                 read_ret = (*read_fn)(infd, buf, num_to_read_thistime);
800                 if (read_ret == -1) {
801                         DEBUG(0,("transfer_file_internal: read failure. Error = %s\n", strerror(errno) ));
802                         SAFE_FREE(buf);
803                         return -1;
804                 }
805                 if (read_ret == 0)
806                         break;
807
808                 num_written = 0;
809  
810                 while (num_written < read_ret) {
811                         write_ret = (*write_fn)(outfd,buf + num_written, read_ret - num_written);
812  
813                         if (write_ret == -1) {
814                                 DEBUG(0,("transfer_file_internal: write failure. Error = %s\n", strerror(errno) ));
815                                 SAFE_FREE(buf);
816                                 return -1;
817                         }
818                         if (write_ret == 0)
819                                 return (ssize_t)total;
820  
821                         num_written += (size_t)write_ret;
822                 }
823
824                 total += (size_t)read_ret;
825         }
826
827         SAFE_FREE(buf);
828         return (ssize_t)total;          
829 }
830
831 SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n)
832 {
833         return (SMB_OFF_T)transfer_file_internal(infd, outfd, (size_t)n, sys_read, sys_write);
834 }
835
836 /*******************************************************************
837  Sleep for a specified number of milliseconds.
838 ********************************************************************/
839
840 void msleep(unsigned int t)
841 {
842         unsigned int tdiff=0;
843         struct timeval tval,t1,t2;  
844         fd_set fds;
845
846         GetTimeOfDay(&t1);
847         GetTimeOfDay(&t2);
848   
849         while (tdiff < t) {
850                 tval.tv_sec = (t-tdiff)/1000;
851                 tval.tv_usec = 1000*((t-tdiff)%1000);
852
853                 /* Never wait for more than 1 sec. */
854                 if (tval.tv_sec > 1) {
855                         tval.tv_sec = 1; 
856                         tval.tv_usec = 0;
857                 }
858
859                 FD_ZERO(&fds);
860                 errno = 0;
861                 sys_select_intr(0,&fds,NULL,NULL,&tval);
862
863                 GetTimeOfDay(&t2);
864                 if (t2.tv_sec < t1.tv_sec) {
865                         /* Someone adjusted time... */
866                         t1 = t2;
867                 }
868
869                 tdiff = TvalDiff(&t1,&t2);
870         }
871 }
872
873 /****************************************************************************
874  Become a daemon, discarding the controlling terminal.
875 ****************************************************************************/
876
877 void become_daemon(BOOL Fork)
878 {
879         if (Fork) {
880                 if (sys_fork()) {
881                         _exit(0);
882                 }
883         }
884
885   /* detach from the terminal */
886 #ifdef HAVE_SETSID
887         setsid();
888 #elif defined(TIOCNOTTY)
889         {
890                 int i = sys_open("/dev/tty", O_RDWR, 0);
891                 if (i != -1) {
892                         ioctl(i, (int) TIOCNOTTY, (char *)0);      
893                         close(i);
894                 }
895         }
896 #endif /* HAVE_SETSID */
897
898         /* Close fd's 0,1,2. Needed if started by rsh */
899         close_low_fds(False);  /* Don't close stderr, let the debug system
900                                   attach it to the logfile */
901 }
902
903 /****************************************************************************
904  Put up a yes/no prompt.
905 ****************************************************************************/
906
907 BOOL yesno(char *p)
908 {
909         pstring ans;
910         printf("%s",p);
911
912         if (!fgets(ans,sizeof(ans)-1,stdin))
913                 return(False);
914
915         if (*ans == 'y' || *ans == 'Y')
916                 return(True);
917
918         return(False);
919 }
920
921 /****************************************************************************
922  Expand a pointer to be a particular size.
923 ****************************************************************************/
924
925 void *Realloc(void *p,size_t size)
926 {
927         void *ret=NULL;
928
929         if (size == 0) {
930                 SAFE_FREE(p);
931                 DEBUG(5,("Realloc asked for 0 bytes\n"));
932                 return NULL;
933         }
934
935         if (!p)
936                 ret = (void *)malloc(size);
937         else
938                 ret = (void *)realloc(p,size);
939
940         if (!ret)
941                 DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size));
942
943         return(ret);
944 }
945
946 /****************************************************************************
947  Free memory, checks for NULL.
948  Use directly SAFE_FREE()
949  Exists only because we need to pass a function pointer somewhere --SSS
950 ****************************************************************************/
951
952 void safe_free(void *p)
953 {
954         SAFE_FREE(p);
955 }
956
957 /****************************************************************************
958  Get my own name and IP.
959 ****************************************************************************/
960
961 BOOL get_myname(char *my_name)
962 {
963         pstring hostname;
964
965         *hostname = 0;
966
967         /* get my host name */
968         if (gethostname(hostname, sizeof(hostname)) == -1) {
969                 DEBUG(0,("gethostname failed\n"));
970                 return False;
971         } 
972
973         /* Ensure null termination. */
974         hostname[sizeof(hostname)-1] = '\0';
975
976         if (my_name) {
977                 /* split off any parts after an initial . */
978                 char *p = strchr_m(hostname,'.');
979
980                 if (p)
981                         *p = 0;
982                 
983                 fstrcpy(my_name,hostname);
984         }
985         
986         return(True);
987 }
988
989 /****************************************************************************
990  Get my own name, including domain.
991 ****************************************************************************/
992
993 BOOL get_myfullname(char *my_name)
994 {
995         pstring hostname;
996
997         *hostname = 0;
998
999         /* get my host name */
1000         if (gethostname(hostname, sizeof(hostname)) == -1) {
1001                 DEBUG(0,("gethostname failed\n"));
1002                 return False;
1003         } 
1004
1005         /* Ensure null termination. */
1006         hostname[sizeof(hostname)-1] = '\0';
1007
1008         if (my_name)
1009                 fstrcpy(my_name, hostname);
1010         return True;
1011 }
1012
1013 /****************************************************************************
1014  Get my own domain name.
1015 ****************************************************************************/
1016
1017 BOOL get_mydomname(char *my_domname)
1018 {
1019         pstring hostname;
1020         char *p;
1021
1022         *hostname = 0;
1023         /* get my host name */
1024         if (gethostname(hostname, sizeof(hostname)) == -1) {
1025                 DEBUG(0,("gethostname failed\n"));
1026                 return False;
1027         } 
1028
1029         /* Ensure null termination. */
1030         hostname[sizeof(hostname)-1] = '\0';
1031
1032         p = strchr_m(hostname, '.');
1033
1034         if (!p)
1035                 return False;
1036
1037         p++;
1038         
1039         if (my_domname)
1040                 fstrcpy(my_domname, p);
1041
1042         return True;
1043 }
1044
1045 /****************************************************************************
1046  Interpret a protocol description string, with a default.
1047 ****************************************************************************/
1048
1049 int interpret_protocol(char *str,int def)
1050 {
1051         if (strequal(str,"NT1"))
1052                 return(PROTOCOL_NT1);
1053         if (strequal(str,"LANMAN2"))
1054                 return(PROTOCOL_LANMAN2);
1055         if (strequal(str,"LANMAN1"))
1056                 return(PROTOCOL_LANMAN1);
1057         if (strequal(str,"CORE"))
1058                 return(PROTOCOL_CORE);
1059         if (strequal(str,"COREPLUS"))
1060                 return(PROTOCOL_COREPLUS);
1061         if (strequal(str,"CORE+"))
1062                 return(PROTOCOL_COREPLUS);
1063   
1064         DEBUG(0,("Unrecognised protocol level %s\n",str));
1065   
1066         return(def);
1067 }
1068
1069 /****************************************************************************
1070  Return true if a string could be a pure IP address.
1071 ****************************************************************************/
1072
1073 BOOL is_ipaddress(const char *str)
1074 {
1075         BOOL pure_address = True;
1076         int i;
1077   
1078         for (i=0; pure_address && str[i]; i++)
1079                 if (!(isdigit((int)str[i]) || str[i] == '.'))
1080                         pure_address = False;
1081
1082         /* Check that a pure number is not misinterpreted as an IP */
1083         pure_address = pure_address && (strchr_m(str, '.') != NULL);
1084
1085         return pure_address;
1086 }
1087
1088 /****************************************************************************
1089  Interpret an internet address or name into an IP address in 4 byte form.
1090 ****************************************************************************/
1091
1092 uint32 interpret_addr(const char *str)
1093 {
1094         struct hostent *hp;
1095         uint32 res;
1096
1097         if (strcmp(str,"0.0.0.0") == 0)
1098                 return(0);
1099         if (strcmp(str,"255.255.255.255") == 0)
1100                 return(0xFFFFFFFF);
1101
1102   /* if it's in the form of an IP address then get the lib to interpret it */
1103         if (is_ipaddress(str)) {
1104                 res = inet_addr(str);
1105         } else {
1106                 /* otherwise assume it's a network name of some sort and use 
1107                         sys_gethostbyname */
1108                 if ((hp = sys_gethostbyname(str)) == 0) {
1109                         DEBUG(3,("sys_gethostbyname: Unknown host. %s\n",str));
1110                         return 0;
1111                 }
1112
1113                 if(hp->h_addr == NULL) {
1114                         DEBUG(3,("sys_gethostbyname: host address is invalid for host %s\n",str));
1115                         return 0;
1116                 }
1117                 putip((char *)&res,(char *)hp->h_addr);
1118         }
1119
1120         if (res == (uint32)-1)
1121                 return(0);
1122
1123         return(res);
1124 }
1125
1126 /*******************************************************************
1127  A convenient addition to interpret_addr().
1128 ******************************************************************/
1129
1130 struct in_addr *interpret_addr2(const char *str)
1131 {
1132         static struct in_addr ret;
1133         uint32 a = interpret_addr(str);
1134         ret.s_addr = a;
1135         return(&ret);
1136 }
1137
1138 /*******************************************************************
1139  Check if an IP is the 0.0.0.0.
1140 ******************************************************************/
1141
1142 BOOL is_zero_ip(struct in_addr ip)
1143 {
1144         uint32 a;
1145         putip((char *)&a,(char *)&ip);
1146         return(a == 0);
1147 }
1148
1149 /*******************************************************************
1150  Set an IP to 0.0.0.0.
1151 ******************************************************************/
1152
1153 void zero_ip(struct in_addr *ip)
1154 {
1155         static BOOL init;
1156         static struct in_addr ipzero;
1157
1158         if (!init) {
1159                 ipzero = *interpret_addr2("0.0.0.0");
1160                 init = True;
1161         }
1162
1163         *ip = ipzero;
1164 }
1165
1166 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1167 /******************************************************************
1168  Remove any mount options such as -rsize=2048,wsize=2048 etc.
1169  Based on a fix from <Thomas.Hepper@icem.de>.
1170 *******************************************************************/
1171
1172 static void strip_mount_options( pstring *str)
1173 {
1174         if (**str == '-') { 
1175                 char *p = *str;
1176                 while(*p && !isspace(*p))
1177                         p++;
1178                 while(*p && isspace(*p))
1179                         p++;
1180                 if(*p) {
1181                         pstring tmp_str;
1182
1183                         pstrcpy(tmp_str, p);
1184                         pstrcpy(*str, tmp_str);
1185                 }
1186         }
1187 }
1188
1189 /*******************************************************************
1190  Patch from jkf@soton.ac.uk
1191  Split Luke's automount_server into YP lookup and string splitter
1192  so can easily implement automount_path(). 
1193  As we may end up doing both, cache the last YP result. 
1194 *******************************************************************/
1195
1196 #ifdef WITH_NISPLUS_HOME
1197 char *automount_lookup(const char *user_name)
1198 {
1199         static fstring last_key = "";
1200         static pstring last_value = "";
1201  
1202         char *nis_map = (char *)lp_nis_home_map_name();
1203  
1204         char buffer[NIS_MAXATTRVAL + 1];
1205         nis_result *result;
1206         nis_object *object;
1207         entry_obj  *entry;
1208  
1209         if (strcmp(user_name, last_key)) {
1210                 slprintf(buffer, sizeof(buffer)-1, "[key=%s],%s", user_name, nis_map);
1211                 DEBUG(5, ("NIS+ querystring: %s\n", buffer));
1212  
1213                 if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL)) {
1214                         if (result->status != NIS_SUCCESS) {
1215                                 DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
1216                                 fstrcpy(last_key, ""); pstrcpy(last_value, "");
1217                         } else {
1218                                 object = result->objects.objects_val;
1219                                 if (object->zo_data.zo_type == ENTRY_OBJ) {
1220                                         entry = &object->zo_data.objdata_u.en_data;
1221                                         DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
1222                                         DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
1223  
1224                                         pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
1225                                         pstring_sub(last_value, "&", user_name);
1226                                         fstrcpy(last_key, user_name);
1227                                 }
1228                         }
1229                 }
1230                 nis_freeresult(result);
1231         }
1232
1233         strip_mount_options(&last_value);
1234
1235         DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
1236         return last_value;
1237 }
1238 #else /* WITH_NISPLUS_HOME */
1239
1240 char *automount_lookup(const char *user_name)
1241 {
1242         static fstring last_key = "";
1243         static pstring last_value = "";
1244
1245         int nis_error;        /* returned by yp all functions */
1246         char *nis_result;     /* yp_match inits this */
1247         int nis_result_len;  /* and set this */
1248         char *nis_domain;     /* yp_get_default_domain inits this */
1249         char *nis_map = (char *)lp_nis_home_map_name();
1250
1251         if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
1252                 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
1253                 return last_value;
1254         }
1255
1256         DEBUG(5, ("NIS Domain: %s\n", nis_domain));
1257
1258         if (!strcmp(user_name, last_key)) {
1259                 nis_result = last_value;
1260                 nis_result_len = strlen(last_value);
1261                 nis_error = 0;
1262         } else {
1263                 if ((nis_error = yp_match(nis_domain, nis_map, user_name, strlen(user_name),
1264                                 &nis_result, &nis_result_len)) == 0) {
1265                         if (!nis_error && nis_result_len >= sizeof(pstring)) {
1266                                 nis_result_len = sizeof(pstring)-1;
1267                         }
1268                         fstrcpy(last_key, user_name);
1269                         strncpy(last_value, nis_result, nis_result_len);
1270                         last_value[nis_result_len] = '\0';
1271                         strip_mount_options(&last_value);
1272
1273                 } else if(nis_error == YPERR_KEY) {
1274
1275                         /* If Key lookup fails user home server is not in nis_map 
1276                                 use default information for server, and home directory */
1277                         last_value[0] = 0;
1278                         DEBUG(3, ("YP Key not found:  while looking up \"%s\" in map \"%s\"\n", 
1279                                         user_name, nis_map));
1280                         DEBUG(3, ("using defaults for server and home directory\n"));
1281                 } else {
1282                         DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n", 
1283                                         yperr_string(nis_error), user_name, nis_map));
1284                 }
1285         }
1286
1287         DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
1288         return last_value;
1289 }
1290 #endif /* WITH_NISPLUS_HOME */
1291 #endif
1292
1293 /*******************************************************************
1294  Are two IPs on the same subnet?
1295 ********************************************************************/
1296
1297 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
1298 {
1299         uint32 net1,net2,nmask;
1300
1301         nmask = ntohl(mask.s_addr);
1302         net1  = ntohl(ip1.s_addr);
1303         net2  = ntohl(ip2.s_addr);
1304             
1305         return((net1 & nmask) == (net2 & nmask));
1306 }
1307
1308
1309 /****************************************************************************
1310  Check if a process exists. Does this work on all unixes?
1311 ****************************************************************************/
1312
1313 BOOL process_exists(pid_t pid)
1314 {
1315         /* Doing kill with a non-positive pid causes messages to be
1316          * sent to places we don't want. */
1317         SMB_ASSERT(pid > 0);
1318         return(kill(pid,0) == 0 || errno != ESRCH);
1319 }
1320
1321 /*******************************************************************
1322  Convert a uid into a user name.
1323 ********************************************************************/
1324
1325 const char *uidtoname(uid_t uid)
1326 {
1327         static fstring name;
1328         struct passwd *pass;
1329
1330         pass = getpwuid_alloc(uid);
1331         if (pass) {
1332                 fstrcpy(name, pass->pw_name);
1333                 passwd_free(&pass);
1334         } else {
1335                 slprintf(name, sizeof(name) - 1, "%ld",(long int)uid);
1336         }
1337         return name;
1338 }
1339
1340
1341 /*******************************************************************
1342  Convert a gid into a group name.
1343 ********************************************************************/
1344
1345 char *gidtoname(gid_t gid)
1346 {
1347         static fstring name;
1348         struct group *grp;
1349
1350         grp = getgrgid(gid);
1351         if (grp)
1352                 return(grp->gr_name);
1353         slprintf(name,sizeof(name) - 1, "%d",(int)gid);
1354         return(name);
1355 }
1356
1357 /*******************************************************************
1358  Convert a user name into a uid. 
1359 ********************************************************************/
1360
1361 uid_t nametouid(char *name)
1362 {
1363         struct passwd *pass;
1364         char *p;
1365         uid_t u;
1366
1367         pass = getpwnam_alloc(name);
1368         if (pass) {
1369                 u = pass->pw_uid;
1370                 passwd_free(&pass);
1371                 return u;
1372         }
1373
1374         u = (uid_t)strtol(name, &p, 0);
1375         if ((p != name) && (*p == '\0'))
1376                 return u;
1377
1378         return (uid_t)-1;
1379 }
1380
1381 /*******************************************************************
1382  Convert a name to a gid_t if possible. Return -1 if not a group. 
1383 ********************************************************************/
1384
1385 gid_t nametogid(const char *name)
1386 {
1387         struct group *grp;
1388         char *p;
1389         gid_t g;
1390
1391         g = (gid_t)strtol(name, &p, 0);
1392         if ((p != name) && (*p == '\0'))
1393                 return g;
1394
1395         grp = sys_getgrnam(name);
1396         if (grp)
1397                 return(grp->gr_gid);
1398         return (gid_t)-1;
1399 }
1400
1401 /*******************************************************************
1402  Something really nasty happened - panic !
1403 ********************************************************************/
1404
1405 void smb_panic(const char *why)
1406 {
1407         char *cmd = lp_panic_action();
1408         int result;
1409
1410         if (cmd && *cmd) {
1411                 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
1412                 result = system(cmd);
1413
1414                 if (result == -1)
1415                         DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
1416                                   strerror(errno)));
1417                 else
1418                         DEBUG(0, ("smb_panic(): action returned status %d\n",
1419                                   WEXITSTATUS(result)));
1420         }
1421         DEBUG(0,("PANIC: %s\n", why));
1422         dbgflush();
1423         abort();
1424 }
1425
1426 /*******************************************************************
1427  A readdir wrapper which just returns the file name.
1428 ********************************************************************/
1429
1430 char *readdirname(DIR *p)
1431 {
1432         SMB_STRUCT_DIRENT *ptr;
1433         char *dname;
1434
1435         if (!p)
1436                 return(NULL);
1437   
1438         ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
1439         if (!ptr)
1440                 return(NULL);
1441
1442         dname = ptr->d_name;
1443
1444 #ifdef NEXT2
1445         if (telldir(p) < 0)
1446                 return(NULL);
1447 #endif
1448
1449 #ifdef HAVE_BROKEN_READDIR
1450         /* using /usr/ucb/cc is BAD */
1451         dname = dname - 2;
1452 #endif
1453
1454         {
1455                 static pstring buf;
1456                 int len = NAMLEN(ptr);
1457                 memcpy(buf, dname, len);
1458                 buf[len] = 0;
1459                 dname = buf;
1460         }
1461
1462         return(dname);
1463 }
1464
1465 /*******************************************************************
1466  Utility function used to decide if the last component 
1467  of a path matches a (possibly wildcarded) entry in a namelist.
1468 ********************************************************************/
1469
1470 BOOL is_in_path(const char *name, name_compare_entry *namelist)
1471 {
1472         pstring last_component;
1473         char *p;
1474
1475         DEBUG(8, ("is_in_path: %s\n", name));
1476
1477         /* if we have no list it's obviously not in the path */
1478         if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
1479                 DEBUG(8,("is_in_path: no name list.\n"));
1480                 return False;
1481         }
1482
1483         /* Get the last component of the unix name. */
1484         p = strrchr_m(name, '/');
1485         strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
1486         last_component[sizeof(last_component)-1] = '\0'; 
1487
1488         for(; namelist->name != NULL; namelist++) {
1489                 if(namelist->is_wild) {
1490                         if (mask_match(last_component, namelist->name, case_sensitive)) {
1491                                 DEBUG(8,("is_in_path: mask match succeeded\n"));
1492                                 return True;
1493                         }
1494                 } else {
1495                         if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
1496                                                 (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0))) {
1497                                 DEBUG(8,("is_in_path: match succeeded\n"));
1498                                 return True;
1499                         }
1500                 }
1501         }
1502         DEBUG(8,("is_in_path: match not found\n"));
1503  
1504         return False;
1505 }
1506
1507 /*******************************************************************
1508  Strip a '/' separated list into an array of 
1509  name_compare_enties structures suitable for 
1510  passing to is_in_path(). We do this for
1511  speed so we can pre-parse all the names in the list 
1512  and don't do it for each call to is_in_path().
1513  namelist is modified here and is assumed to be 
1514  a copy owned by the caller.
1515  We also check if the entry contains a wildcard to
1516  remove a potentially expensive call to mask_match
1517  if possible.
1518 ********************************************************************/
1519  
1520 void set_namearray(name_compare_entry **ppname_array, char *namelist)
1521 {
1522         char *name_end;
1523         char *nameptr = namelist;
1524         int num_entries = 0;
1525         int i;
1526
1527         (*ppname_array) = NULL;
1528
1529         if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0'))) 
1530                 return;
1531
1532         /* We need to make two passes over the string. The
1533                 first to count the number of elements, the second
1534                 to split it.
1535         */
1536
1537         while(*nameptr) {
1538                 if ( *nameptr == '/' ) {
1539                         /* cope with multiple (useless) /s) */
1540                         nameptr++;
1541                         continue;
1542                 }
1543                 /* find the next / */
1544                 name_end = strchr_m(nameptr, '/');
1545
1546                 /* oops - the last check for a / didn't find one. */
1547                 if (name_end == NULL)
1548                         break;
1549
1550                 /* next segment please */
1551                 nameptr = name_end + 1;
1552                 num_entries++;
1553         }
1554
1555         if(num_entries == 0)
1556                 return;
1557
1558         if(( (*ppname_array) = (name_compare_entry *)malloc(
1559                                         (num_entries + 1) * sizeof(name_compare_entry))) == NULL) {
1560                 DEBUG(0,("set_namearray: malloc fail\n"));
1561                 return;
1562         }
1563
1564         /* Now copy out the names */
1565         nameptr = namelist;
1566         i = 0;
1567         while(*nameptr) {
1568                 if ( *nameptr == '/' ) {
1569                         /* cope with multiple (useless) /s) */
1570                         nameptr++;
1571                         continue;
1572                 }
1573                 /* find the next / */
1574                 if ((name_end = strchr_m(nameptr, '/')) != NULL)
1575                         *name_end = 0;
1576
1577                 /* oops - the last check for a / didn't find one. */
1578                 if(name_end == NULL) 
1579                         break;
1580
1581                 (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
1582                 if(((*ppname_array)[i].name = strdup(nameptr)) == NULL) {
1583                         DEBUG(0,("set_namearray: malloc fail (1)\n"));
1584                         return;
1585                 }
1586
1587                 /* next segment please */
1588                 nameptr = name_end + 1;
1589                 i++;
1590         }
1591   
1592         (*ppname_array)[i].name = NULL;
1593
1594         return;
1595 }
1596
1597 /****************************************************************************
1598  Routine to free a namearray.
1599 ****************************************************************************/
1600
1601 void free_namearray(name_compare_entry *name_array)
1602 {
1603         int i;
1604
1605         if(name_array == NULL)
1606                 return;
1607
1608         for(i=0; name_array[i].name!=NULL; i++)
1609                 SAFE_FREE(name_array[i].name);
1610         SAFE_FREE(name_array);
1611 }
1612
1613 /****************************************************************************
1614  Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
1615  is dealt with in posix.c
1616 ****************************************************************************/
1617
1618 BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
1619 {
1620         SMB_STRUCT_FLOCK lock;
1621         int ret;
1622
1623         DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
1624
1625         lock.l_type = type;
1626         lock.l_whence = SEEK_SET;
1627         lock.l_start = offset;
1628         lock.l_len = count;
1629         lock.l_pid = 0;
1630
1631         ret = sys_fcntl_ptr(fd,op,&lock);
1632
1633         if (ret == -1 && errno != 0)
1634                 DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
1635
1636         /* a lock query */
1637         if (op == SMB_F_GETLK) {
1638                 if ((ret != -1) &&
1639                                 (lock.l_type != F_UNLCK) && 
1640                                 (lock.l_pid != 0) && 
1641                                 (lock.l_pid != sys_getpid())) {
1642                         DEBUG(3,("fcntl_lock: fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
1643                         return(True);
1644                 }
1645
1646                 /* it must be not locked or locked by me */
1647                 return(False);
1648         }
1649
1650         /* a lock set or unset */
1651         if (ret == -1) {
1652                 DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
1653                         (double)offset,(double)count,op,type,strerror(errno)));
1654                 return(False);
1655         }
1656
1657         /* everything went OK */
1658         DEBUG(8,("fcntl_lock: Lock call successful\n"));
1659
1660         return(True);
1661 }
1662
1663 /*******************************************************************
1664  Is the name specified one of my netbios names.
1665  Returns true if it is equal, false otherwise.
1666 ********************************************************************/
1667
1668 BOOL is_myname(const char *s)
1669 {
1670         int n;
1671         BOOL ret = False;
1672
1673         for (n=0; my_netbios_names(n); n++) {
1674                 if (strequal(my_netbios_names(n), s)) {
1675                         ret=True;
1676                         break;
1677                 }
1678         }
1679         DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
1680         return(ret);
1681 }
1682
1683 /********************************************************************
1684  Return only the first IP address of our configured interfaces
1685  as a string
1686  *******************************************************************/
1687
1688 const char* get_my_primary_ip (void)
1689 {
1690         static fstring ip_string;
1691         int n;
1692         struct iface_struct nics[MAX_INTERFACES];
1693
1694         if ((n=get_interfaces(nics, MAX_INTERFACES)) <= 0)
1695                 return NULL;
1696
1697         fstrcpy(ip_string, inet_ntoa(nics[0].ip));
1698         return ip_string;
1699 }
1700
1701 BOOL is_myname_or_ipaddr(const char *s)
1702 {
1703         /* optimize for the common case */
1704         if (strequal(s, global_myname())) 
1705                 return True;
1706
1707         /* maybe its an IP address? */
1708         if (is_ipaddress(s)) {
1709                 struct iface_struct nics[MAX_INTERFACES];
1710                 int i, n;
1711                 uint32 ip;
1712                 
1713                 ip = interpret_addr(s);
1714                 if ((ip==0) || (ip==0xffffffff))
1715                         return False;
1716                         
1717                 n = get_interfaces(nics, MAX_INTERFACES);
1718                 for (i=0; i<n; i++) {
1719                         if (ip == nics[i].ip.s_addr)
1720                                 return True;
1721                 }
1722         }       
1723
1724         /* check for an alias */
1725         if (is_myname(s))
1726                 return True;
1727         
1728         /* no match */
1729         return False;
1730 }
1731
1732 /*******************************************************************
1733  Set the horrid remote_arch string based on an enum.
1734 ********************************************************************/
1735
1736 void set_remote_arch(enum remote_arch_types type)
1737 {
1738         extern fstring remote_arch;
1739         ra_type = type;
1740         switch( type ) {
1741         case RA_WFWG:
1742                 fstrcpy(remote_arch, "WfWg");
1743                 return;
1744         case RA_OS2:
1745                 fstrcpy(remote_arch, "OS2");
1746                 return;
1747         case RA_WIN95:
1748                 fstrcpy(remote_arch, "Win95");
1749                 return;
1750         case RA_WINNT:
1751                 fstrcpy(remote_arch, "WinNT");
1752                 return;
1753         case RA_WIN2K:
1754                 fstrcpy(remote_arch, "Win2K");
1755                 return;
1756         case RA_SAMBA:
1757                 fstrcpy(remote_arch,"Samba");
1758                 return;
1759         default:
1760                 ra_type = RA_UNKNOWN;
1761                 fstrcpy(remote_arch, "UNKNOWN");
1762                 break;
1763         }
1764 }
1765
1766 /*******************************************************************
1767  Get the remote_arch type.
1768 ********************************************************************/
1769
1770 enum remote_arch_types get_remote_arch(void)
1771 {
1772         return ra_type;
1773 }
1774
1775
1776 void out_ascii(FILE *f, unsigned char *buf,int len)
1777 {
1778         int i;
1779         for (i=0;i<len;i++)
1780                 fprintf(f, "%c", isprint(buf[i])?buf[i]:'.');
1781 }
1782
1783 void out_data(FILE *f,char *buf1,int len, int per_line)
1784 {
1785         unsigned char *buf = (unsigned char *)buf1;
1786         int i=0;
1787         if (len<=0) {
1788                 return;
1789         }
1790
1791         fprintf(f, "[%03X] ",i);
1792         for (i=0;i<len;) {
1793                 fprintf(f, "%02X ",(int)buf[i]);
1794                 i++;
1795                 if (i%(per_line/2) == 0) fprintf(f, " ");
1796                 if (i%per_line == 0) {      
1797                         out_ascii(f,&buf[i-per_line  ],per_line/2); fprintf(f, " ");
1798                         out_ascii(f,&buf[i-per_line/2],per_line/2); fprintf(f, "\n");
1799                         if (i<len) fprintf(f, "[%03X] ",i);
1800                 }
1801         }
1802         if ((i%per_line) != 0) {
1803                 int n;
1804
1805                 n = per_line - (i%per_line);
1806                 fprintf(f, " ");
1807                 if (n>(per_line/2)) fprintf(f, " ");
1808                 while (n--) {
1809                         fprintf(f, "   ");
1810                 }
1811                 n = MIN(per_line/2,i%per_line);
1812                 out_ascii(f,&buf[i-(i%per_line)],n); fprintf(f, " ");
1813                 n = (i%per_line) - n;
1814                 if (n>0) out_ascii(f,&buf[i-n],n); 
1815                 fprintf(f, "\n");    
1816         }
1817 }
1818
1819 void print_asc(int level, const unsigned char *buf,int len)
1820 {
1821         int i;
1822         for (i=0;i<len;i++)
1823                 DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
1824 }
1825
1826 void dump_data(int level, const char *buf1,int len)
1827 {
1828         const unsigned char *buf = (const unsigned char *)buf1;
1829         int i=0;
1830         if (len<=0) return;
1831
1832         if (!DEBUGLVL(level)) return;
1833         
1834         DEBUGADD(level,("[%03X] ",i));
1835         for (i=0;i<len;) {
1836                 DEBUGADD(level,("%02X ",(int)buf[i]));
1837                 i++;
1838                 if (i%8 == 0) DEBUGADD(level,(" "));
1839                 if (i%16 == 0) {      
1840                         print_asc(level,&buf[i-16],8); DEBUGADD(level,(" "));
1841                         print_asc(level,&buf[i-8],8); DEBUGADD(level,("\n"));
1842                         if (i<len) DEBUGADD(level,("[%03X] ",i));
1843                 }
1844         }
1845         if (i%16) {
1846                 int n;
1847                 n = 16 - (i%16);
1848                 DEBUGADD(level,(" "));
1849                 if (n>8) DEBUGADD(level,(" "));
1850                 while (n--) DEBUGADD(level,("   "));
1851                 n = MIN(8,i%16);
1852                 print_asc(level,&buf[i-(i%16)],n); DEBUGADD(level,( " " ));
1853                 n = (i%16) - n;
1854                 if (n>0) print_asc(level,&buf[i-n],n); 
1855                 DEBUGADD(level,("\n"));    
1856         }       
1857 }
1858
1859 char *tab_depth(int depth)
1860 {
1861         static pstring spaces;
1862         memset(spaces, ' ', depth * 4);
1863         spaces[depth * 4] = 0;
1864         return spaces;
1865 }
1866
1867 /*****************************************************************************
1868  Provide a checksum on a string
1869
1870  Input:  s - the null-terminated character string for which the checksum
1871              will be calculated.
1872
1873   Output: The checksum value calculated for s.
1874 *****************************************************************************/
1875
1876 int str_checksum(const char *s)
1877 {
1878         int res = 0;
1879         int c;
1880         int i=0;
1881         
1882         while(*s) {
1883                 c = *s;
1884                 res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
1885                 s++;
1886                 i++;
1887         }
1888         return(res);
1889 }
1890
1891 /*****************************************************************
1892  Zero a memory area then free it. Used to catch bugs faster.
1893 *****************************************************************/  
1894
1895 void zero_free(void *p, size_t size)
1896 {
1897         memset(p, 0, size);
1898         SAFE_FREE(p);
1899 }
1900
1901 /*****************************************************************
1902  Set our open file limit to a requested max and return the limit.
1903 *****************************************************************/  
1904
1905 int set_maxfiles(int requested_max)
1906 {
1907 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
1908         struct rlimit rlp;
1909         int saved_current_limit;
1910
1911         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1912                 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
1913                         strerror(errno) ));
1914                 /* just guess... */
1915                 return requested_max;
1916         }
1917
1918         /* 
1919          * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
1920          * account for the extra fd we need 
1921          * as well as the log files and standard
1922          * handles etc. Save the limit we want to set in case
1923          * we are running on an OS that doesn't support this limit (AIX)
1924          * which always returns RLIM_INFINITY for rlp.rlim_max.
1925          */
1926
1927         /* Try raising the hard (max) limit to the requested amount. */
1928
1929 #if defined(RLIM_INFINITY)
1930         if (rlp.rlim_max != RLIM_INFINITY) {
1931                 int orig_max = rlp.rlim_max;
1932
1933                 if ( rlp.rlim_max < requested_max )
1934                         rlp.rlim_max = requested_max;
1935
1936                 /* This failing is not an error - many systems (Linux) don't
1937                         support our default request of 10,000 open files. JRA. */
1938
1939                 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1940                         DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n", 
1941                                 (int)rlp.rlim_max, strerror(errno) ));
1942
1943                         /* Set failed - restore original value from get. */
1944                         rlp.rlim_max = orig_max;
1945                 }
1946         }
1947 #endif
1948
1949         /* Now try setting the soft (current) limit. */
1950
1951         saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
1952
1953         if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1954                 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n", 
1955                         (int)rlp.rlim_cur, strerror(errno) ));
1956                 /* just guess... */
1957                 return saved_current_limit;
1958         }
1959
1960         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1961                 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
1962                         strerror(errno) ));
1963                 /* just guess... */
1964                 return saved_current_limit;
1965     }
1966
1967 #if defined(RLIM_INFINITY)
1968         if(rlp.rlim_cur == RLIM_INFINITY)
1969                 return saved_current_limit;
1970 #endif
1971
1972         if((int)rlp.rlim_cur > saved_current_limit)
1973                 return saved_current_limit;
1974
1975         return rlp.rlim_cur;
1976 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
1977         /*
1978          * No way to know - just guess...
1979          */
1980         return requested_max;
1981 #endif
1982 }
1983
1984 /*****************************************************************
1985  Splits out the start of the key (HKLM or HKU) and the rest of the key.
1986 *****************************************************************/  
1987
1988 BOOL reg_split_key(const char *full_keyname, uint32 *reg_type, char *key_name)
1989 {
1990         pstring tmp;
1991
1992         if (!next_token(&full_keyname, tmp, "\\", sizeof(tmp)))
1993                 return False;
1994
1995         (*reg_type) = 0;
1996
1997         DEBUG(10, ("reg_split_key: hive %s\n", tmp));
1998
1999         if (strequal(tmp, "HKLM") || strequal(tmp, "HKEY_LOCAL_MACHINE"))
2000                 (*reg_type) = HKEY_LOCAL_MACHINE;
2001         else if (strequal(tmp, "HKU") || strequal(tmp, "HKEY_USERS"))
2002                 (*reg_type) = HKEY_USERS;
2003         else {
2004                 DEBUG(10,("reg_split_key: unrecognised hive key %s\n", tmp));
2005                 return False;
2006         }
2007         
2008         if (next_token(&full_keyname, tmp, "\n\r", sizeof(tmp)))
2009                 fstrcpy(key_name, tmp);
2010         else
2011                 key_name[0] = 0;
2012
2013         DEBUG(10, ("reg_split_key: name %s\n", key_name));
2014
2015         return True;
2016 }
2017
2018 /*****************************************************************
2019  Possibly replace mkstemp if it is broken.
2020 *****************************************************************/  
2021
2022 int smb_mkstemp(char *template)
2023 {
2024 #if HAVE_SECURE_MKSTEMP
2025         return mkstemp(template);
2026 #else
2027         /* have a reasonable go at emulating it. Hope that
2028            the system mktemp() isn't completly hopeless */
2029         char *p = mktemp(template);
2030         if (!p)
2031                 return -1;
2032         return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
2033 #endif
2034 }
2035
2036 /*****************************************************************
2037  malloc that aborts with smb_panic on fail or zero size.
2038  *****************************************************************/  
2039
2040 void *smb_xmalloc(size_t size)
2041 {
2042         void *p;
2043         if (size == 0)
2044                 smb_panic("smb_xmalloc: called with zero size.\n");
2045         if ((p = malloc(size)) == NULL)
2046                 smb_panic("smb_xmalloc: malloc fail.\n");
2047         return p;
2048 }
2049
2050 /**
2051  Memdup with smb_panic on fail.
2052 **/
2053
2054 void *smb_xmemdup(const void *p, size_t size)
2055 {
2056         void *p2;
2057         p2 = smb_xmalloc(size);
2058         memcpy(p2, p, size);
2059         return p2;
2060 }
2061
2062 /**
2063  strdup that aborts on malloc fail.
2064 **/
2065
2066 char *smb_xstrdup(const char *s)
2067 {
2068         char *s1 = strdup(s);
2069         if (!s1)
2070                 smb_panic("smb_xstrdup: malloc fail\n");
2071         return s1;
2072 }
2073
2074 /**
2075  strndup that aborts on malloc fail.
2076 **/
2077
2078 char *smb_xstrndup(const char *s, size_t n)
2079 {
2080         char *s1 = strndup(s, n);
2081         if (!s1)
2082                 smb_panic("smb_xstrndup: malloc fail\n");
2083         return s1;
2084 }
2085
2086 /*
2087   vasprintf that aborts on malloc fail
2088 */
2089
2090  int smb_xvasprintf(char **ptr, const char *format, va_list ap)
2091 {
2092         int n;
2093         va_list ap2;
2094
2095         VA_COPY(ap2, ap);
2096
2097         n = vasprintf(ptr, format, ap2);
2098         if (n == -1 || ! *ptr)
2099                 smb_panic("smb_xvasprintf: out of memory");
2100         return n;
2101 }
2102
2103 /*****************************************************************
2104  Like strdup but for memory.
2105 *****************************************************************/  
2106
2107 void *memdup(const void *p, size_t size)
2108 {
2109         void *p2;
2110         if (size == 0)
2111                 return NULL;
2112         p2 = malloc(size);
2113         if (!p2)
2114                 return NULL;
2115         memcpy(p2, p, size);
2116         return p2;
2117 }
2118
2119 /*****************************************************************
2120  Get local hostname and cache result.
2121 *****************************************************************/  
2122
2123 char *myhostname(void)
2124 {
2125         static pstring ret;
2126         if (ret[0] == 0)
2127                 get_myname(ret);
2128         return ret;
2129 }
2130
2131 /*****************************************************************
2132  A useful function for returning a path in the Samba lock directory.
2133 *****************************************************************/  
2134
2135 char *lock_path(const char *name)
2136 {
2137         static pstring fname;
2138
2139         pstrcpy(fname,lp_lockdir());
2140         trim_string(fname,"","/");
2141         
2142         if (!directory_exist(fname,NULL))
2143                 mkdir(fname,0755);
2144         
2145         pstrcat(fname,"/");
2146         pstrcat(fname,name);
2147
2148         return fname;
2149 }
2150
2151 /*****************************************************************
2152  A useful function for returning a path in the Samba pid directory.
2153 *****************************************************************/
2154
2155 char *pid_path(const char *name)
2156 {
2157         static pstring fname;
2158
2159         pstrcpy(fname,lp_piddir());
2160         trim_string(fname,"","/");
2161
2162         if (!directory_exist(fname,NULL))
2163                 mkdir(fname,0755);
2164
2165         pstrcat(fname,"/");
2166         pstrcat(fname,name);
2167
2168         return fname;
2169 }
2170
2171 /**
2172  * @brief Returns an absolute path to a file in the Samba lib directory.
2173  *
2174  * @param name File to find, relative to LIBDIR.
2175  *
2176  * @retval Pointer to a static #pstring containing the full path.
2177  **/
2178
2179 char *lib_path(const char *name)
2180 {
2181         static pstring fname;
2182         snprintf(fname, sizeof(fname), "%s/%s", dyn_LIBDIR, name);
2183         return fname;
2184 }
2185
2186 /**
2187  * @brief Returns the platform specific shared library extension.
2188  *
2189  * @retval Pointer to a static #fstring containing the extension.
2190  **/
2191
2192 const char *shlib_ext(void)
2193 {
2194   return dyn_SHLIBEXT;
2195 }
2196
2197 /*******************************************************************
2198  Given a filename - get its directory name
2199  NB: Returned in static storage.  Caveats:
2200  o  Not safe in thread environment.
2201  o  Caller must not free.
2202  o  If caller wishes to preserve, they should copy.
2203 ********************************************************************/
2204
2205 char *parent_dirname(const char *path)
2206 {
2207         static pstring dirpath;
2208         char *p;
2209
2210         if (!path)
2211                 return(NULL);
2212
2213         pstrcpy(dirpath, path);
2214         p = strrchr_m(dirpath, '/');  /* Find final '/', if any */
2215         if (!p) {
2216                 pstrcpy(dirpath, ".");    /* No final "/", so dir is "." */
2217         } else {
2218                 if (p == dirpath)
2219                         ++p;    /* For root "/", leave "/" in place */
2220                 *p = '\0';
2221         }
2222         return dirpath;
2223 }
2224
2225
2226 /*******************************************************************
2227  Determine if a pattern contains any Microsoft wildcard characters.
2228 *******************************************************************/
2229
2230 BOOL ms_has_wild(char *s)
2231 {
2232         char c;
2233         while ((c = *s++)) {
2234                 switch (c) {
2235                 case '*':
2236                 case '?':
2237                 case '<':
2238                 case '>':
2239                 case '"':
2240                         return True;
2241                 }
2242         }
2243         return False;
2244 }
2245
2246 BOOL ms_has_wild_w(const smb_ucs2_t *s)
2247 {
2248         smb_ucs2_t c;
2249         if (!s) return False;
2250         while ((c = *s++)) {
2251                 switch (c) {
2252                 case UCS2_CHAR('*'):
2253                 case UCS2_CHAR('?'):
2254                 case UCS2_CHAR('<'):
2255                 case UCS2_CHAR('>'):
2256                 case UCS2_CHAR('"'):
2257                         return True;
2258                 }
2259         }
2260         return False;
2261 }
2262
2263 /*******************************************************************
2264  A wrapper that handles case sensitivity and the special handling
2265  of the ".." name.
2266 *******************************************************************/
2267
2268 BOOL mask_match(const char *string, char *pattern, BOOL is_case_sensitive)
2269 {
2270         fstring p2, s2;
2271
2272         if (strcmp(string,"..") == 0)
2273                 string = ".";
2274         if (strcmp(pattern,".") == 0)
2275                 return False;
2276         
2277         if (is_case_sensitive)
2278                 return ms_fnmatch(pattern, string, Protocol) == 0;
2279
2280         fstrcpy(p2, pattern);
2281         fstrcpy(s2, string);
2282         strlower(p2); 
2283         strlower(s2);
2284         return ms_fnmatch(p2, s2, Protocol) == 0;
2285 }
2286
2287 /*********************************************************
2288  Recursive routine that is called by unix_wild_match.
2289 *********************************************************/
2290
2291 static BOOL unix_do_match(char *regexp, char *str)
2292 {
2293         char *p;
2294
2295         for( p = regexp; *p && *str; ) {
2296
2297                 switch(*p) {
2298                         case '?':
2299                                 str++;
2300                                 p++;
2301                                 break;
2302
2303                         case '*':
2304
2305                                 /*
2306                                  * Look for a character matching 
2307                                  * the one after the '*'.
2308                                  */
2309                                 p++;
2310                                 if(!*p)
2311                                         return True; /* Automatic match */
2312                                 while(*str) {
2313
2314                                         while(*str && (*p != *str))
2315                                                 str++;
2316
2317                                         /*
2318                                          * Patch from weidel@multichart.de. In the case of the regexp
2319                                          * '*XX*' we want to ensure there are at least 2 'X' characters
2320                                          * in the string after the '*' for a match to be made.
2321                                          */
2322
2323                                         {
2324                                                 int matchcount=0;
2325
2326                                                 /*
2327                                                  * Eat all the characters that match, but count how many there were.
2328                                                  */
2329
2330                                                 while(*str && (*p == *str)) {
2331                                                         str++;
2332                                                         matchcount++;
2333                                                 }
2334
2335                                                 /*
2336                                                  * Now check that if the regexp had n identical characters that
2337                                                  * matchcount had at least that many matches.
2338                                                  */
2339
2340                                                 while ( *(p+1) && (*(p+1) == *p)) {
2341                                                         p++;
2342                                                         matchcount--;
2343                                                 }
2344
2345                                                 if ( matchcount <= 0 )
2346                                                         return False;
2347                                         }
2348
2349                                         str--; /* We've eaten the match char after the '*' */
2350
2351                                         if(unix_do_match(p, str))
2352                                                 return True;
2353
2354                                         if(!*str)
2355                                                 return False;
2356                                         else
2357                                                 str++;
2358                                 }
2359                                 return False;
2360
2361                         default:
2362                                 if(*str != *p)
2363                                         return False;
2364                                 str++;
2365                                 p++;
2366                                 break;
2367                 }
2368         }
2369
2370         if(!*p && !*str)
2371                 return True;
2372
2373         if (!*p && str[0] == '.' && str[1] == 0)
2374                 return(True);
2375   
2376         if (!*str && *p == '?') {
2377                 while (*p == '?')
2378                         p++;
2379                 return(!*p);
2380         }
2381
2382         if(!*str && (*p == '*' && p[1] == '\0'))
2383                 return True;
2384
2385         return False;
2386 }
2387
2388 /*******************************************************************
2389  Simple case insensitive interface to a UNIX wildcard matcher.
2390 *******************************************************************/
2391
2392 BOOL unix_wild_match(char *pattern, char *string)
2393 {
2394         pstring p2, s2;
2395         char *p;
2396
2397         pstrcpy(p2, pattern);
2398         pstrcpy(s2, string);
2399         strlower(p2);
2400         strlower(s2);
2401
2402         /* Remove any *? and ** from the pattern as they are meaningless */
2403         for(p = p2; *p; p++)
2404                 while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
2405                         pstrcpy( &p[1], &p[2]);
2406  
2407         if (strequal(p2,"*"))
2408                 return True;
2409
2410         return unix_do_match(p2, s2) == 0;      
2411 }
2412
2413 #ifdef __INSURE__
2414
2415 /*******************************************************************
2416 This routine is a trick to immediately catch errors when debugging
2417 with insure. A xterm with a gdb is popped up when insure catches
2418 a error. It is Linux specific.
2419 ********************************************************************/
2420
2421 int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
2422 {
2423         static int (*fn)();
2424         int ret;
2425         char pidstr[10];
2426         /* you can get /usr/bin/backtrace from 
2427            http://samba.org/ftp/unpacked/junkcode/backtrace */
2428         pstring cmd = "/usr/bin/backtrace %d";
2429
2430         slprintf(pidstr, sizeof(pidstr)-1, "%d", sys_getpid());
2431         pstring_sub(cmd, "%d", pidstr);
2432
2433         if (!fn) {
2434                 static void *h;
2435                 h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
2436                 fn = dlsym(h, "_Insure_trap_error");
2437
2438                 if (!h || h == _Insure_trap_error) {
2439                         h = dlopen("/usr/local/parasoft/lib.linux2/libinsure.so", RTLD_LAZY);
2440                         fn = dlsym(h, "_Insure_trap_error");
2441                 }               
2442         }
2443
2444         ret = fn(a1, a2, a3, a4, a5, a6);
2445
2446         system(cmd);
2447
2448         return ret;
2449 }
2450 #endif