r943: change samba4 to use 'uint8_t' instead of 'unsigned char'
[ira/wip.git] / source4 / 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    Copyright (C) James J Myers 2003
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26
27 /**************************************************************************n
28  Find a suitable temporary directory. The result should be copied immediately
29  as it may be overwritten by a subsequent call.
30 ****************************************************************************/
31
32 const char *tmpdir(void)
33 {
34         char *p;
35         if ((p = getenv("TMPDIR")))
36                 return p;
37         return "/tmp";
38 }
39
40 /****************************************************************************
41  Determine whether we are in the specified group.
42 ****************************************************************************/
43
44 BOOL in_group(gid_t group, gid_t current_gid, int ngroups, const gid_t *groups)
45 {
46         int i;
47
48         if (group == current_gid)
49                 return(True);
50
51         for (i=0;i<ngroups;i++)
52                 if (group == groups[i])
53                         return(True);
54
55         return(False);
56 }
57
58 /*******************************************************************
59  Check if a file exists - call vfs_file_exist for samba files.
60 ********************************************************************/
61
62 BOOL file_exist(const char *fname,SMB_STRUCT_STAT *sbuf)
63 {
64         SMB_STRUCT_STAT st;
65         if (!sbuf)
66                 sbuf = &st;
67   
68         if (sys_stat(fname,sbuf) != 0) 
69                 return(False);
70
71         return((S_ISREG(sbuf->st_mode)) || (S_ISFIFO(sbuf->st_mode)));
72 }
73
74 /*******************************************************************
75  Check a files mod time.
76 ********************************************************************/
77
78 time_t file_modtime(const char *fname)
79 {
80         SMB_STRUCT_STAT st;
81   
82         if (sys_stat(fname,&st) != 0) 
83                 return(0);
84
85         return(st.st_mtime);
86 }
87
88 /*******************************************************************
89  Check if a directory exists.
90 ********************************************************************/
91
92 BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st)
93 {
94         SMB_STRUCT_STAT st2;
95         BOOL ret;
96
97         if (!st)
98                 st = &st2;
99
100         if (sys_stat(dname,st) != 0) 
101                 return(False);
102
103         ret = S_ISDIR(st->st_mode);
104         if(!ret)
105                 errno = ENOTDIR;
106         return ret;
107 }
108
109 /*******************************************************************
110  Returns the size in bytes of the named file.
111 ********************************************************************/
112 SMB_OFF_T get_file_size(char *file_name)
113 {
114         SMB_STRUCT_STAT buf;
115         buf.st_size = 0;
116         if(sys_stat(file_name,&buf) != 0)
117                 return (SMB_OFF_T)-1;
118         return(buf.st_size);
119 }
120
121 /*******************************************************************
122  Close the low 3 fd's and open dev/null in their place.
123 ********************************************************************/
124 void close_low_fds(BOOL stderr_too)
125 {
126 #ifndef VALGRIND
127         int fd;
128         int i;
129
130         close(0);
131         close(1); 
132
133         if (stderr_too)
134                 close(2);
135
136         /* try and use up these file descriptors, so silly
137                 library routines writing to stdout etc won't cause havoc */
138         for (i=0;i<3;i++) {
139                 if (i == 2 && !stderr_too)
140                         continue;
141
142                 fd = sys_open("/dev/null",O_RDWR,0);
143                 if (fd < 0)
144                         fd = sys_open("/dev/null",O_WRONLY,0);
145                 if (fd < 0) {
146                         DEBUG(0,("Can't open /dev/null\n"));
147                         return;
148                 }
149                 if (fd != i) {
150                         DEBUG(0,("Didn't get file descriptor %d\n",i));
151                         return;
152                 }
153         }
154 #endif
155 }
156
157 /****************************************************************************
158  Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
159  else
160   if SYSV use O_NDELAY
161   if BSD use FNDELAY
162 ****************************************************************************/
163
164 int set_blocking(int fd, BOOL set)
165 {
166         int val;
167 #ifdef O_NONBLOCK
168 #define FLAG_TO_SET O_NONBLOCK
169 #else
170 #ifdef SYSV
171 #define FLAG_TO_SET O_NDELAY
172 #else /* BSD */
173 #define FLAG_TO_SET FNDELAY
174 #endif
175 #endif
176
177         if((val = sys_fcntl_long(fd, F_GETFL, 0)) == -1)
178                 return -1;
179         if(set) /* Turn blocking on - ie. clear nonblock flag */
180                 val &= ~FLAG_TO_SET;
181         else
182                 val |= FLAG_TO_SET;
183         return sys_fcntl_long( fd, F_SETFL, val);
184 #undef FLAG_TO_SET
185 }
186
187
188 /*******************************************************************
189  Sleep for a specified number of milliseconds.
190 ********************************************************************/
191
192 void msleep(unsigned int t)
193 {
194         struct timeval tval;  
195
196         tval.tv_sec = t/1000;
197         tval.tv_usec = 1000*(t%1000);
198         /* this should be the real select - do NOT replace
199            with sys_select() */
200         select(0,NULL,NULL,NULL,&tval);
201 }
202
203 /****************************************************************************
204  Become a daemon, discarding the controlling terminal.
205 ****************************************************************************/
206
207 void become_daemon(BOOL Fork)
208 {
209         if (Fork) {
210                 if (fork()) {
211                         _exit(0);
212                 }
213         }
214
215   /* detach from the terminal */
216 #ifdef HAVE_SETSID
217         setsid();
218 #elif defined(TIOCNOTTY)
219         {
220                 int i = sys_open("/dev/tty", O_RDWR, 0);
221                 if (i != -1) {
222                         ioctl(i, (int) TIOCNOTTY, (char *)0);      
223                         close(i);
224                 }
225         }
226 #endif /* HAVE_SETSID */
227
228         /* Close fd's 0,1,2. Needed if started by rsh */
229         close_low_fds(False);  /* Don't close stderr, let the debug system
230                                   attach it to the logfile */
231 }
232
233
234 /****************************************************************************
235  Expand a pointer to be a particular size.
236 ****************************************************************************/
237
238 void *Realloc(void *p,size_t size)
239 {
240         void *ret=NULL;
241
242         if (size == 0) {
243                 SAFE_FREE(p);
244                 DEBUG(5,("Realloc asked for 0 bytes\n"));
245                 return NULL;
246         }
247
248         if (!p)
249                 ret = (void *)malloc(size);
250         else
251                 ret = (void *)realloc(p,size);
252
253         if (!ret)
254                 DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size));
255
256         return(ret);
257 }
258
259 /****************************************************************************
260  Free memory, checks for NULL.
261  Use directly SAFE_FREE()
262  Exists only because we need to pass a function pointer somewhere --SSS
263 ****************************************************************************/
264
265 void safe_free(void *p)
266 {
267         SAFE_FREE(p);
268 }
269
270
271 /*
272   see if a string matches either our primary or one of our secondary 
273   netbios aliases. do a case insensitive match
274 */
275 BOOL is_myname(const char *name)
276 {
277         const char **aliases;
278         int i;
279
280         if (strcasecmp(name, lp_netbios_name()) == 0) {
281                 return True;
282         }
283
284         aliases = lp_netbios_aliases();
285         for (i=0; aliases && aliases[i]; i++) {
286                 if (strcasecmp(name, aliases[i]) == 0) {
287                         return True;
288                 }
289         }
290
291         return False;
292 }
293
294
295 /****************************************************************************
296  Get my own name, return in malloc'ed storage.
297 ****************************************************************************/
298
299 char* get_myname(void)
300 {
301         char *hostname;
302         const int host_name_max = 255;
303         char *p;
304
305         hostname = malloc(host_name_max+1);
306         *hostname = 0;
307
308         /* get my host name */
309         if (gethostname(hostname, host_name_max+1) == -1) {
310                 DEBUG(0,("gethostname failed\n"));
311                 return NULL;
312         } 
313
314         /* Ensure null termination. */
315         hostname[host_name_max] = '\0';
316
317         /* split off any parts after an initial . */
318         p = strchr_m(hostname,'.');
319
320         if (p)
321                 *p = 0;
322         
323         return hostname;
324 }
325
326 /****************************************************************************
327  Get my own name, including domain.
328 ****************************************************************************/
329
330 BOOL get_myfullname(char *my_name)
331 {
332         pstring hostname;
333
334         *hostname = 0;
335
336         /* get my host name */
337         if (gethostname(hostname, sizeof(hostname)) == -1) {
338                 DEBUG(0,("gethostname failed\n"));
339                 return False;
340         } 
341
342         /* Ensure null termination. */
343         hostname[sizeof(hostname)-1] = '\0';
344
345         if (my_name)
346                 fstrcpy(my_name, hostname);
347         return True;
348 }
349
350 /****************************************************************************
351  Get my own domain name.
352 ****************************************************************************/
353
354 BOOL get_mydomname(fstring my_domname)
355 {
356         pstring hostname;
357         char *p;
358
359         *hostname = 0;
360         /* get my host name */
361         if (gethostname(hostname, sizeof(hostname)) == -1) {
362                 DEBUG(0,("gethostname failed\n"));
363                 return False;
364         } 
365
366         /* Ensure null termination. */
367         hostname[sizeof(hostname)-1] = '\0';
368
369         p = strchr_m(hostname, '.');
370
371         if (!p)
372                 return False;
373
374         p++;
375         
376         if (my_domname)
377                 fstrcpy(my_domname, p);
378
379         return True;
380 }
381
382 /****************************************************************************
383  Interpret a protocol description string, with a default.
384 ****************************************************************************/
385
386 int interpret_protocol(char *str,int def)
387 {
388         if (strequal(str,"NT1"))
389                 return(PROTOCOL_NT1);
390         if (strequal(str,"LANMAN2"))
391                 return(PROTOCOL_LANMAN2);
392         if (strequal(str,"LANMAN1"))
393                 return(PROTOCOL_LANMAN1);
394         if (strequal(str,"CORE"))
395                 return(PROTOCOL_CORE);
396         if (strequal(str,"COREPLUS"))
397                 return(PROTOCOL_COREPLUS);
398         if (strequal(str,"CORE+"))
399                 return(PROTOCOL_COREPLUS);
400   
401         DEBUG(0,("Unrecognised protocol level %s\n",str));
402   
403         return(def);
404 }
405
406 /****************************************************************************
407  Return true if a string could be a pure IP address.
408 ****************************************************************************/
409
410 BOOL is_ipaddress(const char *str)
411 {
412         BOOL pure_address = True;
413         int i;
414   
415         for (i=0; pure_address && str[i]; i++)
416                 if (!(isdigit((int)str[i]) || str[i] == '.'))
417                         pure_address = False;
418
419         /* Check that a pure number is not misinterpreted as an IP */
420         pure_address = pure_address && (strchr_m(str, '.') != NULL);
421
422         return pure_address;
423 }
424
425 /****************************************************************************
426  Interpret an internet address or name into an IP address in 4 byte form.
427 ****************************************************************************/
428
429 uint32_t interpret_addr(const char *str)
430 {
431         struct hostent *hp;
432         uint32_t res;
433
434         if (strcmp(str,"0.0.0.0") == 0)
435                 return(0);
436         if (strcmp(str,"255.255.255.255") == 0)
437                 return(0xFFFFFFFF);
438
439         /* if it's in the form of an IP address then get the lib to interpret it */
440         if (is_ipaddress(str)) {
441                 res = inet_addr(str);
442         } else {
443                 /* otherwise assume it's a network name of some sort and use 
444                         sys_gethostbyname */
445                 if ((hp = sys_gethostbyname(str)) == 0) {
446                         DEBUG(3,("sys_gethostbyname: Unknown host. %s\n",str));
447                         return 0;
448                 }
449
450                 if(hp->h_addr == NULL) {
451                         DEBUG(3,("sys_gethostbyname: host address is invalid for host %s\n",str));
452                         return 0;
453                 }
454                 putip((char *)&res,(char *)hp->h_addr);
455         }
456
457         if (res == (uint32_t)-1)
458                 return(0);
459
460         return(res);
461 }
462
463 /*******************************************************************
464  A convenient addition to interpret_addr().
465 ******************************************************************/
466
467 struct in_addr *interpret_addr2(TALLOC_CTX *mem_ctx, const char *str)
468 {
469         struct in_addr *ret;
470         uint32_t a = interpret_addr(str);
471         
472         ret = talloc(mem_ctx, sizeof(struct in_addr));
473         if (!ret) return NULL;
474         ret->s_addr = a;
475         return(ret);
476 }
477
478 /*******************************************************************
479  Check if an IP is the 0.0.0.0.
480 ******************************************************************/
481
482 BOOL is_zero_ip(struct in_addr ip)
483 {
484         uint32_t a;
485         putip((char *)&a,(char *)&ip);
486         return(a == 0);
487 }
488
489 /*******************************************************************
490  Set an IP to 0.0.0.0.
491 ******************************************************************/
492
493 void zero_ip(struct in_addr *ip)
494 {
495         *ip = inet_makeaddr(0,0);
496         return;
497 }
498
499
500 /*******************************************************************
501  Are two IPs on the same subnet?
502 ********************************************************************/
503
504 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
505 {
506         uint32_t net1,net2,nmask;
507
508         nmask = ntohl(mask.s_addr);
509         net1  = ntohl(ip1.s_addr);
510         net2  = ntohl(ip2.s_addr);
511             
512         return((net1 & nmask) == (net2 & nmask));
513 }
514
515
516 /****************************************************************************
517  Check if a process exists. Does this work on all unixes?
518 ****************************************************************************/
519
520 BOOL process_exists(pid_t pid)
521 {
522         /* Doing kill with a non-positive pid causes messages to be
523          * sent to places we don't want. */
524         SMB_ASSERT(pid > 0);
525         return(kill(pid,0) == 0 || errno != ESRCH);
526 }
527
528 /*******************************************************************
529  Convert a gid into a group name.
530 ********************************************************************/
531
532 char *gidtoname(TALLOC_CTX *mem_ctx, gid_t gid)
533 {
534         char *name;
535         struct group *grp;
536
537         grp = getgrgid(gid);
538         if (grp)
539                 return(grp->gr_name);
540         name = talloc_asprintf(mem_ctx, "%d",(int)gid);
541         return(name);
542 }
543
544
545 /*******************************************************************
546  Convert a name to a gid_t if possible. Return -1 if not a group. 
547 ********************************************************************/
548
549 gid_t nametogid(const char *name)
550 {
551         struct group *grp;
552         char *p;
553         gid_t g;
554
555         g = (gid_t)strtol(name, &p, 0);
556         if ((p != name) && (*p == '\0'))
557                 return g;
558
559         grp = sys_getgrnam(name);
560         if (grp)
561                 return(grp->gr_gid);
562         return (gid_t)-1;
563 }
564
565 /*******************************************************************
566  Something really nasty happened - panic !
567 ********************************************************************/
568
569 void smb_panic(const char *why)
570 {
571         char *cmd = lp_panic_action();
572         int result;
573
574         if (cmd && *cmd) {
575                 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
576                 result = system(cmd);
577
578                 if (result == -1)
579                         DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
580                                   strerror(errno)));
581                 else
582                         DEBUG(0, ("smb_panic(): action returned status %d\n",
583                                   WEXITSTATUS(result)));
584         }
585         DEBUG(0,("PANIC: %s\n", why));
586         abort();
587 }
588
589 /****************************************************************************
590  Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
591  is dealt with in posix.c
592 ****************************************************************************/
593
594 BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
595 {
596         SMB_STRUCT_FLOCK lock;
597         int ret;
598
599         DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
600
601         lock.l_type = type;
602         lock.l_whence = SEEK_SET;
603         lock.l_start = offset;
604         lock.l_len = count;
605         lock.l_pid = 0;
606
607         ret = sys_fcntl_ptr(fd,op,&lock);
608
609         if (ret == -1 && errno != 0)
610                 DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
611
612         /* a lock query */
613         if (op == SMB_F_GETLK) {
614                 if ((ret != -1) &&
615                                 (lock.l_type != F_UNLCK) && 
616                                 (lock.l_pid != 0) && 
617                                 (lock.l_pid != getpid())) {
618                         DEBUG(3,("fcntl_lock: fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
619                         return(True);
620                 }
621
622                 /* it must be not locked or locked by me */
623                 return(False);
624         }
625
626         /* a lock set or unset */
627         if (ret == -1) {
628                 DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
629                         (double)offset,(double)count,op,type,strerror(errno)));
630                 return(False);
631         }
632
633         /* everything went OK */
634         DEBUG(8,("fcntl_lock: Lock call successful\n"));
635
636         return(True);
637 }
638
639 /*******************************************************************
640  Set the remote_arch string based on an enum. This is used in places
641 where we desperately need to distinguish client type. 
642 ********************************************************************/
643 void set_remote_arch(struct server_context *smb, enum remote_arch_types type)
644 {
645         const char *arch;
646
647         smb->negotiate.ra_type = type;
648         switch (type) {
649         case RA_WFWG:
650                 arch = "WfWg";
651                 return;
652         case RA_OS2:
653                 arch = "OS2";
654                 return;
655         case RA_WIN95:
656                 arch = "Win95";
657                 return;
658         case RA_WINNT:
659                 arch = "WinNT";
660                 return;
661         case RA_WIN2K:
662                 arch = "Win2K";
663                 return;
664         case RA_WINXP:
665                 arch = "WinXP";
666                 return;
667         case RA_SAMBA:
668                 arch = "Samba";
669                 return;
670         default:
671                 smb->negotiate.ra_type = RA_UNKNOWN;
672                 arch = "UNKNOWN";
673                 break;
674         }
675
676         sub_set_remote_arch(arch);
677 }
678
679
680 void print_asc(int level, const uint8_t *buf,int len)
681 {
682         int i;
683         for (i=0;i<len;i++)
684                 DEBUGADD(level,("%c", isprint(buf[i])?buf[i]:'.'));
685 }
686
687 void dump_data(int level, const char *buf1,int len)
688 {
689         const uint8_t *buf = (const uint8_t *)buf1;
690         int i=0;
691         if (len<=0) return;
692
693         if (!DEBUGLVL(level)) return;
694         
695         DEBUGADD(level,("[%03X] ",i));
696         for (i=0;i<len;) {
697                 DEBUGADD(level,("%02X ",(int)buf[i]));
698                 i++;
699                 if (i%8 == 0) DEBUGADD(level,(" "));
700                 if (i%16 == 0) {      
701                         print_asc(level,&buf[i-16],8); DEBUGADD(level,(" "));
702                         print_asc(level,&buf[i-8],8); DEBUGADD(level,("\n"));
703                         if (i<len) DEBUGADD(level,("[%03X] ",i));
704                 }
705         }
706         if (i%16) {
707                 int n;
708                 n = 16 - (i%16);
709                 DEBUGADD(level,(" "));
710                 if (n>8) DEBUGADD(level,(" "));
711                 while (n--) DEBUGADD(level,("   "));
712                 n = MIN(8,i%16);
713                 print_asc(level,&buf[i-(i%16)],n); DEBUGADD(level,( " " ));
714                 n = (i%16) - n;
715                 if (n>0) print_asc(level,&buf[i-n],n); 
716                 DEBUGADD(level,("\n"));    
717         }       
718 }
719
720 /*****************************************************************
721  Possibly replace mkstemp if it is broken.
722 *****************************************************************/  
723
724 int smb_mkstemp(char *template)
725 {
726 #if HAVE_SECURE_MKSTEMP
727         return mkstemp(template);
728 #else
729         /* have a reasonable go at emulating it. Hope that
730            the system mktemp() isn't completly hopeless */
731         char *p = mktemp(template);
732         if (!p)
733                 return -1;
734         return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
735 #endif
736 }
737
738 /*****************************************************************
739  malloc that aborts with smb_panic on fail or zero size.
740  *****************************************************************/  
741
742 void *smb_xmalloc(size_t size)
743 {
744         void *p;
745         if (size == 0)
746                 smb_panic("smb_xmalloc: called with zero size.\n");
747         if ((p = malloc(size)) == NULL)
748                 smb_panic("smb_xmalloc: malloc fail.\n");
749         return p;
750 }
751
752 /**
753  Memdup with smb_panic on fail.
754 **/
755
756 void *smb_xmemdup(const void *p, size_t size)
757 {
758         void *p2;
759         p2 = smb_xmalloc(size);
760         memcpy(p2, p, size);
761         return p2;
762 }
763
764 /**
765  strdup that aborts on malloc fail.
766 **/
767
768 char *smb_xstrdup(const char *s)
769 {
770         char *s1 = strdup(s);
771         if (!s1)
772                 smb_panic("smb_xstrdup: malloc fail\n");
773         return s1;
774 }
775
776
777 /*
778   vasprintf that aborts on malloc fail
779 */
780
781  int smb_xvasprintf(char **ptr, const char *format, va_list ap)
782 {
783         int n;
784         va_list ap2;
785
786         VA_COPY(ap2, ap);
787
788         n = vasprintf(ptr, format, ap2);
789         if (n == -1 || ! *ptr)
790                 smb_panic("smb_xvasprintf: out of memory");
791         return n;
792 }
793
794 /*****************************************************************
795  Like strdup but for memory.
796 *****************************************************************/  
797
798 void *memdup(const void *p, size_t size)
799 {
800         void *p2;
801         if (size == 0)
802                 return NULL;
803         p2 = malloc(size);
804         if (!p2)
805                 return NULL;
806         memcpy(p2, p, size);
807         return p2;
808 }
809
810 /*****************************************************************
811  Get local hostname and cache result.
812 *****************************************************************/  
813
814 char *myhostname(TALLOC_CTX *mem_ctx)
815 {
816         char *myname, *ret;
817         myname = get_myname();
818         ret = talloc_strdup(mem_ctx, myname);
819         free(myname);
820         return ret;
821
822 }
823
824 /*****************************************************************
825  A useful function for returning a path in the Samba lock directory.
826 *****************************************************************/  
827
828 char *lock_path(TALLOC_CTX* mem_ctx, const char *name)
829 {
830         char *fname;
831
832         fname = talloc_strdup(mem_ctx, lp_lockdir());
833         trim_string(fname,"","/");
834         
835         if (!directory_exist(fname,NULL))
836                 mkdir(fname,0755);
837         
838         fname = talloc_asprintf(mem_ctx, "%s/%s", fname, name);
839
840         return fname;
841 }
842
843 /**
844  * @brief Returns an absolute path to a file in the Samba lib directory.
845  *
846  * @param name File to find, relative to LIBDIR.
847  *
848  * @retval Pointer to a talloc'ed string containing the full path.
849  **/
850
851 char *lib_path(TALLOC_CTX* mem_ctx, const char *name)
852 {
853         char *fname;
854         fname = talloc_asprintf(mem_ctx, "%s/%s", dyn_LIBDIR, name);
855         return fname;
856 }
857
858 /**
859  * @brief Returns the platform specific shared library extension.
860  *
861  * @retval Pointer to a static #fstring containing the extension.
862  **/
863
864 const char *shlib_ext(void)
865 {
866   return dyn_SHLIBEXT;
867 }
868
869
870 /*********************************************************
871  Recursive routine that is called by unix_wild_match.
872 *********************************************************/
873
874 static BOOL unix_do_match(char *regexp, char *str)
875 {
876         char *p;
877
878         for( p = regexp; *p && *str; ) {
879
880                 switch(*p) {
881                         case '?':
882                                 str++;
883                                 p++;
884                                 break;
885
886                         case '*':
887
888                                 /*
889                                  * Look for a character matching 
890                                  * the one after the '*'.
891                                  */
892                                 p++;
893                                 if(!*p)
894                                         return True; /* Automatic match */
895                                 while(*str) {
896
897                                         while(*str && (*p != *str))
898                                                 str++;
899
900                                         /*
901                                          * Patch from weidel@multichart.de. In the case of the regexp
902                                          * '*XX*' we want to ensure there are at least 2 'X' characters
903                                          * in the string after the '*' for a match to be made.
904                                          */
905
906                                         {
907                                                 int matchcount=0;
908
909                                                 /*
910                                                  * Eat all the characters that match, but count how many there were.
911                                                  */
912
913                                                 while(*str && (*p == *str)) {
914                                                         str++;
915                                                         matchcount++;
916                                                 }
917
918                                                 /*
919                                                  * Now check that if the regexp had n identical characters that
920                                                  * matchcount had at least that many matches.
921                                                  */
922
923                                                 while ( *(p+1) && (*(p+1) == *p)) {
924                                                         p++;
925                                                         matchcount--;
926                                                 }
927
928                                                 if ( matchcount <= 0 )
929                                                         return False;
930                                         }
931
932                                         str--; /* We've eaten the match char after the '*' */
933
934                                         if(unix_do_match(p, str))
935                                                 return True;
936
937                                         if(!*str)
938                                                 return False;
939                                         else
940                                                 str++;
941                                 }
942                                 return False;
943
944                         default:
945                                 if(*str != *p)
946                                         return False;
947                                 str++;
948                                 p++;
949                                 break;
950                 }
951         }
952
953         if(!*p && !*str)
954                 return True;
955
956         if (!*p && str[0] == '.' && str[1] == 0)
957                 return(True);
958   
959         if (!*str && *p == '?') {
960                 while (*p == '?')
961                         p++;
962                 return(!*p);
963         }
964
965         if(!*str && (*p == '*' && p[1] == '\0'))
966                 return True;
967
968         return False;
969 }
970
971 void dump_data_pw(const char *msg, const uchar * data, size_t len)
972 {
973 #ifdef DEBUG_PASSWORD
974         DEBUG(11, ("%s", msg));
975         if (data != NULL && len > 0)
976         {
977                 dump_data(11, data, len);
978         }
979 #endif
980 }
981
982
983 /* see if a range of memory is all zero. A NULL pointer is considered
984    to be all zero */
985 BOOL all_zero(const char *ptr, unsigned size)
986 {
987         int i;
988         if (!ptr) return True;
989         for (i=0;i<size;i++) {
990                 if (ptr[i]) return False;
991         }
992         return True;
993 }
994