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