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