e9c2d372276d36189960df9d97cc4f513aefad34
[samba.git] / source3 / lib / util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 2001-2002
6    Copyright (C) Simo Sorce 2001
7    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
8    Copyright (C) James Peach 2006
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 extern fstring local_machine;
28 extern char *global_clobber_region_function;
29 extern unsigned int global_clobber_region_line;
30 extern fstring remote_arch;
31
32 /* Max allowable allococation - 256mb - 0x10000000 */
33 #define MAX_ALLOC_SIZE (1024*1024*256)
34
35 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
36 #ifdef WITH_NISPLUS_HOME
37 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
38 /*
39  * The following lines are needed due to buggy include files
40  * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
41  * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
42  * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
43  * an enum in /usr/include/rpcsvc/nis.h.
44  */
45
46 #if defined(GROUP)
47 #undef GROUP
48 #endif
49
50 #if defined(GROUP_OBJ)
51 #undef GROUP_OBJ
52 #endif
53
54 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
55
56 #include <rpcsvc/nis.h>
57
58 #endif /* WITH_NISPLUS_HOME */
59 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
60
61 enum protocol_types Protocol = PROTOCOL_COREPLUS;
62
63 /* a default finfo structure to ensure all fields are sensible */
64 file_info def_finfo;
65
66 /* this is used by the chaining code */
67 int chain_size = 0;
68
69 int trans_num = 0;
70
71 static enum remote_arch_types ra_type = RA_UNKNOWN;
72 pstring user_socket_options=DEFAULT_SOCKET_OPTIONS;   
73
74 /***********************************************************************
75  Definitions for all names.
76 ***********************************************************************/
77
78 static char *smb_myname;
79 static char *smb_myworkgroup;
80 static char *smb_scope;
81 static int smb_num_netbios_names;
82 static char **smb_my_netbios_names;
83
84 /***********************************************************************
85  Allocate and set myname. Ensure upper case.
86 ***********************************************************************/
87
88 BOOL set_global_myname(const char *myname)
89 {
90         SAFE_FREE(smb_myname);
91         smb_myname = SMB_STRDUP(myname);
92         if (!smb_myname)
93                 return False;
94         strupper_m(smb_myname);
95         return True;
96 }
97
98 const char *global_myname(void)
99 {
100         return smb_myname;
101 }
102
103 /***********************************************************************
104  Allocate and set myworkgroup. Ensure upper case.
105 ***********************************************************************/
106
107 BOOL set_global_myworkgroup(const char *myworkgroup)
108 {
109         SAFE_FREE(smb_myworkgroup);
110         smb_myworkgroup = SMB_STRDUP(myworkgroup);
111         if (!smb_myworkgroup)
112                 return False;
113         strupper_m(smb_myworkgroup);
114         return True;
115 }
116
117 const char *lp_workgroup(void)
118 {
119         return smb_myworkgroup;
120 }
121
122 /***********************************************************************
123  Allocate and set scope. Ensure upper case.
124 ***********************************************************************/
125
126 BOOL set_global_scope(const char *scope)
127 {
128         SAFE_FREE(smb_scope);
129         smb_scope = SMB_STRDUP(scope);
130         if (!smb_scope)
131                 return False;
132         strupper_m(smb_scope);
133         return True;
134 }
135
136 /*********************************************************************
137  Ensure scope is never null string.
138 *********************************************************************/
139
140 const char *global_scope(void)
141 {
142         if (!smb_scope)
143                 set_global_scope("");
144         return smb_scope;
145 }
146
147 static void free_netbios_names_array(void)
148 {
149         int i;
150
151         for (i = 0; i < smb_num_netbios_names; i++)
152                 SAFE_FREE(smb_my_netbios_names[i]);
153
154         SAFE_FREE(smb_my_netbios_names);
155         smb_num_netbios_names = 0;
156 }
157
158 static BOOL allocate_my_netbios_names_array(size_t number)
159 {
160         free_netbios_names_array();
161
162         smb_num_netbios_names = number + 1;
163         smb_my_netbios_names = SMB_MALLOC_ARRAY( char *, smb_num_netbios_names );
164
165         if (!smb_my_netbios_names)
166                 return False;
167
168         memset(smb_my_netbios_names, '\0', sizeof(char *) * smb_num_netbios_names);
169         return True;
170 }
171
172 static BOOL set_my_netbios_names(const char *name, int i)
173 {
174         SAFE_FREE(smb_my_netbios_names[i]);
175
176         smb_my_netbios_names[i] = SMB_STRDUP(name);
177         if (!smb_my_netbios_names[i])
178                 return False;
179         strupper_m(smb_my_netbios_names[i]);
180         return True;
181 }
182
183 /***********************************************************************
184  Free memory allocated to global objects
185 ***********************************************************************/
186
187 void gfree_names(void)
188 {
189         SAFE_FREE( smb_myname );
190         SAFE_FREE( smb_myworkgroup );
191         SAFE_FREE( smb_scope );
192         free_netbios_names_array();
193 }
194
195 void gfree_all( void )
196 {
197         gfree_names();  
198         gfree_loadparm();
199         gfree_case_tables();
200         gfree_debugsyms();
201         gfree_charcnv();
202         gfree_messages();
203         gfree_interfaces();
204
205         /* release the talloc null_context memory last */
206         talloc_disable_null_tracking();
207 }
208
209 const char *my_netbios_names(int i)
210 {
211         return smb_my_netbios_names[i];
212 }
213
214 BOOL set_netbios_aliases(const char **str_array)
215 {
216         size_t namecount;
217
218         /* Work out the max number of netbios aliases that we have */
219         for( namecount=0; str_array && (str_array[namecount] != NULL); namecount++ )
220                 ;
221
222         if ( global_myname() && *global_myname())
223                 namecount++;
224
225         /* Allocate space for the netbios aliases */
226         if (!allocate_my_netbios_names_array(namecount))
227                 return False;
228
229         /* Use the global_myname string first */
230         namecount=0;
231         if ( global_myname() && *global_myname()) {
232                 set_my_netbios_names( global_myname(), namecount );
233                 namecount++;
234         }
235
236         if (str_array) {
237                 size_t i;
238                 for ( i = 0; str_array[i] != NULL; i++) {
239                         size_t n;
240                         BOOL duplicate = False;
241
242                         /* Look for duplicates */
243                         for( n=0; n<namecount; n++ ) {
244                                 if( strequal( str_array[i], my_netbios_names(n) ) ) {
245                                         duplicate = True;
246                                         break;
247                                 }
248                         }
249                         if (!duplicate) {
250                                 if (!set_my_netbios_names(str_array[i], namecount))
251                                         return False;
252                                 namecount++;
253                         }
254                 }
255         }
256         return True;
257 }
258
259 /****************************************************************************
260   Common name initialization code.
261 ****************************************************************************/
262
263 BOOL init_names(void)
264 {
265         char *p;
266         int n;
267
268         if (global_myname() == NULL || *global_myname() == '\0') {
269                 if (!set_global_myname(myhostname())) {
270                         DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
271                         return False;
272                 }
273         }
274
275         if (!set_netbios_aliases(lp_netbios_aliases())) {
276                 DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
277                 return False;
278         }                       
279
280         fstrcpy( local_machine, global_myname() );
281         trim_char( local_machine, ' ', ' ' );
282         p = strchr( local_machine, ' ' );
283         if (p)
284                 *p = 0;
285         strlower_m( local_machine );
286
287         DEBUG( 5, ("Netbios name list:-\n") );
288         for( n=0; my_netbios_names(n); n++ )
289                 DEBUGADD( 5, ( "my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names(n) ) );
290
291         return( True );
292 }
293
294 /**************************************************************************n
295  Find a suitable temporary directory. The result should be copied immediately
296  as it may be overwritten by a subsequent call.
297 ****************************************************************************/
298
299 const char *tmpdir(void)
300 {
301         char *p;
302         if ((p = getenv("TMPDIR")))
303                 return p;
304         return "/tmp";
305 }
306
307 /****************************************************************************
308  Add a gid to an array of gids if it's not already there.
309 ****************************************************************************/
310
311 BOOL add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid,
312                              gid_t **gids, size_t *num_gids)
313 {
314         int i;
315
316         if ((*num_gids != 0) && (*gids == NULL)) {
317                 /*
318                  * A former call to this routine has failed to allocate memory
319                  */
320                 return False;
321         }
322
323         for (i=0; i<*num_gids; i++) {
324                 if ((*gids)[i] == gid) {
325                         return True;
326                 }
327         }
328
329         *gids = TALLOC_REALLOC_ARRAY(mem_ctx, *gids, gid_t, *num_gids+1);
330         if (*gids == NULL) {
331                 *num_gids = 0;
332                 return False;
333         }
334
335         (*gids)[*num_gids] = gid;
336         *num_gids += 1;
337         return True;
338 }
339
340 /****************************************************************************
341  Like atoi but gets the value up to the separator character.
342 ****************************************************************************/
343
344 static const char *Atoic(const char *p, int *n, const char *c)
345 {
346         if (!isdigit((int)*p)) {
347                 DEBUG(5, ("Atoic: malformed number\n"));
348                 return NULL;
349         }
350
351         (*n) = atoi(p);
352
353         while ((*p) && isdigit((int)*p))
354                 p++;
355
356         if (strchr_m(c, *p) == NULL) {
357                 DEBUG(5, ("Atoic: no separator characters (%s) not found\n", c));
358                 return NULL;
359         }
360
361         return p;
362 }
363
364 /*************************************************************************
365  Reads a list of numbers.
366  *************************************************************************/
367
368 const char *get_numlist(const char *p, uint32 **num, int *count)
369 {
370         int val;
371
372         if (num == NULL || count == NULL)
373                 return NULL;
374
375         (*count) = 0;
376         (*num  ) = NULL;
377
378         while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':') {
379                 *num = SMB_REALLOC_ARRAY((*num), uint32, (*count)+1);
380                 if (!(*num)) {
381                         return NULL;
382                 }
383                 (*num)[(*count)] = val;
384                 (*count)++;
385                 p++;
386         }
387
388         return p;
389 }
390
391 /*******************************************************************
392  Check if a file exists - call vfs_file_exist for samba files.
393 ********************************************************************/
394
395 BOOL file_exist(const char *fname,SMB_STRUCT_STAT *sbuf)
396 {
397         SMB_STRUCT_STAT st;
398         if (!sbuf)
399                 sbuf = &st;
400   
401         if (sys_stat(fname,sbuf) != 0) 
402                 return(False);
403
404         return((S_ISREG(sbuf->st_mode)) || (S_ISFIFO(sbuf->st_mode)));
405 }
406
407 /*******************************************************************
408  Check a files mod time.
409 ********************************************************************/
410
411 time_t file_modtime(const char *fname)
412 {
413         SMB_STRUCT_STAT st;
414   
415         if (sys_stat(fname,&st) != 0) 
416                 return(0);
417
418         return(st.st_mtime);
419 }
420
421 /*******************************************************************
422  Check if a directory exists.
423 ********************************************************************/
424
425 BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st)
426 {
427         SMB_STRUCT_STAT st2;
428         BOOL ret;
429
430         if (!st)
431                 st = &st2;
432
433         if (sys_stat(dname,st) != 0) 
434                 return(False);
435
436         ret = S_ISDIR(st->st_mode);
437         if(!ret)
438                 errno = ENOTDIR;
439         return ret;
440 }
441
442 /*******************************************************************
443  Returns the size in bytes of the named file.
444 ********************************************************************/
445
446 SMB_OFF_T get_file_size(char *file_name)
447 {
448         SMB_STRUCT_STAT buf;
449         buf.st_size = 0;
450         if(sys_stat(file_name,&buf) != 0)
451                 return (SMB_OFF_T)-1;
452         return(buf.st_size);
453 }
454
455 /*******************************************************************
456  Return a string representing an attribute for a file.
457 ********************************************************************/
458
459 char *attrib_string(uint16 mode)
460 {
461         static fstring attrstr;
462
463         attrstr[0] = 0;
464
465         if (mode & aVOLID) fstrcat(attrstr,"V");
466         if (mode & aDIR) fstrcat(attrstr,"D");
467         if (mode & aARCH) fstrcat(attrstr,"A");
468         if (mode & aHIDDEN) fstrcat(attrstr,"H");
469         if (mode & aSYSTEM) fstrcat(attrstr,"S");
470         if (mode & aRONLY) fstrcat(attrstr,"R");          
471
472         return(attrstr);
473 }
474
475 /*******************************************************************
476  Show a smb message structure.
477 ********************************************************************/
478
479 void show_msg(char *buf)
480 {
481         int i;
482         int bcc=0;
483
484         if (!DEBUGLVL(5))
485                 return;
486         
487         DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
488                         smb_len(buf),
489                         (int)CVAL(buf,smb_com),
490                         (int)CVAL(buf,smb_rcls),
491                         (int)CVAL(buf,smb_reh),
492                         (int)SVAL(buf,smb_err),
493                         (int)CVAL(buf,smb_flg),
494                         (int)SVAL(buf,smb_flg2)));
495         DEBUGADD(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n",
496                         (int)SVAL(buf,smb_tid),
497                         (int)SVAL(buf,smb_pid),
498                         (int)SVAL(buf,smb_uid),
499                         (int)SVAL(buf,smb_mid)));
500         DEBUGADD(5,("smt_wct=%d\n",(int)CVAL(buf,smb_wct)));
501
502         for (i=0;i<(int)CVAL(buf,smb_wct);i++)
503                 DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i,
504                         SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
505         
506         bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
507
508         DEBUGADD(5,("smb_bcc=%d\n",bcc));
509
510         if (DEBUGLEVEL < 10)
511                 return;
512
513         if (DEBUGLEVEL < 50)
514                 bcc = MIN(bcc, 512);
515
516         dump_data(10, smb_buf(buf), bcc);       
517 }
518
519 /*******************************************************************
520  Set the length and marker of an encrypted smb packet.
521 ********************************************************************/
522
523 void smb_set_enclen(char *buf,int len,uint16 enc_ctx_num)
524 {
525         _smb_setlen(buf,len);
526
527         SCVAL(buf,4,0xFF);
528         SCVAL(buf,5,'S');
529         SSVAL(buf,6,enc_ctx_num);
530 }
531
532 /*******************************************************************
533  Set the length and marker of an smb packet.
534 ********************************************************************/
535
536 void smb_setlen(char *buf,int len)
537 {
538         _smb_setlen(buf,len);
539
540         SCVAL(buf,4,0xFF);
541         SCVAL(buf,5,'S');
542         SCVAL(buf,6,'M');
543         SCVAL(buf,7,'B');
544 }
545
546 /*******************************************************************
547  Setup the word count and byte count for a smb message.
548 ********************************************************************/
549
550 int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
551 {
552         if (zero && (num_words || num_bytes)) {
553                 memset(buf + smb_size,'\0',num_words*2 + num_bytes);
554         }
555         SCVAL(buf,smb_wct,num_words);
556         SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);  
557         smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
558         return (smb_size + num_words*2 + num_bytes);
559 }
560
561 /*******************************************************************
562  Setup only the byte count for a smb message.
563 ********************************************************************/
564
565 int set_message_bcc(char *buf,int num_bytes)
566 {
567         int num_words = CVAL(buf,smb_wct);
568         SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);  
569         smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
570         return (smb_size + num_words*2 + num_bytes);
571 }
572
573 /*******************************************************************
574  Setup only the byte count for a smb message, using the end of the
575  message as a marker.
576 ********************************************************************/
577
578 int set_message_end(void *outbuf,void *end_ptr)
579 {
580         return set_message_bcc((char *)outbuf,PTR_DIFF(end_ptr,smb_buf((char *)outbuf)));
581 }
582
583 /*******************************************************************
584  Reduce a file name, removing .. elements.
585 ********************************************************************/
586
587 void dos_clean_name(char *s)
588 {
589         char *p=NULL;
590
591         DEBUG(3,("dos_clean_name [%s]\n",s));
592
593         /* remove any double slashes */
594         all_string_sub(s, "\\\\", "\\", 0);
595
596         /* Remove leading .\\ characters */
597         if(strncmp(s, ".\\", 2) == 0) {
598                 trim_string(s, ".\\", NULL);
599                 if(*s == 0)
600                         pstrcpy(s,".\\");
601         }
602
603         while ((p = strstr_m(s,"\\..\\")) != NULL) {
604                 pstring s1;
605
606                 *p = 0;
607                 pstrcpy(s1,p+3);
608
609                 if ((p=strrchr_m(s,'\\')) != NULL)
610                         *p = 0;
611                 else
612                         *s = 0;
613                 pstrcat(s,s1);
614         }  
615
616         trim_string(s,NULL,"\\..");
617         all_string_sub(s, "\\.\\", "\\", 0);
618 }
619
620 /*******************************************************************
621  Reduce a file name, removing .. elements. 
622 ********************************************************************/
623
624 void unix_clean_name(char *s)
625 {
626         char *p=NULL;
627
628         DEBUG(3,("unix_clean_name [%s]\n",s));
629
630         /* remove any double slashes */
631         all_string_sub(s, "//","/", 0);
632
633         /* Remove leading ./ characters */
634         if(strncmp(s, "./", 2) == 0) {
635                 trim_string(s, "./", NULL);
636                 if(*s == 0)
637                         pstrcpy(s,"./");
638         }
639
640         while ((p = strstr_m(s,"/../")) != NULL) {
641                 pstring s1;
642
643                 *p = 0;
644                 pstrcpy(s1,p+3);
645
646                 if ((p=strrchr_m(s,'/')) != NULL)
647                         *p = 0;
648                 else
649                         *s = 0;
650                 pstrcat(s,s1);
651         }  
652
653         trim_string(s,NULL,"/..");
654         all_string_sub(s, "/./", "/", 0);
655 }
656
657 void clean_name(char *s)
658 {
659         dos_clean_name(s);
660         unix_clean_name(s);
661 }
662
663 /*******************************************************************
664  Close the low 3 fd's and open dev/null in their place.
665 ********************************************************************/
666
667 void close_low_fds(BOOL stderr_too)
668 {
669 #ifndef VALGRIND
670         int fd;
671         int i;
672
673         close(0);
674         close(1); 
675
676         if (stderr_too)
677                 close(2);
678
679         /* try and use up these file descriptors, so silly
680                 library routines writing to stdout etc won't cause havoc */
681         for (i=0;i<3;i++) {
682                 if (i == 2 && !stderr_too)
683                         continue;
684
685                 fd = sys_open("/dev/null",O_RDWR,0);
686                 if (fd < 0)
687                         fd = sys_open("/dev/null",O_WRONLY,0);
688                 if (fd < 0) {
689                         DEBUG(0,("Can't open /dev/null\n"));
690                         return;
691                 }
692                 if (fd != i) {
693                         DEBUG(0,("Didn't get file descriptor %d\n",i));
694                         return;
695                 }
696         }
697 #endif
698 }
699
700 /*******************************************************************
701  Write data into an fd at a given offset. Ignore seek errors.
702 ********************************************************************/
703
704 ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, SMB_OFF_T pos)
705 {
706         size_t total=0;
707         ssize_t ret;
708
709         if (pos == (SMB_OFF_T)-1) {
710                 return write_data(fd, buffer, N);
711         }
712 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
713         while (total < N) {
714                 ret = sys_pwrite(fd,buffer + total,N - total, pos);
715                 if (ret == -1 && errno == ESPIPE) {
716                         return write_data(fd, buffer + total,N - total);
717                 }
718                 if (ret == -1) {
719                         DEBUG(0,("write_data_at_offset: write failure. Error = %s\n", strerror(errno) ));
720                         return -1;
721                 }
722                 if (ret == 0) {
723                         return total;
724                 }
725                 total += ret;
726                 pos += ret;
727         }
728         return (ssize_t)total;
729 #else
730         /* Use lseek and write_data. */
731         if (sys_lseek(fd, pos, SEEK_SET) == -1) {
732                 if (errno != ESPIPE) {
733                         return -1;
734                 }
735         }
736         return write_data(fd, buffer, N);
737 #endif
738 }
739
740 /****************************************************************************
741  Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
742  else
743   if SYSV use O_NDELAY
744   if BSD use FNDELAY
745 ****************************************************************************/
746
747 int set_blocking(int fd, BOOL set)
748 {
749         int val;
750 #ifdef O_NONBLOCK
751 #define FLAG_TO_SET O_NONBLOCK
752 #else
753 #ifdef SYSV
754 #define FLAG_TO_SET O_NDELAY
755 #else /* BSD */
756 #define FLAG_TO_SET FNDELAY
757 #endif
758 #endif
759
760         if((val = sys_fcntl_long(fd, F_GETFL, 0)) == -1)
761                 return -1;
762         if(set) /* Turn blocking on - ie. clear nonblock flag */
763                 val &= ~FLAG_TO_SET;
764         else
765                 val |= FLAG_TO_SET;
766         return sys_fcntl_long( fd, F_SETFL, val);
767 #undef FLAG_TO_SET
768 }
769
770 /****************************************************************************
771  Transfer some data between two fd's.
772 ****************************************************************************/
773
774 #ifndef TRANSFER_BUF_SIZE
775 #define TRANSFER_BUF_SIZE 65536
776 #endif
777
778 ssize_t transfer_file_internal(int infd, int outfd, size_t n, ssize_t (*read_fn)(int, void *, size_t),
779                                                 ssize_t (*write_fn)(int, const void *, size_t))
780 {
781         char *buf;
782         size_t total = 0;
783         ssize_t read_ret;
784         ssize_t write_ret;
785         size_t num_to_read_thistime;
786         size_t num_written = 0;
787
788         if ((buf = SMB_MALLOC_ARRAY(char, TRANSFER_BUF_SIZE)) == NULL)
789                 return -1;
790
791         while (total < n) {
792                 num_to_read_thistime = MIN((n - total), TRANSFER_BUF_SIZE);
793
794                 read_ret = (*read_fn)(infd, buf, num_to_read_thistime);
795                 if (read_ret == -1) {
796                         DEBUG(0,("transfer_file_internal: read failure. Error = %s\n", strerror(errno) ));
797                         SAFE_FREE(buf);
798                         return -1;
799                 }
800                 if (read_ret == 0)
801                         break;
802
803                 num_written = 0;
804  
805                 while (num_written < read_ret) {
806                         write_ret = (*write_fn)(outfd,buf + num_written, read_ret - num_written);
807  
808                         if (write_ret == -1) {
809                                 DEBUG(0,("transfer_file_internal: write failure. Error = %s\n", strerror(errno) ));
810                                 SAFE_FREE(buf);
811                                 return -1;
812                         }
813                         if (write_ret == 0)
814                                 return (ssize_t)total;
815  
816                         num_written += (size_t)write_ret;
817                 }
818
819                 total += (size_t)read_ret;
820         }
821
822         SAFE_FREE(buf);
823         return (ssize_t)total;          
824 }
825
826 SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n)
827 {
828         return (SMB_OFF_T)transfer_file_internal(infd, outfd, (size_t)n, sys_read, sys_write);
829 }
830
831 /*******************************************************************
832  Sleep for a specified number of milliseconds.
833 ********************************************************************/
834
835 void smb_msleep(unsigned int t)
836 {
837 #if defined(HAVE_NANOSLEEP)
838         struct timespec tval;
839         int ret;
840
841         tval.tv_sec = t/1000;
842         tval.tv_nsec = 1000000*(t%1000);
843
844         do {
845                 errno = 0;
846                 ret = nanosleep(&tval, &tval);
847         } while (ret < 0 && errno == EINTR && (tval.tv_sec > 0 || tval.tv_nsec > 0));
848 #else
849         unsigned int tdiff=0;
850         struct timeval tval,t1,t2;  
851         fd_set fds;
852
853         GetTimeOfDay(&t1);
854         t2 = t1;
855   
856         while (tdiff < t) {
857                 tval.tv_sec = (t-tdiff)/1000;
858                 tval.tv_usec = 1000*((t-tdiff)%1000);
859
860                 /* Never wait for more than 1 sec. */
861                 if (tval.tv_sec > 1) {
862                         tval.tv_sec = 1; 
863                         tval.tv_usec = 0;
864                 }
865
866                 FD_ZERO(&fds);
867                 errno = 0;
868                 sys_select_intr(0,&fds,NULL,NULL,&tval);
869
870                 GetTimeOfDay(&t2);
871                 if (t2.tv_sec < t1.tv_sec) {
872                         /* Someone adjusted time... */
873                         t1 = t2;
874                 }
875
876                 tdiff = TvalDiff(&t1,&t2);
877         }
878 #endif
879 }
880
881 /****************************************************************************
882  Become a daemon, discarding the controlling terminal.
883 ****************************************************************************/
884
885 void become_daemon(BOOL Fork, BOOL no_process_group)
886 {
887         if (Fork) {
888                 if (sys_fork()) {
889                         _exit(0);
890                 }
891         }
892
893   /* detach from the terminal */
894 #ifdef HAVE_SETSID
895         if (!no_process_group) setsid();
896 #elif defined(TIOCNOTTY)
897         if (!no_process_group) {
898                 int i = sys_open("/dev/tty", O_RDWR, 0);
899                 if (i != -1) {
900                         ioctl(i, (int) TIOCNOTTY, (char *)0);      
901                         close(i);
902                 }
903         }
904 #endif /* HAVE_SETSID */
905
906         /* Close fd's 0,1,2. Needed if started by rsh */
907         close_low_fds(False);  /* Don't close stderr, let the debug system
908                                   attach it to the logfile */
909 }
910
911 /****************************************************************************
912  Put up a yes/no prompt.
913 ****************************************************************************/
914
915 BOOL yesno(char *p)
916 {
917         pstring ans;
918         printf("%s",p);
919
920         if (!fgets(ans,sizeof(ans)-1,stdin))
921                 return(False);
922
923         if (*ans == 'y' || *ans == 'Y')
924                 return(True);
925
926         return(False);
927 }
928
929 #if defined(PARANOID_MALLOC_CHECKER)
930
931 /****************************************************************************
932  Internal malloc wrapper. Externally visible.
933 ****************************************************************************/
934
935 void *malloc_(size_t size)
936 {
937 #undef malloc
938         return malloc(size);
939 #define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY
940 }
941
942 /****************************************************************************
943  Internal calloc wrapper. Not externally visible.
944 ****************************************************************************/
945
946 static void *calloc_(size_t count, size_t size)
947 {
948 #undef calloc
949         return calloc(count, size);
950 #define calloc(n,s) __ERROR_DONT_USE_CALLOC_DIRECTLY
951 }
952
953 /****************************************************************************
954  Internal realloc wrapper. Not externally visible.
955 ****************************************************************************/
956
957 static void *realloc_(void *ptr, size_t size)
958 {
959 #undef realloc
960         return realloc(ptr, size);
961 #define realloc(p,s) __ERROR_DONT_USE_RELLOC_DIRECTLY
962 }
963
964 #endif /* PARANOID_MALLOC_CHECKER */
965
966 /****************************************************************************
967  Type-safe malloc.
968 ****************************************************************************/
969
970 void *malloc_array(size_t el_size, unsigned int count)
971 {
972         if (count >= MAX_ALLOC_SIZE/el_size) {
973                 return NULL;
974         }
975
976 #if defined(PARANOID_MALLOC_CHECKER)
977         return malloc_(el_size*count);
978 #else
979         return malloc(el_size*count);
980 #endif
981 }
982
983 /****************************************************************************
984  Type-safe memalign
985 ****************************************************************************/
986
987 void *memalign_array(size_t el_size, size_t align, unsigned int count)
988 {
989         if (count >= MAX_ALLOC_SIZE/el_size) {
990                 return NULL;
991         }
992
993         return sys_memalign(align, el_size*count);
994 }
995
996 /****************************************************************************
997  Type-safe calloc.
998 ****************************************************************************/
999
1000 void *calloc_array(size_t size, size_t nmemb)
1001 {
1002         if (nmemb >= MAX_ALLOC_SIZE/size) {
1003                 return NULL;
1004         }
1005 #if defined(PARANOID_MALLOC_CHECKER)
1006         return calloc_(nmemb, size);
1007 #else
1008         return calloc(nmemb, size);
1009 #endif
1010 }
1011
1012 /****************************************************************************
1013  Expand a pointer to be a particular size.
1014  Note that this version of Realloc has an extra parameter that decides
1015  whether to free the passed in storage on allocation failure or if the
1016  new size is zero.
1017
1018  This is designed for use in the typical idiom of :
1019
1020  p = SMB_REALLOC(p, size)
1021  if (!p) {
1022     return error;
1023  }
1024
1025  and not to have to keep track of the old 'p' contents to free later, nor
1026  to worry if the size parameter was zero. In the case where NULL is returned
1027  we guarentee that p has been freed.
1028
1029  If free later semantics are desired, then pass 'free_old_on_error' as False which
1030  guarentees that the old contents are not freed on error, even if size == 0. To use
1031  this idiom use :
1032
1033  tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
1034  if (!tmp) {
1035     SAFE_FREE(p);
1036     return error;
1037  } else {
1038     p = tmp;
1039  }
1040
1041  Changes were instigated by Coverity error checking. JRA.
1042 ****************************************************************************/
1043
1044 void *Realloc(void *p, size_t size, BOOL free_old_on_error)
1045 {
1046         void *ret=NULL;
1047
1048         if (size == 0) {
1049                 if (free_old_on_error) {
1050                         SAFE_FREE(p);
1051                 }
1052                 DEBUG(2,("Realloc asked for 0 bytes\n"));
1053                 return NULL;
1054         }
1055
1056 #if defined(PARANOID_MALLOC_CHECKER)
1057         if (!p) {
1058                 ret = (void *)malloc_(size);
1059         } else {
1060                 ret = (void *)realloc_(p,size);
1061         }
1062 #else
1063         if (!p) {
1064                 ret = (void *)malloc(size);
1065         } else {
1066                 ret = (void *)realloc(p,size);
1067         }
1068 #endif
1069
1070         if (!ret) {
1071                 if (free_old_on_error && p) {
1072                         SAFE_FREE(p);
1073                 }
1074                 DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size));
1075         }
1076
1077         return(ret);
1078 }
1079
1080 /****************************************************************************
1081  Type-safe realloc.
1082 ****************************************************************************/
1083
1084 void *realloc_array(void *p, size_t el_size, unsigned int count, BOOL free_old_on_error)
1085 {
1086         if (count >= MAX_ALLOC_SIZE/el_size) {
1087                 if (free_old_on_error) {
1088                         SAFE_FREE(p);
1089                 }
1090                 return NULL;
1091         }
1092         return Realloc(p, el_size*count, free_old_on_error);
1093 }
1094
1095 /****************************************************************************
1096  (Hopefully) efficient array append.
1097 ****************************************************************************/
1098
1099 void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
1100                         void *element, void *_array, uint32 *num_elements,
1101                         ssize_t *array_size)
1102 {
1103         void **array = (void **)_array;
1104
1105         if (*array_size < 0) {
1106                 return;
1107         }
1108
1109         if (*array == NULL) {
1110                 if (*array_size == 0) {
1111                         *array_size = 128;
1112                 }
1113
1114                 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
1115                         goto error;
1116                 }
1117
1118                 *array = TALLOC(mem_ctx, element_size * (*array_size));
1119                 if (*array == NULL) {
1120                         goto error;
1121                 }
1122         }
1123
1124         if (*num_elements == *array_size) {
1125                 *array_size *= 2;
1126
1127                 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
1128                         goto error;
1129                 }
1130
1131                 *array = TALLOC_REALLOC(mem_ctx, *array,
1132                                         element_size * (*array_size));
1133
1134                 if (*array == NULL) {
1135                         goto error;
1136                 }
1137         }
1138
1139         memcpy((char *)(*array) + element_size*(*num_elements),
1140                element, element_size);
1141         *num_elements += 1;
1142
1143         return;
1144
1145  error:
1146         *num_elements = 0;
1147         *array_size = -1;
1148 }
1149
1150 /****************************************************************************
1151  Free memory, checks for NULL.
1152  Use directly SAFE_FREE()
1153  Exists only because we need to pass a function pointer somewhere --SSS
1154 ****************************************************************************/
1155
1156 void safe_free(void *p)
1157 {
1158         SAFE_FREE(p);
1159 }
1160
1161 /****************************************************************************
1162  Get my own name and IP.
1163 ****************************************************************************/
1164
1165 BOOL get_myname(char *my_name)
1166 {
1167         pstring hostname;
1168
1169         *hostname = 0;
1170
1171         /* get my host name */
1172         if (gethostname(hostname, sizeof(hostname)) == -1) {
1173                 DEBUG(0,("gethostname failed\n"));
1174                 return False;
1175         } 
1176
1177         /* Ensure null termination. */
1178         hostname[sizeof(hostname)-1] = '\0';
1179
1180         if (my_name) {
1181                 /* split off any parts after an initial . */
1182                 char *p = strchr_m(hostname,'.');
1183
1184                 if (p)
1185                         *p = 0;
1186                 
1187                 fstrcpy(my_name,hostname);
1188         }
1189         
1190         return(True);
1191 }
1192
1193 /****************************************************************************
1194  Get my own canonical name, including domain.
1195 ****************************************************************************/
1196
1197 BOOL get_mydnsfullname(fstring my_dnsname)
1198 {
1199         static fstring dnshostname;
1200         struct hostent *hp;
1201
1202         if (!*dnshostname) {
1203                 /* get my host name */
1204                 if (gethostname(dnshostname, sizeof(dnshostname)) == -1) {
1205                         *dnshostname = '\0';
1206                         DEBUG(0,("gethostname failed\n"));
1207                         return False;
1208                 } 
1209
1210                 /* Ensure null termination. */
1211                 dnshostname[sizeof(dnshostname)-1] = '\0';
1212
1213                 /* Ensure we get the cannonical name. */
1214                 if (!(hp = sys_gethostbyname(dnshostname))) {
1215                         *dnshostname = '\0';
1216                         return False;
1217                 }
1218                 fstrcpy(dnshostname, hp->h_name);
1219         }
1220         fstrcpy(my_dnsname, dnshostname);
1221         return True;
1222 }
1223
1224 /****************************************************************************
1225  Get my own domain name.
1226 ****************************************************************************/
1227
1228 BOOL get_mydnsdomname(fstring my_domname)
1229 {
1230         fstring domname;
1231         char *p;
1232
1233         *my_domname = '\0';
1234         if (!get_mydnsfullname(domname)) {
1235                 return False;
1236         }       
1237         p = strchr_m(domname, '.');
1238         if (p) {
1239                 p++;
1240                 fstrcpy(my_domname, p);
1241         }
1242
1243         return False;
1244 }
1245
1246 /****************************************************************************
1247  Interpret a protocol description string, with a default.
1248 ****************************************************************************/
1249
1250 int interpret_protocol(const char *str,int def)
1251 {
1252         if (strequal(str,"NT1"))
1253                 return(PROTOCOL_NT1);
1254         if (strequal(str,"LANMAN2"))
1255                 return(PROTOCOL_LANMAN2);
1256         if (strequal(str,"LANMAN1"))
1257                 return(PROTOCOL_LANMAN1);
1258         if (strequal(str,"CORE"))
1259                 return(PROTOCOL_CORE);
1260         if (strequal(str,"COREPLUS"))
1261                 return(PROTOCOL_COREPLUS);
1262         if (strequal(str,"CORE+"))
1263                 return(PROTOCOL_COREPLUS);
1264   
1265         DEBUG(0,("Unrecognised protocol level %s\n",str));
1266   
1267         return(def);
1268 }
1269
1270 /****************************************************************************
1271  Return true if a string could be a pure IP address.
1272 ****************************************************************************/
1273
1274 BOOL is_ipaddress(const char *str)
1275 {
1276         BOOL pure_address = True;
1277         int i;
1278   
1279         for (i=0; pure_address && str[i]; i++)
1280                 if (!(isdigit((int)str[i]) || str[i] == '.'))
1281                         pure_address = False;
1282
1283         /* Check that a pure number is not misinterpreted as an IP */
1284         pure_address = pure_address && (strchr_m(str, '.') != NULL);
1285
1286         return pure_address;
1287 }
1288
1289 /****************************************************************************
1290  Interpret an internet address or name into an IP address in 4 byte form.
1291 ****************************************************************************/
1292
1293 uint32 interpret_addr(const char *str)
1294 {
1295         struct hostent *hp;
1296         uint32 res;
1297
1298         if (strcmp(str,"0.0.0.0") == 0)
1299                 return(0);
1300         if (strcmp(str,"255.255.255.255") == 0)
1301                 return(0xFFFFFFFF);
1302
1303   /* if it's in the form of an IP address then get the lib to interpret it */
1304         if (is_ipaddress(str)) {
1305                 res = inet_addr(str);
1306         } else {
1307                 /* otherwise assume it's a network name of some sort and use 
1308                         sys_gethostbyname */
1309                 if ((hp = sys_gethostbyname(str)) == 0) {
1310                         DEBUG(3,("sys_gethostbyname: Unknown host. %s\n",str));
1311                         return 0;
1312                 }
1313
1314                 if(hp->h_addr == NULL) {
1315                         DEBUG(3,("sys_gethostbyname: host address is invalid for host %s\n",str));
1316                         return 0;
1317                 }
1318                 putip((char *)&res,(char *)hp->h_addr);
1319         }
1320
1321         if (res == (uint32)-1)
1322                 return(0);
1323
1324         return(res);
1325 }
1326
1327 /*******************************************************************
1328  A convenient addition to interpret_addr().
1329 ******************************************************************/
1330
1331 struct in_addr *interpret_addr2(const char *str)
1332 {
1333         static struct in_addr ret;
1334         uint32 a = interpret_addr(str);
1335         ret.s_addr = a;
1336         return(&ret);
1337 }
1338
1339 /*******************************************************************
1340  Check if an IP is the 0.0.0.0.
1341 ******************************************************************/
1342
1343 BOOL is_zero_ip(struct in_addr ip)
1344 {
1345         uint32 a;
1346         putip((char *)&a,(char *)&ip);
1347         return(a == 0);
1348 }
1349
1350 /*******************************************************************
1351  Set an IP to 0.0.0.0.
1352 ******************************************************************/
1353
1354 void zero_ip(struct in_addr *ip)
1355 {
1356         static BOOL init;
1357         static struct in_addr ipzero;
1358
1359         if (!init) {
1360                 ipzero = *interpret_addr2("0.0.0.0");
1361                 init = True;
1362         }
1363
1364         *ip = ipzero;
1365 }
1366
1367 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1368 /******************************************************************
1369  Remove any mount options such as -rsize=2048,wsize=2048 etc.
1370  Based on a fix from <Thomas.Hepper@icem.de>.
1371 *******************************************************************/
1372
1373 static void strip_mount_options( pstring *str)
1374 {
1375         if (**str == '-') { 
1376                 char *p = *str;
1377                 while(*p && !isspace(*p))
1378                         p++;
1379                 while(*p && isspace(*p))
1380                         p++;
1381                 if(*p) {
1382                         pstring tmp_str;
1383
1384                         pstrcpy(tmp_str, p);
1385                         pstrcpy(*str, tmp_str);
1386                 }
1387         }
1388 }
1389
1390 /*******************************************************************
1391  Patch from jkf@soton.ac.uk
1392  Split Luke's automount_server into YP lookup and string splitter
1393  so can easily implement automount_path(). 
1394  As we may end up doing both, cache the last YP result. 
1395 *******************************************************************/
1396
1397 #ifdef WITH_NISPLUS_HOME
1398 char *automount_lookup(const char *user_name)
1399 {
1400         static fstring last_key = "";
1401         static pstring last_value = "";
1402  
1403         char *nis_map = (char *)lp_nis_home_map_name();
1404  
1405         char buffer[NIS_MAXATTRVAL + 1];
1406         nis_result *result;
1407         nis_object *object;
1408         entry_obj  *entry;
1409  
1410         if (strcmp(user_name, last_key)) {
1411                 slprintf(buffer, sizeof(buffer)-1, "[key=%s],%s", user_name, nis_map);
1412                 DEBUG(5, ("NIS+ querystring: %s\n", buffer));
1413  
1414                 if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL)) {
1415                         if (result->status != NIS_SUCCESS) {
1416                                 DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
1417                                 fstrcpy(last_key, ""); pstrcpy(last_value, "");
1418                         } else {
1419                                 object = result->objects.objects_val;
1420                                 if (object->zo_data.zo_type == ENTRY_OBJ) {
1421                                         entry = &object->zo_data.objdata_u.en_data;
1422                                         DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
1423                                         DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
1424  
1425                                         pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
1426                                         pstring_sub(last_value, "&", user_name);
1427                                         fstrcpy(last_key, user_name);
1428                                 }
1429                         }
1430                 }
1431                 nis_freeresult(result);
1432         }
1433
1434         strip_mount_options(&last_value);
1435
1436         DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
1437         return last_value;
1438 }
1439 #else /* WITH_NISPLUS_HOME */
1440
1441 char *automount_lookup(const char *user_name)
1442 {
1443         static fstring last_key = "";
1444         static pstring last_value = "";
1445
1446         int nis_error;        /* returned by yp all functions */
1447         char *nis_result;     /* yp_match inits this */
1448         int nis_result_len;  /* and set this */
1449         char *nis_domain;     /* yp_get_default_domain inits this */
1450         char *nis_map = (char *)lp_nis_home_map_name();
1451
1452         if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
1453                 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
1454                 return last_value;
1455         }
1456
1457         DEBUG(5, ("NIS Domain: %s\n", nis_domain));
1458
1459         if (!strcmp(user_name, last_key)) {
1460                 nis_result = last_value;
1461                 nis_result_len = strlen(last_value);
1462                 nis_error = 0;
1463         } else {
1464                 if ((nis_error = yp_match(nis_domain, nis_map, user_name, strlen(user_name),
1465                                 &nis_result, &nis_result_len)) == 0) {
1466                         fstrcpy(last_key, user_name);
1467                         pstrcpy(last_value, nis_result);
1468                         strip_mount_options(&last_value);
1469
1470                 } else if(nis_error == YPERR_KEY) {
1471
1472                         /* If Key lookup fails user home server is not in nis_map 
1473                                 use default information for server, and home directory */
1474                         last_value[0] = 0;
1475                         DEBUG(3, ("YP Key not found:  while looking up \"%s\" in map \"%s\"\n", 
1476                                         user_name, nis_map));
1477                         DEBUG(3, ("using defaults for server and home directory\n"));
1478                 } else {
1479                         DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n", 
1480                                         yperr_string(nis_error), user_name, nis_map));
1481                 }
1482         }
1483
1484         DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
1485         return last_value;
1486 }
1487 #endif /* WITH_NISPLUS_HOME */
1488 #endif
1489
1490 /*******************************************************************
1491  Are two IPs on the same subnet?
1492 ********************************************************************/
1493
1494 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
1495 {
1496         uint32 net1,net2,nmask;
1497
1498         nmask = ntohl(mask.s_addr);
1499         net1  = ntohl(ip1.s_addr);
1500         net2  = ntohl(ip2.s_addr);
1501             
1502         return((net1 & nmask) == (net2 & nmask));
1503 }
1504
1505
1506 /****************************************************************************
1507  Check if a process exists. Does this work on all unixes?
1508 ****************************************************************************/
1509
1510 BOOL process_exists(const struct process_id pid)
1511 {
1512         if (procid_is_me(&pid)) {
1513                 return True;
1514         }
1515
1516         if (!procid_is_local(&pid)) {
1517                 /* This *SEVERELY* needs fixing. */
1518                 return True;
1519         }
1520
1521         /* Doing kill with a non-positive pid causes messages to be
1522          * sent to places we don't want. */
1523         SMB_ASSERT(pid.pid > 0);
1524         return(kill(pid.pid,0) == 0 || errno != ESRCH);
1525 }
1526
1527 BOOL process_exists_by_pid(pid_t pid)
1528 {
1529         return process_exists(pid_to_procid(pid));
1530 }
1531
1532 /*******************************************************************
1533  Convert a uid into a user name.
1534 ********************************************************************/
1535
1536 const char *uidtoname(uid_t uid)
1537 {
1538         static fstring name;
1539         struct passwd *pass;
1540
1541         pass = getpwuid_alloc(NULL, uid);
1542         if (pass) {
1543                 fstrcpy(name, pass->pw_name);
1544                 TALLOC_FREE(pass);
1545         } else {
1546                 slprintf(name, sizeof(name) - 1, "%ld",(long int)uid);
1547         }
1548         return name;
1549 }
1550
1551
1552 /*******************************************************************
1553  Convert a gid into a group name.
1554 ********************************************************************/
1555
1556 char *gidtoname(gid_t gid)
1557 {
1558         static fstring name;
1559         struct group *grp;
1560
1561         grp = getgrgid(gid);
1562         if (grp)
1563                 return(grp->gr_name);
1564         slprintf(name,sizeof(name) - 1, "%d",(int)gid);
1565         return(name);
1566 }
1567
1568 /*******************************************************************
1569  Convert a user name into a uid. 
1570 ********************************************************************/
1571
1572 uid_t nametouid(const char *name)
1573 {
1574         struct passwd *pass;
1575         char *p;
1576         uid_t u;
1577
1578         pass = getpwnam_alloc(NULL, name);
1579         if (pass) {
1580                 u = pass->pw_uid;
1581                 TALLOC_FREE(pass);
1582                 return u;
1583         }
1584
1585         u = (uid_t)strtol(name, &p, 0);
1586         if ((p != name) && (*p == '\0'))
1587                 return u;
1588
1589         return (uid_t)-1;
1590 }
1591
1592 /*******************************************************************
1593  Convert a name to a gid_t if possible. Return -1 if not a group. 
1594 ********************************************************************/
1595
1596 gid_t nametogid(const char *name)
1597 {
1598         struct group *grp;
1599         char *p;
1600         gid_t g;
1601
1602         g = (gid_t)strtol(name, &p, 0);
1603         if ((p != name) && (*p == '\0'))
1604                 return g;
1605
1606         grp = sys_getgrnam(name);
1607         if (grp)
1608                 return(grp->gr_gid);
1609         return (gid_t)-1;
1610 }
1611
1612 /*******************************************************************
1613  Something really nasty happened - panic !
1614 ********************************************************************/
1615
1616 void smb_panic(const char *const why)
1617 {
1618         char *cmd;
1619         int result;
1620
1621 #ifdef DEVELOPER
1622         {
1623
1624                 if (global_clobber_region_function) {
1625                         DEBUG(0,("smb_panic: clobber_region() last called from [%s(%u)]\n",
1626                                          global_clobber_region_function,
1627                                          global_clobber_region_line));
1628                 } 
1629         }
1630 #endif
1631
1632         DEBUG(0,("PANIC (pid %llu): %s\n",
1633                     (unsigned long long)sys_getpid(), why));
1634         log_stack_trace();
1635
1636         cmd = lp_panic_action();
1637         if (cmd && *cmd) {
1638                 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
1639                 result = system(cmd);
1640
1641                 if (result == -1)
1642                         DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
1643                                           strerror(errno)));
1644                 else
1645                         DEBUG(0, ("smb_panic(): action returned status %d\n",
1646                                           WEXITSTATUS(result)));
1647         }
1648
1649         dump_core();
1650 }
1651
1652 /*******************************************************************
1653  Print a backtrace of the stack to the debug log. This function
1654  DELIBERATELY LEAKS MEMORY. The expectation is that you should
1655  exit shortly after calling it.
1656 ********************************************************************/
1657
1658 #ifdef HAVE_LIBUNWIND_H
1659 #include <libunwind.h>
1660 #endif
1661
1662 #ifdef HAVE_EXECINFO_H
1663 #include <execinfo.h>
1664 #endif
1665
1666 #ifdef HAVE_LIBEXC_H
1667 #include <libexc.h>
1668 #endif
1669
1670 void log_stack_trace(void)
1671 {
1672 #ifdef HAVE_LIBUNWIND
1673         /* Try to use libunwind before any other technique since on ia64
1674          * libunwind correctly walks the stack in more circumstances than
1675          * backtrace.
1676          */ 
1677         unw_cursor_t cursor;
1678         unw_context_t uc;
1679         unsigned i = 0;
1680
1681         char procname[256];
1682         unw_word_t ip, sp, off;
1683
1684         procname[sizeof(procname) - 1] = '\0';
1685
1686         if (unw_getcontext(&uc) != 0) {
1687                 goto libunwind_failed;
1688         }
1689
1690         if (unw_init_local(&cursor, &uc) != 0) {
1691                 goto libunwind_failed;
1692         }
1693
1694         DEBUG(0, ("BACKTRACE:\n"));
1695
1696         do {
1697             ip = sp = 0;
1698             unw_get_reg(&cursor, UNW_REG_IP, &ip);
1699             unw_get_reg(&cursor, UNW_REG_SP, &sp);
1700
1701             switch (unw_get_proc_name(&cursor,
1702                         procname, sizeof(procname) - 1, &off) ) {
1703             case 0:
1704                     /* Name found. */
1705             case -UNW_ENOMEM:
1706                     /* Name truncated. */
1707                     DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
1708                             i, procname, (long long)off,
1709                             (long long)ip, (long long) sp));
1710                     break;
1711             default:
1712             /* case -UNW_ENOINFO: */
1713             /* case -UNW_EUNSPEC: */
1714                     /* No symbol name found. */
1715                     DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
1716                             i, "<unknown symbol>",
1717                             (long long)ip, (long long) sp));
1718             }
1719             ++i;
1720         } while (unw_step(&cursor) > 0);
1721
1722         return;
1723
1724 libunwind_failed:
1725         DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
1726
1727 #elif HAVE_BACKTRACE_SYMBOLS
1728         void *backtrace_stack[BACKTRACE_STACK_SIZE];
1729         size_t backtrace_size;
1730         char **backtrace_strings;
1731
1732         /* get the backtrace (stack frames) */
1733         backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
1734         backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
1735
1736         DEBUG(0, ("BACKTRACE: %lu stack frames:\n", 
1737                   (unsigned long)backtrace_size));
1738         
1739         if (backtrace_strings) {
1740                 int i;
1741
1742                 for (i = 0; i < backtrace_size; i++)
1743                         DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
1744
1745                 /* Leak the backtrace_strings, rather than risk what free() might do */
1746         }
1747
1748 #elif HAVE_LIBEXC
1749
1750         /* The IRIX libexc library provides an API for unwinding the stack. See
1751          * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
1752          * since we are about to abort anyway, it hardly matters.
1753          */
1754
1755 #define NAMESIZE 32 /* Arbitrary */
1756
1757         __uint64_t      addrs[BACKTRACE_STACK_SIZE];
1758         char *          names[BACKTRACE_STACK_SIZE];
1759         char            namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
1760
1761         int             i;
1762         int             levels;
1763
1764         ZERO_ARRAY(addrs);
1765         ZERO_ARRAY(names);
1766         ZERO_ARRAY(namebuf);
1767
1768         /* We need to be root so we can open our /proc entry to walk
1769          * our stack. It also helps when we want to dump core.
1770          */
1771         become_root();
1772
1773         for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
1774                 names[i] = namebuf + (i * NAMESIZE);
1775         }
1776
1777         levels = trace_back_stack(0, addrs, names,
1778                         BACKTRACE_STACK_SIZE, NAMESIZE - 1);
1779
1780         DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
1781         for (i = 0; i < levels; i++) {
1782                 DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
1783         }
1784 #undef NAMESIZE
1785
1786 #else
1787         DEBUG(0, ("unable to produce a stack trace on this platform\n"));
1788 #endif
1789 }
1790
1791 /*******************************************************************
1792   A readdir wrapper which just returns the file name.
1793  ********************************************************************/
1794
1795 const char *readdirname(SMB_STRUCT_DIR *p)
1796 {
1797         SMB_STRUCT_DIRENT *ptr;
1798         char *dname;
1799
1800         if (!p)
1801                 return(NULL);
1802   
1803         ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
1804         if (!ptr)
1805                 return(NULL);
1806
1807         dname = ptr->d_name;
1808
1809 #ifdef NEXT2
1810         if (telldir(p) < 0)
1811                 return(NULL);
1812 #endif
1813
1814 #ifdef HAVE_BROKEN_READDIR_NAME
1815         /* using /usr/ucb/cc is BAD */
1816         dname = dname - 2;
1817 #endif
1818
1819         {
1820                 static pstring buf;
1821                 int len = NAMLEN(ptr);
1822                 memcpy(buf, dname, len);
1823                 buf[len] = 0;
1824                 dname = buf;
1825         }
1826
1827         return(dname);
1828 }
1829
1830 /*******************************************************************
1831  Utility function used to decide if the last component 
1832  of a path matches a (possibly wildcarded) entry in a namelist.
1833 ********************************************************************/
1834
1835 BOOL is_in_path(const char *name, name_compare_entry *namelist, BOOL case_sensitive)
1836 {
1837         pstring last_component;
1838         char *p;
1839
1840         /* if we have no list it's obviously not in the path */
1841         if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
1842                 return False;
1843         }
1844
1845         DEBUG(8, ("is_in_path: %s\n", name));
1846
1847         /* Get the last component of the unix name. */
1848         p = strrchr_m(name, '/');
1849         pstrcpy(last_component, p ? ++p : name);
1850
1851         for(; namelist->name != NULL; namelist++) {
1852                 if(namelist->is_wild) {
1853                         if (mask_match(last_component, namelist->name, case_sensitive)) {
1854                                 DEBUG(8,("is_in_path: mask match succeeded\n"));
1855                                 return True;
1856                         }
1857                 } else {
1858                         if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
1859                                                 (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0))) {
1860                                 DEBUG(8,("is_in_path: match succeeded\n"));
1861                                 return True;
1862                         }
1863                 }
1864         }
1865         DEBUG(8,("is_in_path: match not found\n"));
1866  
1867         return False;
1868 }
1869
1870 /*******************************************************************
1871  Strip a '/' separated list into an array of 
1872  name_compare_enties structures suitable for 
1873  passing to is_in_path(). We do this for
1874  speed so we can pre-parse all the names in the list 
1875  and don't do it for each call to is_in_path().
1876  namelist is modified here and is assumed to be 
1877  a copy owned by the caller.
1878  We also check if the entry contains a wildcard to
1879  remove a potentially expensive call to mask_match
1880  if possible.
1881 ********************************************************************/
1882  
1883 void set_namearray(name_compare_entry **ppname_array, char *namelist)
1884 {
1885         char *name_end;
1886         char *nameptr = namelist;
1887         int num_entries = 0;
1888         int i;
1889
1890         (*ppname_array) = NULL;
1891
1892         if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0'))) 
1893                 return;
1894
1895         /* We need to make two passes over the string. The
1896                 first to count the number of elements, the second
1897                 to split it.
1898         */
1899
1900         while(*nameptr) {
1901                 if ( *nameptr == '/' ) {
1902                         /* cope with multiple (useless) /s) */
1903                         nameptr++;
1904                         continue;
1905                 }
1906                 /* find the next / */
1907                 name_end = strchr_m(nameptr, '/');
1908
1909                 /* oops - the last check for a / didn't find one. */
1910                 if (name_end == NULL)
1911                         break;
1912
1913                 /* next segment please */
1914                 nameptr = name_end + 1;
1915                 num_entries++;
1916         }
1917
1918         if(num_entries == 0)
1919                 return;
1920
1921         if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) {
1922                 DEBUG(0,("set_namearray: malloc fail\n"));
1923                 return;
1924         }
1925
1926         /* Now copy out the names */
1927         nameptr = namelist;
1928         i = 0;
1929         while(*nameptr) {
1930                 if ( *nameptr == '/' ) {
1931                         /* cope with multiple (useless) /s) */
1932                         nameptr++;
1933                         continue;
1934                 }
1935                 /* find the next / */
1936                 if ((name_end = strchr_m(nameptr, '/')) != NULL)
1937                         *name_end = 0;
1938
1939                 /* oops - the last check for a / didn't find one. */
1940                 if(name_end == NULL) 
1941                         break;
1942
1943                 (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
1944                 if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) {
1945                         DEBUG(0,("set_namearray: malloc fail (1)\n"));
1946                         return;
1947                 }
1948
1949                 /* next segment please */
1950                 nameptr = name_end + 1;
1951                 i++;
1952         }
1953   
1954         (*ppname_array)[i].name = NULL;
1955
1956         return;
1957 }
1958
1959 /****************************************************************************
1960  Routine to free a namearray.
1961 ****************************************************************************/
1962
1963 void free_namearray(name_compare_entry *name_array)
1964 {
1965         int i;
1966
1967         if(name_array == NULL)
1968                 return;
1969
1970         for(i=0; name_array[i].name!=NULL; i++)
1971                 SAFE_FREE(name_array[i].name);
1972         SAFE_FREE(name_array);
1973 }
1974
1975 #undef DBGC_CLASS
1976 #define DBGC_CLASS DBGC_LOCKING
1977
1978 /****************************************************************************
1979  Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
1980  is dealt with in posix.c
1981  Returns True if the lock was granted, False otherwise.
1982 ****************************************************************************/
1983
1984 BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
1985 {
1986         SMB_STRUCT_FLOCK lock;
1987         int ret;
1988
1989         DEBUG(8,("fcntl_lock fd=%d op=%d offset=%.0f count=%.0f type=%d\n",
1990                 fd,op,(double)offset,(double)count,type));
1991
1992         lock.l_type = type;
1993         lock.l_whence = SEEK_SET;
1994         lock.l_start = offset;
1995         lock.l_len = count;
1996         lock.l_pid = 0;
1997
1998         ret = sys_fcntl_ptr(fd,op,&lock);
1999
2000         if (ret == -1) {
2001                 int sav = errno;
2002                 DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
2003                         (double)offset,(double)count,op,type,strerror(errno)));
2004                 errno = sav;
2005                 return False;
2006         }
2007
2008         /* everything went OK */
2009         DEBUG(8,("fcntl_lock: Lock call successful\n"));
2010
2011         return True;
2012 }
2013
2014 /****************************************************************************
2015  Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
2016  is dealt with in posix.c
2017  Returns True if we have information regarding this lock region (and returns
2018  F_UNLCK in *ptype if the region is unlocked). False if the call failed.
2019 ****************************************************************************/
2020
2021 BOOL fcntl_getlock(int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
2022 {
2023         SMB_STRUCT_FLOCK lock;
2024         int ret;
2025
2026         DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
2027                     fd,(double)*poffset,(double)*pcount,*ptype));
2028
2029         lock.l_type = *ptype;
2030         lock.l_whence = SEEK_SET;
2031         lock.l_start = *poffset;
2032         lock.l_len = *pcount;
2033         lock.l_pid = 0;
2034
2035         ret = sys_fcntl_ptr(fd,SMB_F_GETLK,&lock);
2036
2037         if (ret == -1) {
2038                 int sav = errno;
2039                 DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
2040                         (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
2041                 errno = sav;
2042                 return False;
2043         }
2044
2045         *ptype = lock.l_type;
2046         *poffset = lock.l_start;
2047         *pcount = lock.l_len;
2048         *ppid = lock.l_pid;
2049         
2050         DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
2051                         fd, (int)lock.l_type, (unsigned int)lock.l_pid));
2052         return True;
2053 }
2054
2055 #undef DBGC_CLASS
2056 #define DBGC_CLASS DBGC_ALL
2057
2058 /*******************************************************************
2059  Is the name specified one of my netbios names.
2060  Returns true if it is equal, false otherwise.
2061 ********************************************************************/
2062
2063 BOOL is_myname(const char *s)
2064 {
2065         int n;
2066         BOOL ret = False;
2067
2068         for (n=0; my_netbios_names(n); n++) {
2069                 if (strequal(my_netbios_names(n), s)) {
2070                         ret=True;
2071                         break;
2072                 }
2073         }
2074         DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
2075         return(ret);
2076 }
2077
2078 BOOL is_myname_or_ipaddr(const char *s)
2079 {
2080         fstring name, dnsname;
2081         char *servername;
2082
2083         if ( !s )
2084                 return False;
2085
2086         /* santize the string from '\\name' */
2087
2088         fstrcpy( name, s );
2089
2090         servername = strrchr_m( name, '\\' );
2091         if ( !servername )
2092                 servername = name;
2093         else
2094                 servername++;
2095
2096         /* optimize for the common case */
2097
2098         if (strequal(servername, global_myname())) 
2099                 return True;
2100
2101         /* check for an alias */
2102
2103         if (is_myname(servername))
2104                 return True;
2105
2106         /* check for loopback */
2107
2108         if (strequal(servername, "127.0.0.1")) 
2109                 return True;
2110
2111         if (strequal(servername, "localhost")) 
2112                 return True;
2113
2114         /* maybe it's my dns name */
2115
2116         if ( get_mydnsfullname( dnsname ) )
2117                 if ( strequal( servername, dnsname ) )
2118                         return True;
2119                 
2120         /* handle possible CNAME records */
2121
2122         if ( !is_ipaddress( servername ) ) {
2123                 /* use DNS to resolve the name, but only the first address */
2124                 struct hostent *hp;
2125
2126                 if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
2127                         struct in_addr return_ip;
2128                         putip( (char*)&return_ip, (char*)hp->h_addr );
2129                         fstrcpy( name, inet_ntoa( return_ip ) );
2130                         servername = name;
2131                 }       
2132         }
2133                 
2134         /* maybe its an IP address? */
2135         if (is_ipaddress(servername)) {
2136                 struct iface_struct nics[MAX_INTERFACES];
2137                 int i, n;
2138                 uint32 ip;
2139                 
2140                 ip = interpret_addr(servername);
2141                 if ((ip==0) || (ip==0xffffffff))
2142                         return False;
2143                         
2144                 n = get_interfaces(nics, MAX_INTERFACES);
2145                 for (i=0; i<n; i++) {
2146                         if (ip == nics[i].ip.s_addr)
2147                                 return True;
2148                 }
2149         }       
2150
2151         /* no match */
2152         return False;
2153 }
2154
2155 /*******************************************************************
2156  Is the name specified our workgroup/domain.
2157  Returns true if it is equal, false otherwise.
2158 ********************************************************************/
2159
2160 BOOL is_myworkgroup(const char *s)
2161 {
2162         BOOL ret = False;
2163
2164         if (strequal(s, lp_workgroup())) {
2165                 ret=True;
2166         }
2167
2168         DEBUG(8, ("is_myworkgroup(\"%s\") returns %d\n", s, ret));
2169         return(ret);
2170 }
2171
2172 /*******************************************************************
2173  we distinguish between 2K and XP by the "Native Lan Manager" string
2174    WinXP => "Windows 2002 5.1"
2175    WinXP 64bit => "Windows XP 5.2"
2176    Win2k => "Windows 2000 5.0"
2177    NT4   => "Windows NT 4.0" 
2178    Win9x => "Windows 4.0"
2179  Windows 2003 doesn't set the native lan manager string but 
2180  they do set the domain to "Windows 2003 5.2" (probably a bug).
2181 ********************************************************************/
2182
2183 void ra_lanman_string( const char *native_lanman )
2184 {       
2185         if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
2186                 set_remote_arch( RA_WINXP );
2187         else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
2188                 set_remote_arch( RA_WINXP );
2189         else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
2190                 set_remote_arch( RA_WIN2K3 );
2191 }
2192
2193 /*******************************************************************
2194  Set the horrid remote_arch string based on an enum.
2195 ********************************************************************/
2196
2197 void set_remote_arch(enum remote_arch_types type)
2198 {
2199         ra_type = type;
2200         switch( type ) {
2201         case RA_WFWG:
2202                 fstrcpy(remote_arch, "WfWg");
2203                 break;
2204         case RA_OS2:
2205                 fstrcpy(remote_arch, "OS2");
2206                 break;
2207         case RA_WIN95:
2208                 fstrcpy(remote_arch, "Win95");
2209                 break;
2210         case RA_WINNT:
2211                 fstrcpy(remote_arch, "WinNT");
2212                 break;
2213         case RA_WIN2K:
2214                 fstrcpy(remote_arch, "Win2K");
2215                 break;
2216         case RA_WINXP:
2217                 fstrcpy(remote_arch, "WinXP");
2218                 break;
2219         case RA_WIN2K3:
2220                 fstrcpy(remote_arch, "Win2K3");
2221                 break;
2222         case RA_VISTA:
2223                 fstrcpy(remote_arch, "Vista");
2224                 break;
2225         case RA_SAMBA:
2226                 fstrcpy(remote_arch,"Samba");
2227                 break;
2228         case RA_CIFSFS:
2229                 fstrcpy(remote_arch,"CIFSFS");
2230                 break;
2231         default:
2232                 ra_type = RA_UNKNOWN;
2233                 fstrcpy(remote_arch, "UNKNOWN");
2234                 break;
2235         }
2236
2237         DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n", remote_arch));
2238 }
2239
2240 /*******************************************************************
2241  Get the remote_arch type.
2242 ********************************************************************/
2243
2244 enum remote_arch_types get_remote_arch(void)
2245 {
2246         return ra_type;
2247 }
2248
2249 void print_asc(int level, const unsigned char *buf,int len)
2250 {
2251         int i;
2252         for (i=0;i<len;i++)
2253                 DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
2254 }
2255
2256 void dump_data(int level, const char *buf1,int len)
2257 {
2258         const unsigned char *buf = (const unsigned char *)buf1;
2259         int i=0;
2260         if (len<=0) return;
2261
2262         if (!DEBUGLVL(level)) return;
2263         
2264         DEBUGADD(level,("[%03X] ",i));
2265         for (i=0;i<len;) {
2266                 DEBUGADD(level,("%02X ",(int)buf[i]));
2267                 i++;
2268                 if (i%8 == 0) DEBUGADD(level,(" "));
2269                 if (i%16 == 0) {      
2270                         print_asc(level,&buf[i-16],8); DEBUGADD(level,(" "));
2271                         print_asc(level,&buf[i-8],8); DEBUGADD(level,("\n"));
2272                         if (i<len) DEBUGADD(level,("[%03X] ",i));
2273                 }
2274         }
2275         if (i%16) {
2276                 int n;
2277                 n = 16 - (i%16);
2278                 DEBUGADD(level,(" "));
2279                 if (n>8) DEBUGADD(level,(" "));
2280                 while (n--) DEBUGADD(level,("   "));
2281                 n = MIN(8,i%16);
2282                 print_asc(level,&buf[i-(i%16)],n); DEBUGADD(level,( " " ));
2283                 n = (i%16) - n;
2284                 if (n>0) print_asc(level,&buf[i-n],n); 
2285                 DEBUGADD(level,("\n"));    
2286         }       
2287 }
2288
2289 void dump_data_pw(const char *msg, const uchar * data, size_t len)
2290 {
2291 #ifdef DEBUG_PASSWORD
2292         DEBUG(11, ("%s", msg));
2293         if (data != NULL && len > 0)
2294         {
2295                 dump_data(11, (const char *)data, len);
2296         }
2297 #endif
2298 }
2299
2300 char *tab_depth(int depth)
2301 {
2302         static pstring spaces;
2303         memset(spaces, ' ', depth * 4);
2304         spaces[depth * 4] = 0;
2305         return spaces;
2306 }
2307
2308 /*****************************************************************************
2309  Provide a checksum on a string
2310
2311  Input:  s - the null-terminated character string for which the checksum
2312              will be calculated.
2313
2314   Output: The checksum value calculated for s.
2315 *****************************************************************************/
2316
2317 int str_checksum(const char *s)
2318 {
2319         int res = 0;
2320         int c;
2321         int i=0;
2322         
2323         while(*s) {
2324                 c = *s;
2325                 res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
2326                 s++;
2327                 i++;
2328         }
2329         return(res);
2330 }
2331
2332 /*****************************************************************
2333  Zero a memory area then free it. Used to catch bugs faster.
2334 *****************************************************************/  
2335
2336 void zero_free(void *p, size_t size)
2337 {
2338         memset(p, 0, size);
2339         SAFE_FREE(p);
2340 }
2341
2342 /*****************************************************************
2343  Set our open file limit to a requested max and return the limit.
2344 *****************************************************************/  
2345
2346 int set_maxfiles(int requested_max)
2347 {
2348 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
2349         struct rlimit rlp;
2350         int saved_current_limit;
2351
2352         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
2353                 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
2354                         strerror(errno) ));
2355                 /* just guess... */
2356                 return requested_max;
2357         }
2358
2359         /* 
2360          * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
2361          * account for the extra fd we need 
2362          * as well as the log files and standard
2363          * handles etc. Save the limit we want to set in case
2364          * we are running on an OS that doesn't support this limit (AIX)
2365          * which always returns RLIM_INFINITY for rlp.rlim_max.
2366          */
2367
2368         /* Try raising the hard (max) limit to the requested amount. */
2369
2370 #if defined(RLIM_INFINITY)
2371         if (rlp.rlim_max != RLIM_INFINITY) {
2372                 int orig_max = rlp.rlim_max;
2373
2374                 if ( rlp.rlim_max < requested_max )
2375                         rlp.rlim_max = requested_max;
2376
2377                 /* This failing is not an error - many systems (Linux) don't
2378                         support our default request of 10,000 open files. JRA. */
2379
2380                 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
2381                         DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n", 
2382                                 (int)rlp.rlim_max, strerror(errno) ));
2383
2384                         /* Set failed - restore original value from get. */
2385                         rlp.rlim_max = orig_max;
2386                 }
2387         }
2388 #endif
2389
2390         /* Now try setting the soft (current) limit. */
2391
2392         saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
2393
2394         if(setrlimit(RLIMIT_NOFILE, &rlp)) {
2395                 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n", 
2396                         (int)rlp.rlim_cur, strerror(errno) ));
2397                 /* just guess... */
2398                 return saved_current_limit;
2399         }
2400
2401         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
2402                 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
2403                         strerror(errno) ));
2404                 /* just guess... */
2405                 return saved_current_limit;
2406     }
2407
2408 #if defined(RLIM_INFINITY)
2409         if(rlp.rlim_cur == RLIM_INFINITY)
2410                 return saved_current_limit;
2411 #endif
2412
2413         if((int)rlp.rlim_cur > saved_current_limit)
2414                 return saved_current_limit;
2415
2416         return rlp.rlim_cur;
2417 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
2418         /*
2419          * No way to know - just guess...
2420          */
2421         return requested_max;
2422 #endif
2423 }
2424
2425 /*****************************************************************
2426  Possibly replace mkstemp if it is broken.
2427 *****************************************************************/  
2428
2429 int smb_mkstemp(char *name_template)
2430 {
2431 #if HAVE_SECURE_MKSTEMP
2432         return mkstemp(name_template);
2433 #else
2434         /* have a reasonable go at emulating it. Hope that
2435            the system mktemp() isn't completly hopeless */
2436         char *p = mktemp(name_template);
2437         if (!p)
2438                 return -1;
2439         return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
2440 #endif
2441 }
2442
2443 /*****************************************************************
2444  malloc that aborts with smb_panic on fail or zero size.
2445  *****************************************************************/  
2446
2447 void *smb_xmalloc_array(size_t size, unsigned int count)
2448 {
2449         void *p;
2450         if (size == 0)
2451                 smb_panic("smb_xmalloc_array: called with zero size.\n");
2452         if (count >= MAX_ALLOC_SIZE/size) {
2453                 smb_panic("smb_xmalloc: alloc size too large.\n");
2454         }
2455         if ((p = SMB_MALLOC(size*count)) == NULL) {
2456                 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
2457                         (unsigned long)size, (unsigned long)count));
2458                 smb_panic("smb_xmalloc_array: malloc fail.\n");
2459         }
2460         return p;
2461 }
2462
2463 /**
2464  Memdup with smb_panic on fail.
2465 **/
2466
2467 void *smb_xmemdup(const void *p, size_t size)
2468 {
2469         void *p2;
2470         p2 = SMB_XMALLOC_ARRAY(unsigned char,size);
2471         memcpy(p2, p, size);
2472         return p2;
2473 }
2474
2475 /**
2476  strdup that aborts on malloc fail.
2477 **/
2478
2479 char *smb_xstrdup(const char *s)
2480 {
2481 #if defined(PARANOID_MALLOC_CHECKER)
2482 #ifdef strdup
2483 #undef strdup
2484 #endif
2485 #endif
2486
2487 #ifndef HAVE_STRDUP
2488 #define strdup rep_strdup
2489 #endif
2490
2491         char *s1 = strdup(s);
2492 #if defined(PARANOID_MALLOC_CHECKER)
2493 #ifdef strdup
2494 #undef strdup
2495 #endif
2496 #define strdup(s) __ERROR_DONT_USE_STRDUP_DIRECTLY
2497 #endif
2498         if (!s1)
2499                 smb_panic("smb_xstrdup: malloc fail\n");
2500         return s1;
2501
2502 }
2503
2504 /**
2505  strndup that aborts on malloc fail.
2506 **/
2507
2508 char *smb_xstrndup(const char *s, size_t n)
2509 {
2510 #if defined(PARANOID_MALLOC_CHECKER)
2511 #ifdef strndup
2512 #undef strndup
2513 #endif
2514 #endif
2515
2516 #if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP))
2517 #undef HAVE_STRNDUP
2518 #define strndup rep_strndup
2519 #endif
2520
2521         char *s1 = strndup(s, n);
2522 #if defined(PARANOID_MALLOC_CHECKER)
2523 #ifdef strndup
2524 #undef strndup
2525 #endif
2526 #define strndup(s,n) __ERROR_DONT_USE_STRNDUP_DIRECTLY
2527 #endif
2528         if (!s1)
2529                 smb_panic("smb_xstrndup: malloc fail\n");
2530         return s1;
2531 }
2532
2533 /*
2534   vasprintf that aborts on malloc fail
2535 */
2536
2537  int smb_xvasprintf(char **ptr, const char *format, va_list ap)
2538 {
2539         int n;
2540         va_list ap2;
2541
2542         VA_COPY(ap2, ap);
2543
2544         n = vasprintf(ptr, format, ap2);
2545         if (n == -1 || ! *ptr)
2546                 smb_panic("smb_xvasprintf: out of memory");
2547         return n;
2548 }
2549
2550 /*****************************************************************
2551  Like strdup but for memory.
2552 *****************************************************************/  
2553
2554 void *memdup(const void *p, size_t size)
2555 {
2556         void *p2;
2557         if (size == 0)
2558                 return NULL;
2559         p2 = SMB_MALLOC(size);
2560         if (!p2)
2561                 return NULL;
2562         memcpy(p2, p, size);
2563         return p2;
2564 }
2565
2566 /*****************************************************************
2567  Get local hostname and cache result.
2568 *****************************************************************/  
2569
2570 char *myhostname(void)
2571 {
2572         static pstring ret;
2573         if (ret[0] == 0)
2574                 get_myname(ret);
2575         return ret;
2576 }
2577
2578 /*****************************************************************
2579  A useful function for returning a path in the Samba lock directory.
2580 *****************************************************************/  
2581
2582 char *lock_path(const char *name)
2583 {
2584         static pstring fname;
2585
2586         pstrcpy(fname,lp_lockdir());
2587         trim_char(fname,'\0','/');
2588         
2589         if (!directory_exist(fname,NULL))
2590                 mkdir(fname,0755);
2591         
2592         pstrcat(fname,"/");
2593         pstrcat(fname,name);
2594
2595         return fname;
2596 }
2597
2598 /*****************************************************************
2599  A useful function for returning a path in the Samba pid directory.
2600 *****************************************************************/
2601
2602 char *pid_path(const char *name)
2603 {
2604         static pstring fname;
2605
2606         pstrcpy(fname,lp_piddir());
2607         trim_char(fname,'\0','/');
2608
2609         if (!directory_exist(fname,NULL))
2610                 mkdir(fname,0755);
2611
2612         pstrcat(fname,"/");
2613         pstrcat(fname,name);
2614
2615         return fname;
2616 }
2617
2618 /**
2619  * @brief Returns an absolute path to a file in the Samba lib directory.
2620  *
2621  * @param name File to find, relative to LIBDIR.
2622  *
2623  * @retval Pointer to a static #pstring containing the full path.
2624  **/
2625
2626 char *lib_path(const char *name)
2627 {
2628         static pstring fname;
2629         fstr_sprintf(fname, "%s/%s", dyn_LIBDIR, name);
2630         return fname;
2631 }
2632
2633 /**
2634  * @brief Returns the platform specific shared library extension.
2635  *
2636  * @retval Pointer to a static #fstring containing the extension.
2637  **/
2638
2639 const char *shlib_ext(void)
2640 {
2641   return dyn_SHLIBEXT;
2642 }
2643
2644 /*******************************************************************
2645  Given a filename - get its directory name
2646  NB: Returned in static storage.  Caveats:
2647  o  Not safe in thread environment.
2648  o  Caller must not free.
2649  o  If caller wishes to preserve, they should copy.
2650 ********************************************************************/
2651
2652 char *parent_dirname(const char *path)
2653 {
2654         static pstring dirpath;
2655         char *p;
2656
2657         if (!path)
2658                 return(NULL);
2659
2660         pstrcpy(dirpath, path);
2661         p = strrchr_m(dirpath, '/');  /* Find final '/', if any */
2662         if (!p) {
2663                 pstrcpy(dirpath, ".");    /* No final "/", so dir is "." */
2664         } else {
2665                 if (p == dirpath)
2666                         ++p;    /* For root "/", leave "/" in place */
2667                 *p = '\0';
2668         }
2669         return dirpath;
2670 }
2671
2672 BOOL parent_dirname_talloc(TALLOC_CTX *mem_ctx, const char *dir,
2673                            char **parent, const char **name)
2674 {
2675         char *p;
2676         ptrdiff_t len;
2677  
2678         p = strrchr_m(dir, '/'); /* Find final '/', if any */
2679
2680         if (p == NULL) {
2681                 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
2682                         return False;
2683                 }
2684                 if (name) {
2685                         *name = "";
2686                 }
2687                 return True;
2688         }
2689
2690         len = p-dir;
2691
2692         if (!(*parent = TALLOC_ARRAY(mem_ctx, char, len+1))) {
2693                 return False;
2694         }
2695         memcpy(*parent, dir, len);
2696         (*parent)[len] = '\0';
2697
2698         if (name) {
2699                 *name = p+1;
2700         }
2701         return True;
2702 }
2703
2704 /*******************************************************************
2705  Determine if a pattern contains any Microsoft wildcard characters.
2706 *******************************************************************/
2707
2708 BOOL ms_has_wild(const char *s)
2709 {
2710         char c;
2711
2712         if (lp_posix_pathnames()) {
2713                 /* With posix pathnames no characters are wild. */
2714                 return False;
2715         }
2716
2717         while ((c = *s++)) {
2718                 switch (c) {
2719                 case '*':
2720                 case '?':
2721                 case '<':
2722                 case '>':
2723                 case '"':
2724                         return True;
2725                 }
2726         }
2727         return False;
2728 }
2729
2730 BOOL ms_has_wild_w(const smb_ucs2_t *s)
2731 {
2732         smb_ucs2_t c;
2733         if (!s) return False;
2734         while ((c = *s++)) {
2735                 switch (c) {
2736                 case UCS2_CHAR('*'):
2737                 case UCS2_CHAR('?'):
2738                 case UCS2_CHAR('<'):
2739                 case UCS2_CHAR('>'):
2740                 case UCS2_CHAR('"'):
2741                         return True;
2742                 }
2743         }
2744         return False;
2745 }
2746
2747 /*******************************************************************
2748  A wrapper that handles case sensitivity and the special handling
2749  of the ".." name.
2750 *******************************************************************/
2751
2752 BOOL mask_match(const char *string, char *pattern, BOOL is_case_sensitive)
2753 {
2754         if (strcmp(string,"..") == 0)
2755                 string = ".";
2756         if (strcmp(pattern,".") == 0)
2757                 return False;
2758         
2759         return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
2760 }
2761
2762 /*******************************************************************
2763  A wrapper that handles case sensitivity and the special handling
2764  of the ".." name. Varient that is only called by old search code which requires
2765  pattern translation.
2766 *******************************************************************/
2767
2768 BOOL mask_match_search(const char *string, char *pattern, BOOL is_case_sensitive)
2769 {
2770         if (strcmp(string,"..") == 0)
2771                 string = ".";
2772         if (strcmp(pattern,".") == 0)
2773                 return False;
2774         
2775         return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
2776 }
2777
2778 /*******************************************************************
2779  A wrapper that handles a list of patters and calls mask_match()
2780  on each.  Returns True if any of the patterns match.
2781 *******************************************************************/
2782
2783 BOOL mask_match_list(const char *string, char **list, int listLen, BOOL is_case_sensitive)
2784 {
2785        while (listLen-- > 0) {
2786                if (mask_match(string, *list++, is_case_sensitive))
2787                        return True;
2788        }
2789        return False;
2790 }
2791
2792 /*********************************************************
2793  Recursive routine that is called by unix_wild_match.
2794 *********************************************************/
2795
2796 static BOOL unix_do_match(const char *regexp, const char *str)
2797 {
2798         const char *p;
2799
2800         for( p = regexp; *p && *str; ) {
2801
2802                 switch(*p) {
2803                         case '?':
2804                                 str++;
2805                                 p++;
2806                                 break;
2807
2808                         case '*':
2809
2810                                 /*
2811                                  * Look for a character matching 
2812                                  * the one after the '*'.
2813                                  */
2814                                 p++;
2815                                 if(!*p)
2816                                         return True; /* Automatic match */
2817                                 while(*str) {
2818
2819                                         while(*str && (*p != *str))
2820                                                 str++;
2821
2822                                         /*
2823                                          * Patch from weidel@multichart.de. In the case of the regexp
2824                                          * '*XX*' we want to ensure there are at least 2 'X' characters
2825                                          * in the string after the '*' for a match to be made.
2826                                          */
2827
2828                                         {
2829                                                 int matchcount=0;
2830
2831                                                 /*
2832                                                  * Eat all the characters that match, but count how many there were.
2833                                                  */
2834
2835                                                 while(*str && (*p == *str)) {
2836                                                         str++;
2837                                                         matchcount++;
2838                                                 }
2839
2840                                                 /*
2841                                                  * Now check that if the regexp had n identical characters that
2842                                                  * matchcount had at least that many matches.
2843                                                  */
2844
2845                                                 while ( *(p+1) && (*(p+1) == *p)) {
2846                                                         p++;
2847                                                         matchcount--;
2848                                                 }
2849
2850                                                 if ( matchcount <= 0 )
2851                                                         return False;
2852                                         }
2853
2854                                         str--; /* We've eaten the match char after the '*' */
2855
2856                                         if(unix_do_match(p, str))
2857                                                 return True;
2858
2859                                         if(!*str)
2860                                                 return False;
2861                                         else
2862                                                 str++;
2863                                 }
2864                                 return False;
2865
2866                         default:
2867                                 if(*str != *p)
2868                                         return False;
2869                                 str++;
2870                                 p++;
2871                                 break;
2872                 }
2873         }
2874
2875         if(!*p && !*str)
2876                 return True;
2877
2878         if (!*p && str[0] == '.' && str[1] == 0)
2879                 return(True);
2880   
2881         if (!*str && *p == '?') {
2882                 while (*p == '?')
2883                         p++;
2884                 return(!*p);
2885         }
2886
2887         if(!*str && (*p == '*' && p[1] == '\0'))
2888                 return True;
2889
2890         return False;
2891 }
2892
2893 /*******************************************************************
2894  Simple case insensitive interface to a UNIX wildcard matcher.
2895  Returns True if match, False if not.
2896 *******************************************************************/
2897
2898 BOOL unix_wild_match(const char *pattern, const char *string)
2899 {
2900         pstring p2, s2;
2901         char *p;
2902
2903         pstrcpy(p2, pattern);
2904         pstrcpy(s2, string);
2905         strlower_m(p2);
2906         strlower_m(s2);
2907
2908         /* Remove any *? and ** from the pattern as they are meaningless */
2909         for(p = p2; *p; p++)
2910                 while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
2911                         pstrcpy( &p[1], &p[2]);
2912  
2913         if (strequal(p2,"*"))
2914                 return True;
2915
2916         return unix_do_match(p2, s2);
2917 }
2918
2919 /**********************************************************************
2920  Converts a name to a fully qualified domain name.
2921  Returns True if lookup succeeded, False if not (then fqdn is set to name)
2922 ***********************************************************************/
2923                                                                                                                                                    
2924 BOOL name_to_fqdn(fstring fqdn, const char *name)
2925 {
2926         struct hostent *hp = sys_gethostbyname(name);
2927
2928         if ( hp && hp->h_name && *hp->h_name ) {
2929                 char *full = NULL;
2930
2931                 /* find out if the fqdn is returned as an alias
2932                  * to cope with /etc/hosts files where the first
2933                  * name is not the fqdn but the short name */
2934                 if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
2935                         int i;
2936                         for (i = 0; hp->h_aliases[i]; i++) {
2937                                 if (strchr_m(hp->h_aliases[i], '.')) {
2938                                         full = hp->h_aliases[i];
2939                                         break;
2940                                 }
2941                         }
2942                 }
2943                 if (full && (StrCaseCmp(full, "localhost.localdomain") == 0)) {
2944                         DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
2945                         DEBUGADD(1, ("    Specifing the machine hostname for address 127.0.0.1 may lead\n"));
2946                         DEBUGADD(1, ("    to Kerberos authentication problems as localhost.localdomain\n"));
2947                         DEBUGADD(1, ("    may end up being used instead of the real machine FQDN.\n"));
2948                         full = hp->h_name;
2949                 }
2950                         
2951                 if (!full) {
2952                         full = hp->h_name;
2953                 }
2954
2955                 DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
2956                 fstrcpy(fqdn, full);
2957                 return True;
2958         } else {
2959                 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
2960                 fstrcpy(fqdn, name);
2961                 return False;
2962         }
2963 }
2964
2965 /**********************************************************************
2966  Extension to talloc_get_type: Abort on type mismatch
2967 ***********************************************************************/
2968
2969 void *talloc_check_name_abort(const void *ptr, const char *name)
2970 {
2971         void *result;
2972
2973         result = talloc_check_name(ptr, name);
2974         if (result != NULL)
2975                 return result;
2976
2977         DEBUG(0, ("Talloc type mismatch, expected %s, got %s\n",
2978                   name, talloc_get_name(ptr)));
2979         smb_panic("aborting");
2980         /* Keep the compiler happy */
2981         return NULL;
2982 }
2983
2984
2985 #ifdef __INSURE__
2986
2987 /*******************************************************************
2988 This routine is a trick to immediately catch errors when debugging
2989 with insure. A xterm with a gdb is popped up when insure catches
2990 a error. It is Linux specific.
2991 ********************************************************************/
2992
2993 int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
2994 {
2995         static int (*fn)();
2996         int ret;
2997         char pidstr[10];
2998         /* you can get /usr/bin/backtrace from 
2999            http://samba.org/ftp/unpacked/junkcode/backtrace */
3000         pstring cmd = "/usr/bin/backtrace %d";
3001
3002         slprintf(pidstr, sizeof(pidstr)-1, "%d", sys_getpid());
3003         pstring_sub(cmd, "%d", pidstr);
3004
3005         if (!fn) {
3006                 static void *h;
3007                 h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
3008                 fn = dlsym(h, "_Insure_trap_error");
3009
3010                 if (!h || h == _Insure_trap_error) {
3011                         h = dlopen("/usr/local/parasoft/lib.linux2/libinsure.so", RTLD_LAZY);
3012                         fn = dlsym(h, "_Insure_trap_error");
3013                 }               
3014         }
3015
3016         ret = fn(a1, a2, a3, a4, a5, a6);
3017
3018         system(cmd);
3019
3020         return ret;
3021 }
3022 #endif
3023
3024 uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
3025 {
3026         switch (share_access & ~FILE_SHARE_DELETE) {
3027                 case FILE_SHARE_NONE:
3028                         return DENY_ALL;
3029                 case FILE_SHARE_READ:
3030                         return DENY_WRITE;
3031                 case FILE_SHARE_WRITE:
3032                         return DENY_READ;
3033                 case FILE_SHARE_READ|FILE_SHARE_WRITE:
3034                         return DENY_NONE;
3035         }
3036         if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
3037                 return DENY_DOS;
3038         } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
3039                 return DENY_FCB;
3040         }
3041
3042         return (uint32)-1;
3043 }
3044
3045 pid_t procid_to_pid(const struct process_id *proc)
3046 {
3047         return proc->pid;
3048 }
3049
3050 struct process_id pid_to_procid(pid_t pid)
3051 {
3052         struct process_id result;
3053         result.pid = pid;
3054         return result;
3055 }
3056
3057 struct process_id procid_self(void)
3058 {
3059         return pid_to_procid(sys_getpid());
3060 }
3061
3062 struct server_id server_id_self(void)
3063 {
3064         struct server_id id;
3065         id.id = procid_self();
3066         return id;
3067 }
3068
3069 BOOL procid_equal(const struct process_id *p1, const struct process_id *p2)
3070 {
3071         return (p1->pid == p2->pid);
3072 }
3073
3074 BOOL cluster_id_equal(const struct server_id *id1,
3075                       const struct server_id *id2)
3076 {
3077         return procid_equal(&id1->id, &id2->id);
3078 }
3079
3080 BOOL procid_is_me(const struct process_id *pid)
3081 {
3082         return (pid->pid == sys_getpid());
3083 }
3084
3085 struct process_id interpret_pid(const char *pid_string)
3086 {
3087         return pid_to_procid(atoi(pid_string));
3088 }
3089
3090 char *procid_str_static(const struct process_id *pid)
3091 {
3092         static fstring str;
3093         fstr_sprintf(str, "%d", pid->pid);
3094         return str;
3095 }
3096
3097 char *procid_str(TALLOC_CTX *mem_ctx, const struct process_id *pid)
3098 {
3099         return talloc_strdup(mem_ctx, procid_str_static(pid));
3100 }
3101
3102 BOOL procid_valid(const struct process_id *pid)
3103 {
3104         return (pid->pid != -1);
3105 }
3106
3107 BOOL procid_is_local(const struct process_id *pid)
3108 {
3109         return True;
3110 }
3111
3112 int this_is_smp(void)
3113 {
3114 #if defined(HAVE_SYSCONF)
3115
3116 #if defined(SYSCONF_SC_NPROC_ONLN)
3117         return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0;
3118 #elif defined(SYSCONF_SC_NPROCESSORS_ONLN)
3119         return (sysconf(_SC_NPROCESSORS_ONLN) > 1) ? 1 : 0;
3120 #else
3121         return 0;
3122 #endif
3123
3124 #else
3125         return 0;
3126 #endif
3127 }