got rid of mem_man
[ira/wip.git] / source3 / lib / util.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Samba utility functions
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
25 #ifdef WITH_NISPLUS_HOME
26 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
27 /*
28  * The following lines are needed due to buggy include files
29  * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
30  * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
31  * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
32  * an enum in /usr/include/rpcsvc/nis.h.
33  */
34
35 #if defined(GROUP)
36 #undef GROUP
37 #endif
38
39 #if defined(GROUP_OBJ)
40 #undef GROUP_OBJ
41 #endif
42
43 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
44
45 #include <rpcsvc/nis.h>
46
47 #else /* !WITH_NISPLUS_HOME */
48
49 #include "rpcsvc/ypclnt.h"
50
51 #endif /* WITH_NISPLUS_HOME */
52 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
53
54 #ifdef WITH_SSL
55 #include <ssl.h>
56 #undef Realloc  /* SSLeay defines this and samba has a function of this name */
57 extern SSL  *ssl;
58 extern int  sslFd;
59 #endif  /* WITH_SSL */
60
61 pstring scope = "";
62
63 extern int DEBUGLEVEL;
64
65 int Protocol = PROTOCOL_COREPLUS;
66
67 /* a default finfo structure to ensure all fields are sensible */
68 file_info def_finfo = {-1,0,0,0,0,0,0,""};
69
70 /* the client file descriptor */
71 extern int Client;
72
73 /* this is used by the chaining code */
74 int chain_size = 0;
75
76 int trans_num = 0;
77
78 /*
79    case handling on filenames 
80 */
81 int case_default = CASE_LOWER;
82
83 /* the following control case operations - they are put here so the
84    client can link easily */
85 BOOL case_sensitive;
86 BOOL case_preserve;
87 BOOL use_mangled_map = False;
88 BOOL short_case_preserve;
89 BOOL case_mangle;
90
91 fstring remote_machine="";
92 fstring local_machine="";
93 fstring remote_arch="UNKNOWN";
94 static enum remote_arch_types ra_type = RA_UNKNOWN;
95 fstring remote_proto="UNKNOWN";
96 pstring user_socket_options=DEFAULT_SOCKET_OPTIONS;   
97
98 pstring sesssetup_user="";
99 pstring samlogon_user="";
100
101 BOOL sam_logon_in_ssb = False;
102
103 pstring global_myname = "";
104 fstring global_myworkgroup = "";
105 char **my_netbios_names;
106
107 static char *filename_dos(char *path,char *buf);
108
109
110
111 /****************************************************************************
112   find a suitable temporary directory. The result should be copied immediately
113   as it may be overwritten by a subsequent call
114   ****************************************************************************/
115 char *tmpdir(void)
116 {
117   char *p;
118   if ((p = getenv("TMPDIR"))) {
119     return p;
120   }
121   return "/tmp";
122 }
123
124 /****************************************************************************
125 determine whether we are in the specified group
126 ****************************************************************************/
127
128 BOOL in_group(gid_t group, gid_t current_gid, int ngroups, gid_t *groups)
129 {
130         int i;
131
132         if (group == current_gid) return(True);
133
134         for (i=0;i<ngroups;i++)
135                 if (group == groups[i])
136                         return(True);
137
138         return(False);
139 }
140
141
142 /****************************************************************************
143 like atoi but gets the value up to the separater character
144 ****************************************************************************/
145 char *Atoic(char *p, int *n, char *c)
146 {
147         if (!isdigit((int)*p))
148         {
149                 DEBUG(5, ("Atoic: malformed number\n"));
150                 return NULL;
151         }
152
153         (*n) = atoi(p);
154
155         while ((*p) && isdigit((int)*p))
156         {
157                 p++;
158         }
159
160         if (strchr(c, *p) == NULL)
161         {
162                 DEBUG(5, ("Atoic: no separator characters (%s) not found\n", c));
163                 return NULL;
164         }
165
166         return p;
167 }
168
169 /*************************************************************************
170  reads a list of numbers
171  *************************************************************************/
172 char *get_numlist(char *p, uint32 **num, int *count)
173 {
174         int val;
175
176         if (num == NULL || count == NULL)
177         {
178                 return NULL;
179         }
180
181         (*count) = 0;
182         (*num  ) = NULL;
183
184         while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':')
185         {
186                 (*num) = Realloc((*num), ((*count)+1) * sizeof(uint32));
187                 if ((*num) == NULL)
188                 {
189                         return NULL;
190                 }
191                 (*num)[(*count)] = val;
192                 (*count)++;
193                 p++;
194         }
195
196         return p;
197 }
198
199 /*******************************************************************
200 copy an IP address from one buffer to another
201 ********************************************************************/
202 void putip(void *dest,void *src)
203 {
204   memcpy(dest,src,4);
205 }
206
207
208 #define TRUNCATE_NETBIOS_NAME 1
209
210 /*******************************************************************
211  convert, possibly using a stupid microsoft-ism which has destroyed
212  the transport independence of netbios (for CIFS vendors that usually
213  use the Win95-type methods, not for NT to NT communication, which uses
214  DCE/RPC and therefore full-length unicode strings...) a dns name into
215  a netbios name.
216
217  the netbios name (NOT necessarily null-terminated) is truncated to 15
218  characters.
219
220  ******************************************************************/
221 char *dns_to_netbios_name(char *dns_name)
222 {
223         static char netbios_name[16];
224         int i;
225         StrnCpy(netbios_name, dns_name, 15);
226         netbios_name[15] = 0;
227         
228 #ifdef TRUNCATE_NETBIOS_NAME
229         /* ok.  this is because of a stupid microsoft-ism.  if the called host
230            name contains a '.', microsoft clients expect you to truncate the
231            netbios name up to and including the '.'  this even applies, by
232            mistake, to workgroup (domain) names, which is _really_ daft.
233          */
234         for (i = 15; i >= 0; i--)
235         {
236                 if (netbios_name[i] == '.')
237                 {
238                         netbios_name[i] = 0;
239                         break;
240                 }
241         }
242 #endif /* TRUNCATE_NETBIOS_NAME */
243
244         return netbios_name;
245 }
246
247
248 /****************************************************************************
249 interpret the weird netbios "name". Return the name type
250 ****************************************************************************/
251 static int name_interpret(char *in,char *out)
252 {
253   int ret;
254   int len = (*in++) / 2;
255
256   *out=0;
257
258   if (len > 30 || len<1) return(0);
259
260   while (len--)
261     {
262       if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
263         *out = 0;
264         return(0);
265       }
266       *out = ((in[0]-'A')<<4) + (in[1]-'A');
267       in += 2;
268       out++;
269     }
270   *out = 0;
271   ret = out[-1];
272
273 #ifdef NETBIOS_SCOPE
274   /* Handle any scope names */
275   while(*in) 
276     {
277       *out++ = '.'; /* Scope names are separated by periods */
278       len = *(unsigned char *)in++;
279       StrnCpy(out, in, len);
280       out += len;
281       *out=0;
282       in += len;
283     }
284 #endif
285   return(ret);
286 }
287
288 /****************************************************************************
289 mangle a name into netbios format
290
291   Note:  <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
292 ****************************************************************************/
293 int name_mangle( char *In, char *Out, char name_type )
294   {
295   int   i;
296   int   c;
297   int   len;
298   char  buf[20];
299   char *p = Out;
300
301   /* Safely copy the input string, In, into buf[]. */
302   (void)memset( buf, 0, 20 );
303   if (strcmp(In,"*") == 0)
304     buf[0] = '*';
305   else
306     (void)slprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, name_type );
307
308   /* Place the length of the first field into the output buffer. */
309   p[0] = 32;
310   p++;
311
312   /* Now convert the name to the rfc1001/1002 format. */
313   for( i = 0; i < 16; i++ )
314     {
315     c = toupper( buf[i] );
316     p[i*2]     = ( (c >> 4) & 0x000F ) + 'A';
317     p[(i*2)+1] = (c & 0x000F) + 'A';
318     }
319   p += 32;
320   p[0] = '\0';
321
322   /* Add the scope string. */
323   for( i = 0, len = 0; NULL != scope; i++, len++ )
324     {
325     switch( scope[i] )
326       {
327       case '\0':
328         p[0]     = len;
329         if( len > 0 )
330           p[len+1] = 0;
331         return( name_len(Out) );
332       case '.':
333         p[0] = len;
334         p   += (len + 1);
335         len  = -1;
336         break;
337       default:
338         p[len+1] = scope[i];
339         break;
340       }
341     }
342
343   return( name_len(Out) );
344   } /* name_mangle */
345
346 /*******************************************************************
347   check if a file exists
348 ********************************************************************/
349 BOOL file_exist(char *fname,SMB_STRUCT_STAT *sbuf)
350 {
351   SMB_STRUCT_STAT st;
352   if (!sbuf) sbuf = &st;
353   
354   if (sys_stat(fname,sbuf) != 0) 
355     return(False);
356
357   return(S_ISREG(sbuf->st_mode));
358 }
359
360 /*******************************************************************
361 check a files mod time
362 ********************************************************************/
363 time_t file_modtime(char *fname)
364 {
365   SMB_STRUCT_STAT st;
366   
367   if (sys_stat(fname,&st) != 0) 
368     return(0);
369
370   return(st.st_mtime);
371 }
372
373 /*******************************************************************
374   check if a directory exists
375 ********************************************************************/
376 BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st)
377 {
378   SMB_STRUCT_STAT st2;
379   BOOL ret;
380
381   if (!st) st = &st2;
382
383   if (sys_stat(dname,st) != 0) 
384     return(False);
385
386   ret = S_ISDIR(st->st_mode);
387   if(!ret)
388     errno = ENOTDIR;
389   return ret;
390 }
391
392 /*******************************************************************
393 returns the size in bytes of the named file
394 ********************************************************************/
395 SMB_OFF_T get_file_size(char *file_name)
396 {
397   SMB_STRUCT_STAT buf;
398   buf.st_size = 0;
399   if(sys_stat(file_name,&buf) != 0)
400     return (SMB_OFF_T)-1;
401   return(buf.st_size);
402 }
403
404 /*******************************************************************
405 return a string representing an attribute for a file
406 ********************************************************************/
407 char *attrib_string(uint16 mode)
408 {
409   static fstring attrstr;
410
411   attrstr[0] = 0;
412
413   if (mode & aVOLID) fstrcat(attrstr,"V");
414   if (mode & aDIR) fstrcat(attrstr,"D");
415   if (mode & aARCH) fstrcat(attrstr,"A");
416   if (mode & aHIDDEN) fstrcat(attrstr,"H");
417   if (mode & aSYSTEM) fstrcat(attrstr,"S");
418   if (mode & aRONLY) fstrcat(attrstr,"R");        
419
420   return(attrstr);
421 }
422
423
424
425 /****************************************************************************
426   make a file into unix format
427 ****************************************************************************/
428 void unix_format(char *fname)
429 {
430   string_replace(fname,'\\','/');
431 }
432
433 /****************************************************************************
434   make a file into dos format
435 ****************************************************************************/
436 void dos_format(char *fname)
437 {
438   string_replace(fname,'/','\\');
439 }
440
441 /*******************************************************************
442   show a smb message structure
443 ********************************************************************/
444 void show_msg(char *buf)
445 {
446         int i;
447         int bcc=0;
448
449         if (DEBUGLEVEL < 5) return;
450
451         DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
452                         smb_len(buf),
453                         (int)CVAL(buf,smb_com),
454                         (int)CVAL(buf,smb_rcls),
455                         (int)CVAL(buf,smb_reh),
456                         (int)SVAL(buf,smb_err),
457                         (int)CVAL(buf,smb_flg),
458                         (int)SVAL(buf,smb_flg2)));
459         DEBUG(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n",
460                         (int)SVAL(buf,smb_tid),
461                         (int)SVAL(buf,smb_pid),
462                         (int)SVAL(buf,smb_uid),
463                         (int)SVAL(buf,smb_mid),
464                         (int)CVAL(buf,smb_wct)));
465
466         for (i=0;i<(int)CVAL(buf,smb_wct);i++)
467         {
468                 DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i,
469                         SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
470         }
471
472         bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
473
474         DEBUG(5,("smb_bcc=%d\n",bcc));
475
476         if (DEBUGLEVEL < 10) return;
477
478         if (DEBUGLEVEL < 50)
479         {
480                 bcc = MIN(bcc, 512);
481         }
482
483         dump_data(10, smb_buf(buf), bcc);
484 }
485 /*******************************************************************
486   return the length of an smb packet
487 ********************************************************************/
488 int smb_len(char *buf)
489 {
490   return( PVAL(buf,3) | (PVAL(buf,2)<<8) | ((PVAL(buf,1)&1)<<16) );
491 }
492
493 /*******************************************************************
494   set the length of an smb packet
495 ********************************************************************/
496 void _smb_setlen(char *buf,int len)
497 {
498   buf[0] = 0;
499   buf[1] = (len&0x10000)>>16;
500   buf[2] = (len&0xFF00)>>8;
501   buf[3] = len&0xFF;
502 }
503
504 /*******************************************************************
505   set the length and marker of an smb packet
506 ********************************************************************/
507 void smb_setlen(char *buf,int len)
508 {
509   _smb_setlen(buf,len);
510
511   CVAL(buf,4) = 0xFF;
512   CVAL(buf,5) = 'S';
513   CVAL(buf,6) = 'M';
514   CVAL(buf,7) = 'B';
515 }
516
517 /*******************************************************************
518   setup the word count and byte count for a smb message
519 ********************************************************************/
520 int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
521 {
522   if (zero)
523     memset(buf + smb_size,'\0',num_words*2 + num_bytes);
524   CVAL(buf,smb_wct) = num_words;
525   SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);  
526   smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
527   return (smb_size + num_words*2 + num_bytes);
528 }
529
530 /*******************************************************************
531 return the number of smb words
532 ********************************************************************/
533 static int smb_numwords(char *buf)
534 {
535   return (CVAL(buf,smb_wct));
536 }
537
538 /*******************************************************************
539 return the size of the smb_buf region of a message
540 ********************************************************************/
541 int smb_buflen(char *buf)
542 {
543   return(SVAL(buf,smb_vwv0 + smb_numwords(buf)*2));
544 }
545
546 /*******************************************************************
547   return a pointer to the smb_buf data area
548 ********************************************************************/
549 static int smb_buf_ofs(char *buf)
550 {
551   return (smb_size + CVAL(buf,smb_wct)*2);
552 }
553
554 /*******************************************************************
555   return a pointer to the smb_buf data area
556 ********************************************************************/
557 char *smb_buf(char *buf)
558 {
559   return (buf + smb_buf_ofs(buf));
560 }
561
562 /*******************************************************************
563 return the SMB offset into an SMB buffer
564 ********************************************************************/
565 int smb_offset(char *p,char *buf)
566 {
567   return(PTR_DIFF(p,buf+4) + chain_size);
568 }
569
570 /*******************************************************************
571 reduce a file name, removing .. elements.
572 ********************************************************************/
573 void dos_clean_name(char *s)
574 {
575   char *p=NULL;
576
577   DEBUG(3,("dos_clean_name [%s]\n",s));
578
579   /* remove any double slashes */
580   all_string_sub(s, "\\\\", "\\", 0);
581
582   while ((p = strstr(s,"\\..\\")) != NULL)
583     {
584       pstring s1;
585
586       *p = 0;
587       pstrcpy(s1,p+3);
588
589       if ((p=strrchr(s,'\\')) != NULL)
590         *p = 0;
591       else
592         *s = 0;
593       pstrcat(s,s1);
594     }  
595
596   trim_string(s,NULL,"\\..");
597
598   all_string_sub(s, "\\.\\", "\\", 0);
599 }
600
601 /*******************************************************************
602 reduce a file name, removing .. elements. 
603 ********************************************************************/
604 void unix_clean_name(char *s)
605 {
606   char *p=NULL;
607
608   DEBUG(3,("unix_clean_name [%s]\n",s));
609
610   /* remove any double slashes */
611   all_string_sub(s, "//","/", 0);
612
613   /* Remove leading ./ characters */
614   if(strncmp(s, "./", 2) == 0) {
615     trim_string(s, "./", NULL);
616     if(*s == 0)
617       pstrcpy(s,"./");
618   }
619
620   while ((p = strstr(s,"/../")) != NULL)
621     {
622       pstring s1;
623
624       *p = 0;
625       pstrcpy(s1,p+3);
626
627       if ((p=strrchr(s,'/')) != NULL)
628         *p = 0;
629       else
630         *s = 0;
631       pstrcat(s,s1);
632     }  
633
634   trim_string(s,NULL,"/..");
635 }
636
637 /*******************************************************************
638 reduce a file name, removing .. elements and checking that 
639 it is below dir in the heirachy. This uses dos_GetWd() and so must be run
640 on the system that has the referenced file system.
641
642 widelinks are allowed if widelinks is true
643 ********************************************************************/
644
645 BOOL reduce_name(char *s,char *dir,BOOL widelinks)
646 {
647 #ifndef REDUCE_PATHS
648   return True;
649 #else
650   pstring dir2;
651   pstring wd;
652   pstring base_name;
653   pstring newname;
654   char *p=NULL;
655   BOOL relative = (*s != '/');
656
657   *dir2 = *wd = *base_name = *newname = 0;
658
659   if (widelinks)
660   {
661     unix_clean_name(s);
662     /* can't have a leading .. */
663     if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
664     {
665       DEBUG(3,("Illegal file name? (%s)\n",s));
666       return(False);
667     }
668
669     if (strlen(s) == 0)
670       pstrcpy(s,"./");
671
672     return(True);
673   }
674   
675   DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
676
677   /* remove any double slashes */
678   all_string_sub(s,"//","/",0);
679
680   pstrcpy(base_name,s);
681   p = strrchr(base_name,'/');
682
683   if (!p)
684     return(True);
685
686   if (!dos_GetWd(wd))
687   {
688     DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
689     return(False);
690   }
691
692   if (dos_ChDir(dir) != 0)
693   {
694     DEBUG(0,("couldn't chdir to %s\n",dir));
695     return(False);
696   }
697
698   if (!dos_GetWd(dir2))
699   {
700     DEBUG(0,("couldn't getwd for %s\n",dir));
701     dos_ChDir(wd);
702     return(False);
703   }
704
705   if (p && (p != base_name))
706   {
707     *p = 0;
708     if (strcmp(p+1,".")==0)
709       p[1]=0;
710     if (strcmp(p+1,"..")==0)
711       *p = '/';
712   }
713
714   if (dos_ChDir(base_name) != 0)
715   {
716     dos_ChDir(wd);
717     DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name));
718     return(False);
719   }
720
721   if (!dos_GetWd(newname))
722   {
723     dos_ChDir(wd);
724     DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
725     return(False);
726   }
727
728   if (p && (p != base_name))
729   {
730     pstrcat(newname,"/");
731     pstrcat(newname,p+1);
732   }
733
734   {
735     size_t l = strlen(dir2);    
736     if (dir2[l-1] == '/')
737       l--;
738
739     if (strncmp(newname,dir2,l) != 0)
740     {
741       dos_ChDir(wd);
742       DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,(int)l));
743       return(False);
744     }
745
746     if (relative)
747     {
748       if (newname[l] == '/')
749         pstrcpy(s,newname + l + 1);
750       else
751         pstrcpy(s,newname+l);
752     }
753     else
754       pstrcpy(s,newname);
755   }
756
757   dos_ChDir(wd);
758
759   if (strlen(s) == 0)
760     pstrcpy(s,"./");
761
762   DEBUG(3,("reduced to %s\n",s));
763   return(True);
764 #endif
765 }
766
767 /****************************************************************************
768 expand some *s 
769 ****************************************************************************/
770 static void expand_one(char *Mask,int len)
771 {
772   char *p1;
773   while ((p1 = strchr(Mask,'*')) != NULL)
774     {
775       int lfill = (len+1) - strlen(Mask);
776       int l1= (p1 - Mask);
777       pstring tmp;
778       pstrcpy(tmp,Mask);  
779       memset(tmp+l1,'?',lfill);
780       pstrcpy(tmp + l1 + lfill,Mask + l1 + 1);  
781       pstrcpy(Mask,tmp);      
782     }
783 }
784
785 /****************************************************************************
786 parse out a directory name from a path name. Assumes dos style filenames.
787 ****************************************************************************/
788 static void dirname_dos(char *path,char *buf)
789 {
790         split_at_last_component(path, buf, '\\', NULL);
791 }
792
793
794 /****************************************************************************
795 expand a wildcard expression, replacing *s with ?s
796 ****************************************************************************/
797 void expand_mask(char *Mask,BOOL doext)
798 {
799   pstring mbeg,mext;
800   pstring dirpart;
801   pstring filepart;
802   BOOL hasdot = False;
803   char *p1;
804   BOOL absolute = (*Mask == '\\');
805
806   *mbeg = *mext = *dirpart = *filepart = 0;
807
808   /* parse the directory and filename */
809   if (strchr(Mask,'\\'))
810     dirname_dos(Mask,dirpart);
811
812   filename_dos(Mask,filepart);
813
814   pstrcpy(mbeg,filepart);
815   if ((p1 = strchr(mbeg,'.')) != NULL)
816     {
817       hasdot = True;
818       *p1 = 0;
819       p1++;
820       pstrcpy(mext,p1);
821     }
822   else
823     {
824       pstrcpy(mext,"");
825       if (strlen(mbeg) > 8)
826         {
827           pstrcpy(mext,mbeg + 8);
828           mbeg[8] = 0;
829         }
830     }
831
832   if (*mbeg == 0)
833     pstrcpy(mbeg,"????????");
834   if ((*mext == 0) && doext && !hasdot)
835     pstrcpy(mext,"???");
836
837   if (strequal(mbeg,"*") && *mext==0) 
838     pstrcpy(mext,"*");
839
840   /* expand *'s */
841   expand_one(mbeg,8);
842   if (*mext)
843     expand_one(mext,3);
844
845   pstrcpy(Mask,dirpart);
846   if (*dirpart || absolute) pstrcat(Mask,"\\");
847   pstrcat(Mask,mbeg);
848   pstrcat(Mask,".");
849   pstrcat(Mask,mext);
850
851   DEBUG(6,("Mask expanded to [%s]\n",Mask));
852 }  
853
854
855
856 /****************************************************************************
857   make a dir struct
858 ****************************************************************************/
859 void make_dir_struct(char *buf,char *mask,char *fname,SMB_OFF_T size,int mode,time_t date)
860 {  
861   char *p;
862   pstring mask2;
863
864   pstrcpy(mask2,mask);
865
866   if ((mode & aDIR) != 0)
867     size = 0;
868
869   memset(buf+1,' ',11);
870   if ((p = strchr(mask2,'.')) != NULL)
871     {
872       *p = 0;
873       memcpy(buf+1,mask2,MIN(strlen(mask2),8));
874       memcpy(buf+9,p+1,MIN(strlen(p+1),3));
875       *p = '.';
876     }
877   else
878     memcpy(buf+1,mask2,MIN(strlen(mask2),11));
879
880   memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
881   CVAL(buf,21) = mode;
882   put_dos_date(buf,22,date);
883   SSVAL(buf,26,size & 0xFFFF);
884   SSVAL(buf,28,(size >> 16)&0xFFFF);
885   StrnCpy(buf+30,fname,12);
886   if (!case_sensitive)
887     strupper(buf+30);
888   DEBUG(8,("put name [%s] into dir struct\n",buf+30));
889 }
890
891
892 /*******************************************************************
893 close the low 3 fd's and open dev/null in their place
894 ********************************************************************/
895 void close_low_fds(void)
896 {
897   int fd;
898   int i;
899   close(0); close(1); close(2);
900   /* try and use up these file descriptors, so silly
901      library routines writing to stdout etc won't cause havoc */
902   for (i=0;i<3;i++) {
903     fd = sys_open("/dev/null",O_RDWR,0);
904     if (fd < 0) fd = sys_open("/dev/null",O_WRONLY,0);
905     if (fd < 0) {
906       DEBUG(0,("Can't open /dev/null\n"));
907       return;
908     }
909     if (fd != i) {
910       DEBUG(0,("Didn't get file descriptor %d\n",i));
911       return;
912     }
913   }
914 }
915
916 /****************************************************************************
917 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
918 else
919 if SYSV use O_NDELAY
920 if BSD use FNDELAY
921 ****************************************************************************/
922 int set_blocking(int fd, BOOL set)
923 {
924   int val;
925 #ifdef O_NONBLOCK
926 #define FLAG_TO_SET O_NONBLOCK
927 #else
928 #ifdef SYSV
929 #define FLAG_TO_SET O_NDELAY
930 #else /* BSD */
931 #define FLAG_TO_SET FNDELAY
932 #endif
933 #endif
934
935   if((val = fcntl(fd, F_GETFL, 0)) == -1)
936         return -1;
937   if(set) /* Turn blocking on - ie. clear nonblock flag */
938         val &= ~FLAG_TO_SET;
939   else
940     val |= FLAG_TO_SET;
941   return fcntl( fd, F_SETFL, val);
942 #undef FLAG_TO_SET
943 }
944
945
946 /*******************************************************************
947 find the difference in milliseconds between two struct timeval
948 values
949 ********************************************************************/
950 int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew)
951 {
952   return((tvalnew->tv_sec - tvalold->tv_sec)*1000 + 
953          ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000);  
954 }
955
956
957
958 /****************************************************************************
959 transfer some data between two fd's
960 ****************************************************************************/
961 SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n,char *header,int headlen,int align)
962 {
963   static char *buf=NULL;  
964   static int size=0;
965   char *buf1,*abuf;
966   SMB_OFF_T total = 0;
967
968   DEBUG(4,("transfer_file n=%.0f  (head=%d) called\n",(double)n,headlen));
969
970   if (size == 0) {
971     size = lp_readsize();
972     size = MAX(size,1024);
973   }
974
975   while (!buf && size>0) {
976     buf = (char *)Realloc(buf,size+8);
977     if (!buf) size /= 2;
978   }
979
980   if (!buf) {
981     DEBUG(0,("Can't allocate transfer buffer!\n"));
982     exit(1);
983   }
984
985   abuf = buf + (align%8);
986
987   if (header)
988     n += headlen;
989
990   while (n > 0)
991   {
992     int s = (int)MIN(n,(SMB_OFF_T)size);
993     int ret,ret2=0;
994
995     ret = 0;
996
997     if (header && (headlen >= MIN(s,1024))) {
998       buf1 = header;
999       s = headlen;
1000       ret = headlen;
1001       headlen = 0;
1002       header = NULL;
1003     } else {
1004       buf1 = abuf;
1005     }
1006
1007     if (header && headlen > 0)
1008     {
1009       ret = MIN(headlen,size);
1010       memcpy(buf1,header,ret);
1011       headlen -= ret;
1012       header += ret;
1013       if (headlen <= 0) header = NULL;
1014     }
1015
1016     if (s > ret)
1017       ret += read(infd,buf1+ret,s-ret);
1018
1019     if (ret > 0)
1020     {
1021       ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret);
1022       if (ret2 > 0) total += ret2;
1023       /* if we can't write then dump excess data */
1024       if (ret2 != ret)
1025         transfer_file(infd,-1,n-(ret+headlen),NULL,0,0);
1026     }
1027     if (ret <= 0 || ret2 != ret)
1028       return(total);
1029     n -= ret;
1030   }
1031   return(total);
1032 }
1033
1034
1035
1036 /****************************************************************************
1037 find a pointer to a netbios name
1038 ****************************************************************************/
1039 static char *name_ptr(char *buf,int ofs)
1040 {
1041   unsigned char c = *(unsigned char *)(buf+ofs);
1042
1043   if ((c & 0xC0) == 0xC0)
1044     {
1045       uint16 l = RSVAL(buf, ofs) & 0x3FFF;
1046       DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
1047       return(buf + l);
1048     }
1049   else
1050     return(buf+ofs);
1051 }  
1052
1053 /****************************************************************************
1054 extract a netbios name from a buf
1055 ****************************************************************************/
1056 int name_extract(char *buf,int ofs,char *name)
1057 {
1058   char *p = name_ptr(buf,ofs);
1059   int d = PTR_DIFF(p,buf+ofs);
1060   pstrcpy(name,"");
1061   if (d < -50 || d > 50) return(0);
1062   return(name_interpret(p,name));
1063 }
1064   
1065 /****************************************************************************
1066 return the total storage length of a mangled name
1067 ****************************************************************************/
1068 int name_len(char *s1)
1069 {
1070         /* NOTE: this argument _must_ be unsigned */
1071         unsigned char *s = (unsigned char *)s1;
1072         int len;
1073
1074         /* If the two high bits of the byte are set, return 2. */
1075         if (0xC0 == (*s & 0xC0))
1076                 return(2);
1077
1078         /* Add up the length bytes. */
1079         for (len = 1; (*s); s += (*s) + 1) {
1080                 len += *s + 1;
1081                 SMB_ASSERT(len < 80);
1082         }
1083
1084         return(len);
1085 } /* name_len */
1086
1087
1088 /*******************************************************************
1089 sleep for a specified number of milliseconds
1090 ********************************************************************/
1091 void msleep(int t)
1092 {
1093   int tdiff=0;
1094   struct timeval tval,t1,t2;  
1095   fd_set fds;
1096
1097   GetTimeOfDay(&t1);
1098   GetTimeOfDay(&t2);
1099   
1100   while (tdiff < t) {
1101     tval.tv_sec = (t-tdiff)/1000;
1102     tval.tv_usec = 1000*((t-tdiff)%1000);
1103  
1104     FD_ZERO(&fds);
1105     errno = 0;
1106     sys_select(0,&fds,&tval);
1107
1108     GetTimeOfDay(&t2);
1109     tdiff = TvalDiff(&t1,&t2);
1110   }
1111 }
1112
1113
1114 /*********************************************************
1115 * Recursive routine that is called by unix_mask_match.
1116 * Does the actual matching. This is the 'original code' 
1117 * used by the unix matcher.
1118 *********************************************************/
1119
1120 BOOL unix_do_match(char *str, char *regexp, BOOL case_sig)
1121 {
1122   char *p;
1123
1124   for( p = regexp; *p && *str; ) {
1125     switch(*p) {
1126     case '?':
1127       str++; p++;
1128       break;
1129
1130     case '*':
1131       /* Look for a character matching 
1132          the one after the '*' */
1133       p++;
1134       if(!*p)
1135         return True; /* Automatic match */
1136       while(*str) {
1137         while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
1138           str++;
1139         if(unix_do_match(str,p,case_sig))
1140           return True;
1141         if(!*str)
1142           return False;
1143         else
1144           str++;
1145       }
1146       return False;
1147
1148     default:
1149       if(case_sig) {
1150         if(*str != *p)
1151           return False;
1152       } else {
1153         if(toupper(*str) != toupper(*p))
1154           return False;
1155       }
1156       str++, p++;
1157       break;
1158     }
1159   }
1160   if(!*p && !*str)
1161     return True;
1162
1163   if (!*p && str[0] == '.' && str[1] == 0)
1164     return(True);
1165   
1166   if (!*str && *p == '?')
1167     {
1168       while (*p == '?') p++;
1169       return(!*p);
1170     }
1171
1172   if(!*str && (*p == '*' && p[1] == '\0'))
1173     return True;
1174   return False;
1175 }
1176
1177
1178 /*********************************************************
1179 * Routine to match a given string with a regexp - uses
1180 * simplified regexp that takes * and ? only. Case can be
1181 * significant or not.
1182 * This is the 'original code' used by the unix matcher.
1183 *********************************************************/
1184
1185 static BOOL unix_mask_match(char *str, char *regexp, BOOL case_sig, BOOL trans2)
1186 {
1187   char *p;
1188   pstring p1, p2;
1189   fstring ebase,eext,sbase,sext;
1190
1191   BOOL matched;
1192
1193   /* Make local copies of str and regexp */
1194   StrnCpy(p1,regexp,sizeof(pstring)-1);
1195   StrnCpy(p2,str,sizeof(pstring)-1);
1196
1197   if (!strchr(p2,'.')) {
1198     pstrcat(p2,".");
1199   }
1200
1201   /* Remove any *? and ** as they are meaningless */
1202   for(p = p1; *p; p++)
1203     while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
1204       (void)pstrcpy( &p[1], &p[2]);
1205
1206   if (strequal(p1,"*")) return(True);
1207
1208   DEBUG(8,("unix_mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
1209
1210   if (trans2) {
1211     fstrcpy(ebase,p1);
1212     fstrcpy(sbase,p2);
1213   } else {
1214     if ((p=strrchr(p1,'.'))) {
1215       *p = 0;
1216       fstrcpy(ebase,p1);
1217       fstrcpy(eext,p+1);
1218     } else {
1219       fstrcpy(ebase,p1);
1220       eext[0] = 0;
1221     }
1222
1223   if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
1224     *p = 0;
1225     fstrcpy(sbase,p2);
1226     fstrcpy(sext,p+1);
1227   } else {
1228     fstrcpy(sbase,p2);
1229     fstrcpy(sext,"");
1230   }
1231   }
1232
1233   matched = unix_do_match(sbase,ebase,case_sig) && 
1234     (trans2 || unix_do_match(sext,eext,case_sig));
1235
1236   DEBUG(8,("unix_mask_match returning %d\n", matched));
1237
1238   return matched;
1239 }
1240
1241 /*********************************************************
1242 * Recursive routine that is called by mask_match.
1243 * Does the actual matching. Returns True if matched,
1244 * False if failed. This is the 'new' NT style matcher.
1245 * The win9x_semantics parameter is needed as Win9x matching
1246 * is *actually different*. In Win9x, trailing '?' characters
1247 * will only match the *exact* number of characters. Under
1248 * DOS and NT they match any number. This makes no
1249 * sense.....
1250 *********************************************************/
1251
1252 static BOOL do_match(char *str, char *regexp, int case_sig, BOOL win9x_semantics)
1253 {
1254   char *p;
1255
1256   for( p = regexp; *p && *str; ) {
1257     switch(*p) {
1258     case '?':
1259       str++; p++;
1260       break;
1261
1262     case '*':
1263       /* Look for a character matching 
1264          the one after the '*' */
1265       p++;
1266       if(!*p)
1267         return True; /* Automatic match */
1268       while(*str) {
1269         while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
1270           str++;
1271         /* Now eat all characters that match, as
1272            we want the *last* character to match. */
1273         while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str))))
1274           str++;
1275         str--; /* We've eaten the match char after the '*' */
1276         if(do_match(str,p,case_sig,win9x_semantics)) {
1277           return True;
1278         }
1279         if(!*str) {
1280           return False;
1281         } else {
1282           str++;
1283         }
1284       }
1285       return False;
1286
1287     default:
1288       if(case_sig) {
1289         if(*str != *p) {
1290           return False;
1291         }
1292       } else {
1293         if(toupper(*str) != toupper(*p)) {
1294           return False;
1295         }
1296       }
1297       str++, p++;
1298       break;
1299     }
1300   }
1301
1302   if(!*p && !*str)
1303     return True;
1304
1305   if (!*p && str[0] == '.' && str[1] == 0) {
1306     return(True);
1307   }
1308   
1309   if (!win9x_semantics) {
1310     if (!*str && *p == '?') {
1311       while (*p == '?')
1312         p++;
1313       return(!*p);
1314     }
1315   }
1316
1317   if(!*str && (*p == '*' && p[1] == '\0')) {
1318     return True;
1319   }
1320  
1321   return False;
1322 }
1323
1324 /*********************************************************
1325 * Routine to check if a given string matches exactly.
1326 * Case can be significant or not.
1327 **********************************************************/
1328
1329 BOOL exact_match(char *str, char *regexp, BOOL case_sig)
1330 {
1331   return ((case_sig?strcmp(str,regexp):strcasecmp(str,regexp)) == 0);
1332 }
1333
1334 /*********************************************************
1335 * Routine to match a given string with a regexp - uses
1336 * simplified regexp that takes * and ? only. Case can be
1337 * significant or not.
1338 * The 8.3 handling was rewritten by Ums Harald <Harald.Ums@pro-sieben.de>
1339 * This is the new 'NT style' matcher.
1340 *********************************************************/
1341
1342 BOOL mask_match(char *str, char *regexp, BOOL case_sig, BOOL trans2)
1343 {
1344   char *p;
1345   pstring t_pattern, t_filename, te_pattern, te_filename;
1346   fstring ebase,eext,sbase,sext;
1347   BOOL matched = False;
1348   BOOL win9x_semantics = (get_remote_arch() == RA_WIN95) && trans2;
1349
1350   /* special case - if it is exactly the same then it always matches! */
1351   if(exact_match(str, regexp, case_sig))
1352     return True;
1353
1354   /* Make local copies of str and regexp */
1355   pstrcpy(t_pattern,regexp);
1356   pstrcpy(t_filename,str);
1357
1358   if(trans2) {
1359
1360     /* a special case for 16 bit apps */
1361     if (strequal(t_pattern,"????????.???"))
1362       pstrcpy(t_pattern,"*");
1363
1364 #if 0
1365     /*
1366      * Handle broken clients that send us old 8.3 format.
1367      */
1368     pstring_sub(t_pattern,"????????","*");
1369     pstring_sub(t_pattern,".???",".*");
1370 #endif
1371   }
1372
1373 #if 0
1374   /* 
1375    * Not sure if this is a good idea. JRA.
1376    */
1377   if(trans2 && is_8_3(t_pattern,False) && is_8_3(t_filename,False))
1378     trans2 = False;
1379 #endif
1380
1381 #if 0
1382   if (!strchr(t_filename,'.')) {
1383     pstrcat(t_filename,".");
1384   }
1385 #endif
1386
1387   /* Remove any *? and ** as they are meaningless */
1388   pstring_sub(t_pattern, "*?", "*");
1389   pstring_sub(t_pattern, "**", "*");
1390
1391   if (strequal(t_pattern,"*"))
1392     return(True);
1393
1394   DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", t_filename, t_pattern, case_sig));
1395
1396   if(trans2) {
1397     /*
1398      * Match each component of the regexp, split up by '.'
1399      * characters.
1400      */
1401     char *fp, *rp, *cp2, *cp1;
1402     BOOL last_wcard_was_star = False;
1403     int num_path_components, num_regexp_components;
1404
1405     pstrcpy(te_pattern,t_pattern);
1406     pstrcpy(te_filename,t_filename);
1407     /*
1408      * Remove multiple "*." patterns.
1409      */
1410     pstring_sub(te_pattern, "*.*.", "*.");
1411     num_regexp_components = count_chars(te_pattern, '.');
1412     num_path_components = count_chars(te_filename, '.');
1413
1414     /* 
1415      * Check for special 'hack' case of "DIR a*z". - needs to match a.b.c...z
1416      */
1417     if(num_regexp_components == 0)
1418       matched = do_match( te_filename, te_pattern, case_sig, win9x_semantics);
1419     else {
1420       for( cp1 = te_pattern, cp2 = te_filename; cp1;) {
1421         fp = strchr(cp2, '.');
1422         if(fp)
1423           *fp = '\0';
1424         rp = strchr(cp1, '.');
1425         if(rp)
1426           *rp = '\0';
1427
1428         if(cp1[0] && cp1[strlen(cp1)-1] == '*')
1429           last_wcard_was_star = True;
1430         else
1431           last_wcard_was_star = False;
1432
1433         if(!do_match(cp2, cp1, case_sig, win9x_semantics))
1434           break;
1435
1436         /*
1437          * Ugly ! Special case for Win9x *only*. If filename is XXXX and pattern extension
1438          * is '*' or all '?' then disallow match.
1439          */
1440
1441         if (win9x_semantics) {
1442           if (*cp2 == '\0' && str_is_all(cp1, '?'))
1443             break;
1444         }
1445
1446         cp1 = rp ? rp + 1 : NULL;
1447         cp2 = fp ? fp + 1 : "";
1448
1449         if(last_wcard_was_star || ((cp1 != NULL) && (*cp1 == '*'))) {
1450           /* Eat the extra path components. */
1451           int i;
1452
1453           for(i = 0; i < num_path_components - num_regexp_components; i++) {
1454             fp = strchr(cp2, '.');
1455             if(fp)
1456               *fp = '\0';
1457
1458             if((cp1 != NULL) && do_match( cp2, cp1, case_sig, win9x_semantics)) {
1459               cp2 = fp ? fp + 1 : "";
1460               break;
1461             }
1462             cp2 = fp ? fp + 1 : "";
1463           }
1464           num_path_components -= i;
1465         }
1466       } 
1467       if(cp1 == NULL && ((*cp2 == '\0') || last_wcard_was_star))
1468         matched = True;
1469     }
1470   } else {
1471
1472     /* -------------------------------------------------
1473      * Behaviour of Win95
1474      * for 8.3 filenames and 8.3 Wildcards
1475      * -------------------------------------------------
1476      */
1477     if (strequal (t_filename, ".")) {
1478       /*
1479        *  Patterns:  *.*  *. ?. ? ????????.??? are valid.
1480        * 
1481        */
1482       if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
1483          strequal(t_pattern, "????????.???") ||
1484          strequal(t_pattern, "?.") || strequal(t_pattern, "?")) 
1485         matched = True;
1486     } else if (strequal (t_filename, "..")) {
1487       /*
1488        *  Patterns:  *.*  *. ?. ? *.? ????????.??? are valid.
1489        *
1490        */
1491       if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
1492          strequal(t_pattern, "?.") || strequal(t_pattern, "?") ||
1493          strequal(t_pattern, "????????.???") ||
1494          strequal(t_pattern, "*.?") || strequal(t_pattern, "?.*"))
1495         matched = True;
1496     } else {
1497
1498       if ((p = strrchr (t_pattern, '.'))) {
1499         /*
1500          * Wildcard has a suffix.
1501          */
1502         *p = 0;
1503         fstrcpy (ebase, t_pattern);
1504         if (p[1]) {
1505           fstrcpy (eext, p + 1);
1506         } else {
1507           /* pattern ends in DOT: treat as if there is no DOT */
1508           *eext = 0;
1509           if (strequal (ebase, "*"))
1510             return (True);
1511         }
1512       } else {
1513         /*
1514          * No suffix for wildcard.
1515          */
1516         fstrcpy (ebase, t_pattern);
1517         eext[0] = 0;
1518       }
1519
1520       p = strrchr (t_filename, '.');
1521       if (p && (p[1] == 0)      ) {
1522         /*
1523          * Filename has an extension of '.' only.
1524          */
1525         *p = 0; /* nuke dot at end of string */
1526         p = 0;  /* and treat it as if there is no extension */
1527       }
1528
1529       if (p) {
1530         /*
1531          * Filename has an extension.
1532          */
1533         *p = 0;
1534         fstrcpy (sbase, t_filename);
1535         fstrcpy (sext, p + 1);
1536         if (*eext) {
1537           matched = do_match(sbase, ebase, case_sig, False)
1538                     && do_match(sext, eext, case_sig, False);
1539         } else {
1540           /* pattern has no extension */
1541           /* Really: match complete filename with pattern ??? means exactly 3 chars */
1542           matched = do_match(str, ebase, case_sig, False);
1543         }
1544       } else {
1545         /* 
1546          * Filename has no extension.
1547          */
1548         fstrcpy (sbase, t_filename);
1549         fstrcpy (sext, "");
1550         if (*eext) {
1551           /* pattern has extension */
1552           matched = do_match(sbase, ebase, case_sig, False)
1553                     && do_match(sext, eext, case_sig, False);
1554
1555         } else {
1556           matched = do_match(sbase, ebase, case_sig, False);
1557 #ifdef EMULATE_WEIRD_W95_MATCHING
1558           /*
1559            * Even Microsoft has some problems
1560            * Behaviour Win95 -> local disk 
1561            * is different from Win95 -> smb drive from Nt 4.0
1562            * This branch would reflect the Win95 local disk behaviour
1563            */
1564           if (!matched) {
1565             /* a? matches aa and a in w95 */
1566             fstrcat (sbase, ".");
1567             matched = do_match(sbase, ebase, case_sig, False);
1568           }
1569 #endif
1570         }
1571       }
1572     }
1573   }
1574
1575   DEBUG(8,("mask_match returning %d\n", matched));
1576
1577   return matched;
1578 }
1579
1580 /****************************************************************************
1581 become a daemon, discarding the controlling terminal
1582 ****************************************************************************/
1583 void become_daemon(void)
1584 {
1585         if (fork()) {
1586                 _exit(0);
1587         }
1588
1589   /* detach from the terminal */
1590 #ifdef HAVE_SETSID
1591         setsid();
1592 #elif defined(TIOCNOTTY)
1593         {
1594                 int i = sys_open("/dev/tty", O_RDWR, 0);
1595                 if (i != -1) {
1596                         ioctl(i, (int) TIOCNOTTY, (char *)0);      
1597                         close(i);
1598                 }
1599         }
1600 #endif /* HAVE_SETSID */
1601
1602         /* Close fd's 0,1,2. Needed if started by rsh */
1603         close_low_fds();
1604 }
1605
1606
1607 /****************************************************************************
1608 put up a yes/no prompt
1609 ****************************************************************************/
1610 BOOL yesno(char *p)
1611 {
1612   pstring ans;
1613   printf("%s",p);
1614
1615   if (!fgets(ans,sizeof(ans)-1,stdin))
1616     return(False);
1617
1618   if (*ans == 'y' || *ans == 'Y')
1619     return(True);
1620
1621   return(False);
1622 }
1623
1624 /****************************************************************************
1625 set the length of a file from a filedescriptor.
1626 Returns 0 on success, -1 on failure.
1627 ****************************************************************************/
1628
1629 int set_filelen(int fd, SMB_OFF_T len)
1630 {
1631 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1632    extend a file with ftruncate. Provide alternate implementation
1633    for this */
1634
1635 #ifdef HAVE_FTRUNCATE_EXTEND
1636   return sys_ftruncate(fd, len);
1637 #else
1638   SMB_STRUCT_STAT st;
1639   char c = 0;
1640   SMB_OFF_T currpos = sys_lseek(fd, (SMB_OFF_T)0, SEEK_CUR);
1641
1642   if(currpos == -1)
1643     return -1;
1644   /* Do an fstat to see if the file is longer than
1645      the requested size (call ftruncate),
1646      or shorter, in which case seek to len - 1 and write 1
1647      byte of zero */
1648   if(sys_fstat(fd, &st)<0)
1649     return -1;
1650
1651 #ifdef S_ISFIFO
1652   if (S_ISFIFO(st.st_mode))
1653     return 0;
1654 #endif
1655
1656   if(st.st_size == len)
1657     return 0;
1658   if(st.st_size > len)
1659     return sys_ftruncate(fd, len);
1660
1661   if(sys_lseek(fd, len-1, SEEK_SET) != len -1)
1662     return -1;
1663   if(write(fd, &c, 1)!=1)
1664     return -1;
1665   /* Seek to where we were */
1666   if(sys_lseek(fd, currpos, SEEK_SET) != currpos)
1667     return -1;
1668   return 0;
1669 #endif
1670 }
1671
1672
1673 #ifdef HPUX
1674 /****************************************************************************
1675 this is a version of setbuffer() for those machines that only have setvbuf
1676 ****************************************************************************/
1677  void setbuffer(FILE *f,char *buf,int bufsize)
1678 {
1679   setvbuf(f,buf,_IOFBF,bufsize);
1680 }
1681 #endif
1682
1683
1684 /****************************************************************************
1685 parse out a filename from a path name. Assumes dos style filenames.
1686 ****************************************************************************/
1687 static char *filename_dos(char *path,char *buf)
1688 {
1689   char *p = strrchr(path,'\\');
1690
1691   if (!p)
1692     pstrcpy(buf,path);
1693   else
1694     pstrcpy(buf,p+1);
1695
1696   return(buf);
1697 }
1698
1699
1700
1701 /****************************************************************************
1702 expand a pointer to be a particular size
1703 ****************************************************************************/
1704 void *Realloc(void *p,size_t size)
1705 {
1706   void *ret=NULL;
1707
1708   if (size == 0) {
1709     if (p) free(p);
1710     DEBUG(5,("Realloc asked for 0 bytes\n"));
1711     return NULL;
1712   }
1713
1714   if (!p)
1715     ret = (void *)malloc(size);
1716   else
1717     ret = (void *)realloc(p,size);
1718
1719   if (!ret)
1720     DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size));
1721
1722   return(ret);
1723 }
1724
1725
1726 /****************************************************************************
1727 get my own name and IP
1728 ****************************************************************************/
1729 BOOL get_myname(char *my_name)
1730 {
1731         pstring hostname;
1732
1733         *hostname = 0;
1734
1735         /* get my host name */
1736         if (gethostname(hostname, sizeof(hostname)) == -1) {
1737                 DEBUG(0,("gethostname failed\n"));
1738                 return False;
1739         } 
1740
1741         /* Ensure null termination. */
1742         hostname[sizeof(hostname)-1] = '\0';
1743
1744         if (my_name) {
1745                 /* split off any parts after an initial . */
1746                 char *p = strchr(hostname,'.');
1747                 if (p) *p = 0;
1748                 
1749                 fstrcpy(my_name,hostname);
1750         }
1751         
1752         return(True);
1753 }
1754
1755
1756 /****************************************************************************
1757 true if two IP addresses are equal
1758 ****************************************************************************/
1759 BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
1760 {
1761         return ip1.s_addr == ip2.s_addr;
1762 }
1763
1764
1765 /****************************************************************************
1766 interpret a protocol description string, with a default
1767 ****************************************************************************/
1768 int interpret_protocol(char *str,int def)
1769 {
1770   if (strequal(str,"NT1"))
1771     return(PROTOCOL_NT1);
1772   if (strequal(str,"LANMAN2"))
1773     return(PROTOCOL_LANMAN2);
1774   if (strequal(str,"LANMAN1"))
1775     return(PROTOCOL_LANMAN1);
1776   if (strequal(str,"CORE"))
1777     return(PROTOCOL_CORE);
1778   if (strequal(str,"COREPLUS"))
1779     return(PROTOCOL_COREPLUS);
1780   if (strequal(str,"CORE+"))
1781     return(PROTOCOL_COREPLUS);
1782   
1783   DEBUG(0,("Unrecognised protocol level %s\n",str));
1784   
1785   return(def);
1786 }
1787
1788 /****************************************************************************
1789  Return true if a string could be a pure IP address.
1790 ****************************************************************************/
1791
1792 BOOL is_ipaddress(const char *str)
1793 {
1794   BOOL pure_address = True;
1795   int i;
1796   
1797   for (i=0; pure_address && str[i]; i++)
1798     if (!(isdigit((int)str[i]) || str[i] == '.'))
1799       pure_address = False;
1800
1801   /* Check that a pure number is not misinterpreted as an IP */
1802   pure_address = pure_address && (strchr(str, '.') != NULL);
1803
1804   return pure_address;
1805 }
1806
1807 /****************************************************************************
1808 interpret an internet address or name into an IP address in 4 byte form
1809 ****************************************************************************/
1810
1811 uint32 interpret_addr(char *str)
1812 {
1813   struct hostent *hp;
1814   uint32 res;
1815
1816   if (strcmp(str,"0.0.0.0") == 0) return(0);
1817   if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
1818
1819   /* if it's in the form of an IP address then get the lib to interpret it */
1820   if (is_ipaddress(str)) {
1821     res = inet_addr(str);
1822   } else {
1823     /* otherwise assume it's a network name of some sort and use 
1824        Get_Hostbyname */
1825     if ((hp = Get_Hostbyname(str)) == 0) {
1826       DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
1827       return 0;
1828     }
1829     if(hp->h_addr == NULL) {
1830       DEBUG(3,("Get_Hostbyname: host address is invalid for host %s\n",str));
1831       return 0;
1832     }
1833     putip((char *)&res,(char *)hp->h_addr);
1834   }
1835
1836   if (res == (uint32)-1) return(0);
1837
1838   return(res);
1839 }
1840
1841 /*******************************************************************
1842   a convenient addition to interpret_addr()
1843   ******************************************************************/
1844 struct in_addr *interpret_addr2(char *str)
1845 {
1846   static struct in_addr ret;
1847   uint32 a = interpret_addr(str);
1848   ret.s_addr = a;
1849   return(&ret);
1850 }
1851
1852 /*******************************************************************
1853   check if an IP is the 0.0.0.0
1854   ******************************************************************/
1855 BOOL zero_ip(struct in_addr ip)
1856 {
1857   uint32 a;
1858   putip((char *)&a,(char *)&ip);
1859   return(a == 0);
1860 }
1861
1862
1863 /*******************************************************************
1864  matchname - determine if host name matches IP address 
1865  ******************************************************************/
1866 BOOL matchname(char *remotehost,struct in_addr  addr)
1867 {
1868   struct hostent *hp;
1869   int     i;
1870   
1871   if ((hp = Get_Hostbyname(remotehost)) == 0) {
1872     DEBUG(0,("Get_Hostbyname(%s): lookup failure.\n", remotehost));
1873     return False;
1874   } 
1875
1876   /*
1877    * Make sure that gethostbyname() returns the "correct" host name.
1878    * Unfortunately, gethostbyname("localhost") sometimes yields
1879    * "localhost.domain". Since the latter host name comes from the
1880    * local DNS, we just have to trust it (all bets are off if the local
1881    * DNS is perverted). We always check the address list, though.
1882    */
1883   
1884   if (strcasecmp(remotehost, hp->h_name)
1885       && strcasecmp(remotehost, "localhost")) {
1886     DEBUG(0,("host name/name mismatch: %s != %s\n",
1887              remotehost, hp->h_name));
1888     return False;
1889   }
1890         
1891   /* Look up the host address in the address list we just got. */
1892   for (i = 0; hp->h_addr_list[i]; i++) {
1893     if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
1894       return True;
1895   }
1896
1897   /*
1898    * The host name does not map to the original host address. Perhaps
1899    * someone has compromised a name server. More likely someone botched
1900    * it, but that could be dangerous, too.
1901    */
1902   
1903   DEBUG(0,("host name/address mismatch: %s != %s\n",
1904            inet_ntoa(addr), hp->h_name));
1905   return False;
1906 }
1907
1908
1909 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1910 /******************************************************************
1911  Remove any mount options such as -rsize=2048,wsize=2048 etc.
1912  Based on a fix from <Thomas.Hepper@icem.de>.
1913 *******************************************************************/
1914
1915 static void strip_mount_options( pstring *str)
1916 {
1917   if (**str == '-')
1918   { 
1919     char *p = *str;
1920     while(*p && !isspace(*p))
1921       p++;
1922     while(*p && isspace(*p))
1923       p++;
1924     if(*p) {
1925       pstring tmp_str;
1926
1927       pstrcpy(tmp_str, p);
1928       pstrcpy(*str, tmp_str);
1929     }
1930   }
1931 }
1932
1933 /*******************************************************************
1934  Patch from jkf@soton.ac.uk
1935  Split Luke's automount_server into YP lookup and string splitter
1936  so can easily implement automount_path(). 
1937  As we may end up doing both, cache the last YP result. 
1938 *******************************************************************/
1939
1940 #ifdef WITH_NISPLUS_HOME
1941 static char *automount_lookup(char *user_name)
1942 {
1943   static fstring last_key = "";
1944   static pstring last_value = "";
1945  
1946   char *nis_map = (char *)lp_nis_home_map_name();
1947  
1948   char nis_domain[NIS_MAXNAMELEN + 1];
1949   char buffer[NIS_MAXATTRVAL + 1];
1950   nis_result *result;
1951   nis_object *object;
1952   entry_obj  *entry;
1953  
1954   strncpy(nis_domain, (char *)nis_local_directory(), NIS_MAXNAMELEN);
1955   nis_domain[NIS_MAXNAMELEN] = '\0';
1956  
1957   DEBUG(5, ("NIS+ Domain: %s\n", nis_domain));
1958  
1959   if (strcmp(user_name, last_key))
1960   {
1961     slprintf(buffer, sizeof(buffer)-1, "[%s=%s]%s.%s", "key", user_name, nis_map, nis_domain);
1962     DEBUG(5, ("NIS+ querystring: %s\n", buffer));
1963  
1964     if (result = nis_list(buffer, RETURN_RESULT, NULL, NULL))
1965     {
1966        if (result->status != NIS_SUCCESS)
1967       {
1968         DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
1969         fstrcpy(last_key, ""); pstrcpy(last_value, "");
1970       }
1971       else
1972       {
1973         object = result->objects.objects_val;
1974         if (object->zo_data.zo_type == ENTRY_OBJ)
1975         {
1976            entry = &object->zo_data.objdata_u.en_data;
1977            DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
1978            DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
1979  
1980            pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
1981            pstring_sub(last_value, "&", user_name);
1982            fstrcpy(last_key, user_name);
1983         }
1984       }
1985     }
1986     nis_freeresult(result);
1987   }
1988
1989   strip_mount_options(&last_value);
1990
1991   DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
1992   return last_value;
1993 }
1994 #else /* WITH_NISPLUS_HOME */
1995 static char *automount_lookup(char *user_name)
1996 {
1997   static fstring last_key = "";
1998   static pstring last_value = "";
1999
2000   int nis_error;        /* returned by yp all functions */
2001   char *nis_result;     /* yp_match inits this */
2002   int nis_result_len;  /* and set this */
2003   char *nis_domain;     /* yp_get_default_domain inits this */
2004   char *nis_map = (char *)lp_nis_home_map_name();
2005
2006   if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
2007   {
2008     DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
2009     return last_value;
2010   }
2011
2012   DEBUG(5, ("NIS Domain: %s\n", nis_domain));
2013
2014   if (!strcmp(user_name, last_key))
2015   {
2016     nis_result = last_value;
2017     nis_result_len = strlen(last_value);
2018     nis_error = 0;
2019   }
2020   else
2021   {
2022     if ((nis_error = yp_match(nis_domain, nis_map,
2023                               user_name, strlen(user_name),
2024                               &nis_result, &nis_result_len)) != 0)
2025     {
2026       DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n", 
2027                yperr_string(nis_error), user_name, nis_map));
2028     }
2029     if (!nis_error && nis_result_len >= sizeof(pstring))
2030     {
2031       nis_result_len = sizeof(pstring)-1;
2032     }
2033     fstrcpy(last_key, user_name);
2034     strncpy(last_value, nis_result, nis_result_len);
2035     last_value[nis_result_len] = '\0';
2036   }
2037
2038   strip_mount_options(&last_value);
2039
2040   DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
2041   return last_value;
2042 }
2043 #endif /* WITH_NISPLUS_HOME */
2044 #endif
2045
2046 /*******************************************************************
2047  Patch from jkf@soton.ac.uk
2048  This is Luke's original function with the NIS lookup code
2049  moved out to a separate function.
2050 *******************************************************************/
2051 static char *automount_server(char *user_name)
2052 {
2053         static pstring server_name;
2054
2055         /* use the local machine name as the default */
2056         /* this will be the default if WITH_AUTOMOUNT is not used or fails */
2057         pstrcpy(server_name, local_machine);
2058
2059 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2060
2061         if (lp_nis_home_map())
2062         {
2063                 int home_server_len;
2064                 char *automount_value = automount_lookup(user_name);
2065                 home_server_len = strcspn(automount_value,":");
2066                 DEBUG(5, ("NIS lookup succeeded.  Home server length: %d\n",home_server_len));
2067                 if (home_server_len > sizeof(pstring))
2068                 {
2069                         home_server_len = sizeof(pstring);
2070                 }
2071                 strncpy(server_name, automount_value, home_server_len);
2072                 server_name[home_server_len] = '\0';
2073         }
2074 #endif
2075
2076         DEBUG(4,("Home server: %s\n", server_name));
2077
2078         return server_name;
2079 }
2080
2081 /*******************************************************************
2082  Patch from jkf@soton.ac.uk
2083  Added this to implement %p (NIS auto-map version of %H)
2084 *******************************************************************/
2085 static char *automount_path(char *user_name)
2086 {
2087         static pstring server_path;
2088
2089         /* use the passwd entry as the default */
2090         /* this will be the default if WITH_AUTOMOUNT is not used or fails */
2091         /* pstrcpy() copes with get_user_home_dir() returning NULL */
2092         pstrcpy(server_path, get_user_home_dir(user_name));
2093
2094 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2095
2096         if (lp_nis_home_map())
2097         {
2098                 char *home_path_start;
2099                 char *automount_value = automount_lookup(user_name);
2100                 home_path_start = strchr(automount_value,':');
2101                 if (home_path_start != NULL)
2102                 {
2103                   DEBUG(5, ("NIS lookup succeeded.  Home path is: %s\n",
2104                         home_path_start?(home_path_start+1):""));
2105                   pstrcpy(server_path, home_path_start+1);
2106                 }
2107         }
2108 #endif
2109
2110         DEBUG(4,("Home server path: %s\n", server_path));
2111
2112         return server_path;
2113 }
2114
2115 /*******************************************************************
2116  Given a pointer to a %$(NAME) expand it as an environment variable.
2117  Return the number of characters by which the pointer should be advanced.
2118  Based on code by Branko Cibej <branko.cibej@hermes.si>
2119  When this is called p points at the '%' character.
2120 ********************************************************************/
2121
2122 static size_t expand_env_var(char *p, int len)
2123 {
2124         fstring envname;
2125         char *envval;
2126         char *q, *r;
2127         int copylen;
2128
2129         if (p[1] != '$')
2130                 return 1;
2131
2132         if (p[2] != '(')
2133                 return 2;
2134
2135         /*
2136          * Look for the terminating ')'.
2137          */
2138
2139         if ((q = strchr(p,')')) == NULL) {
2140                 DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p));
2141                 return 2;
2142         }
2143
2144         /*
2145          * Extract the name from within the %$(NAME) string.
2146          */
2147
2148         r = p+3;
2149         copylen = MIN((q-r),(sizeof(envname)-1));
2150         strncpy(envname,r,copylen);
2151         envname[copylen] = '\0';
2152
2153         if ((envval = getenv(envname)) == NULL) {
2154                 DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname));
2155                 return 2;
2156         }
2157
2158         /*
2159          * Copy the full %$(NAME) into envname so it
2160          * can be replaced.
2161          */
2162
2163         copylen = MIN((q+1-p),(sizeof(envname)-1));
2164         strncpy(envname,p,copylen);
2165         envname[copylen] = '\0';
2166         string_sub(p,envname,envval,len);
2167         return 0; /* Allow the environment contents to be parsed. */
2168 }
2169
2170 /*******************************************************************
2171  Substitute strings with useful parameters.
2172  Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
2173  Paul Rippin <pr3245@nopc.eurostat.cec.be>.
2174 ********************************************************************/
2175
2176 void standard_sub_basic(char *str)
2177 {
2178         char *s, *p;
2179         char pidstr[10];
2180         struct passwd *pass;
2181         char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user;
2182
2183         for (s = str ; s && *s && (p = strchr(s,'%')); s = p )
2184         {
2185                 int l = sizeof(pstring) - (int)(p-str);
2186
2187                 if (l < 0) {
2188                         DEBUG(0,("ERROR: string overflow by %d in standard_sub_basic(%.50s)\n", 
2189                                  -l, str));
2190                         
2191                         return;
2192                 }
2193
2194                 switch (*(p+1))
2195                 {
2196                         case 'G' :
2197                         {
2198                                 if ((pass = Get_Pwnam(username,False))!=NULL) {
2199                                         string_sub(p,"%G",gidtoname(pass->pw_gid),l);
2200                                 } else {
2201                                         p += 2;
2202                                 }
2203                                 break;
2204                         }
2205                         case 'N' : string_sub(p,"%N", automount_server(username),l); break;
2206                         case 'I' : string_sub(p,"%I", client_addr(Client),l); break;
2207                         case 'L' : string_sub(p,"%L", local_machine,l); break;
2208                         case 'M' : string_sub(p,"%M", client_name(Client),l); break;
2209                         case 'R' : string_sub(p,"%R", remote_proto,l); break;
2210                         case 'T' : string_sub(p,"%T", timestring(False),l); break;
2211                         case 'U' : string_sub(p,"%U", username,l); break;
2212                         case 'a' : string_sub(p,"%a", remote_arch,l); break;
2213                         case 'd' :
2214                         {
2215                                 slprintf(pidstr,sizeof(pidstr) - 1, "%d",(int)getpid());
2216                                 string_sub(p,"%d", pidstr,l);
2217                                 break;
2218                         }
2219                         case 'h' : string_sub(p,"%h", myhostname(),l); break;
2220                         case 'm' : string_sub(p,"%m", remote_machine,l); break;
2221                         case 'v' : string_sub(p,"%v", VERSION,l); break;
2222                         case '$' : p += expand_env_var(p,l); break; /* Expand environment variables */
2223                         case '\0': p++; break; /* don't run off end if last character is % */
2224                         default  : p+=2; break;
2225                 }
2226         }
2227         return;
2228 }
2229
2230
2231 /****************************************************************************
2232  Do some standard substitutions in a string.
2233 ****************************************************************************/
2234
2235 void standard_sub(connection_struct *conn,char *str)
2236 {
2237         char *p, *s, *home;
2238
2239         for (s=str; (p=strchr(s, '%'));s=p) {
2240                 int l = sizeof(pstring) - (int)(p-str);
2241
2242                 switch (*(p+1)) {
2243                 case 'H': 
2244                         if ((home = get_user_home_dir(conn->user))) {
2245                                 string_sub(p,"%H",home,l);
2246                         } else {
2247                                 p += 2;
2248                         }
2249                         break;
2250                         
2251                 case 'P': 
2252                         string_sub(p,"%P",conn->connectpath,l); 
2253                         break;
2254                         
2255                 case 'S': 
2256                         string_sub(p,"%S",
2257                                    lp_servicename(SNUM(conn)),l); 
2258                         break;
2259                         
2260                 case 'g': 
2261                         string_sub(p,"%g",
2262                                    gidtoname(conn->gid),l); 
2263                         break;
2264                 case 'u': 
2265                         string_sub(p,"%u",conn->user,l); 
2266                         break;
2267                         
2268                         /* Patch from jkf@soton.ac.uk Left the %N (NIS
2269                          * server name) in standard_sub_basic as it is
2270                          * a feature for logon servers, hence uses the
2271                          * username.  The %p (NIS server path) code is
2272                          * here as it is used instead of the default
2273                          * "path =" string in [homes] and so needs the
2274                          * service name, not the username.  */
2275                 case 'p': 
2276                         string_sub(p,"%p",
2277                                    automount_path(lp_servicename(SNUM(conn))),l); 
2278                         break;
2279                 case '\0': 
2280                         p++; 
2281                         break; /* don't run off the end of the string 
2282                                 */
2283                         
2284                 default: p+=2; 
2285                         break;
2286                 }
2287         }
2288         
2289         standard_sub_basic(str);
2290 }
2291
2292
2293
2294 /*******************************************************************
2295 are two IPs on the same subnet?
2296 ********************************************************************/
2297 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
2298 {
2299   uint32 net1,net2,nmask;
2300
2301   nmask = ntohl(mask.s_addr);
2302   net1  = ntohl(ip1.s_addr);
2303   net2  = ntohl(ip2.s_addr);
2304             
2305   return((net1 & nmask) == (net2 & nmask));
2306 }
2307
2308
2309 /****************************************************************************
2310 a wrapper for gethostbyname() that tries with all lower and all upper case 
2311 if the initial name fails
2312 ****************************************************************************/
2313 struct hostent *Get_Hostbyname(const char *name)
2314 {
2315   char *name2 = strdup(name);
2316   struct hostent *ret;
2317
2318   if (!name2)
2319     {
2320       DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
2321       exit(0);
2322     }
2323
2324    
2325   /* 
2326    * This next test is redundent and causes some systems (with
2327    * broken isalnum() calls) problems.
2328    * JRA.
2329    */
2330
2331 #if 0
2332   if (!isalnum(*name2))
2333     {
2334       free(name2);
2335       return(NULL);
2336     }
2337 #endif /* 0 */
2338
2339   ret = sys_gethostbyname(name2);
2340   if (ret != NULL)
2341     {
2342       free(name2);
2343       return(ret);
2344     }
2345
2346   /* try with all lowercase */
2347   strlower(name2);
2348   ret = sys_gethostbyname(name2);
2349   if (ret != NULL)
2350     {
2351       free(name2);
2352       return(ret);
2353     }
2354
2355   /* try with all uppercase */
2356   strupper(name2);
2357   ret = sys_gethostbyname(name2);
2358   if (ret != NULL)
2359     {
2360       free(name2);
2361       return(ret);
2362     }
2363   
2364   /* nothing works :-( */
2365   free(name2);
2366   return(NULL);
2367 }
2368
2369
2370 /****************************************************************************
2371 check if a process exists. Does this work on all unixes?
2372 ****************************************************************************/
2373
2374 BOOL process_exists(pid_t pid)
2375 {
2376         return(kill(pid,0) == 0 || errno != ESRCH);
2377 }
2378
2379
2380 /*******************************************************************
2381 turn a uid into a user name
2382 ********************************************************************/
2383 char *uidtoname(uid_t uid)
2384 {
2385   static char name[40];
2386   struct passwd *pass = sys_getpwuid(uid);
2387   if (pass) return(pass->pw_name);
2388   slprintf(name, sizeof(name) - 1, "%d",(int)uid);
2389   return(name);
2390 }
2391
2392
2393 /*******************************************************************
2394 turn a gid into a group name
2395 ********************************************************************/
2396
2397 char *gidtoname(gid_t gid)
2398 {
2399         static char name[40];
2400         struct group *grp = getgrgid(gid);
2401         if (grp) return(grp->gr_name);
2402         slprintf(name,sizeof(name) - 1, "%d",(int)gid);
2403         return(name);
2404 }
2405
2406 /*******************************************************************
2407 turn a user name into a uid
2408 ********************************************************************/
2409 uid_t nametouid(const char *name)
2410 {
2411         struct passwd *pass;
2412         char *p;
2413         uid_t u;
2414
2415         u = strtol(name, &p, 0);
2416         if (p != name) return u;
2417
2418         pass = sys_getpwnam(name);
2419         if (pass) return(pass->pw_uid);
2420         return (uid_t)-1;
2421 }
2422
2423 /*******************************************************************
2424 turn a group name into a gid
2425 ********************************************************************/
2426 gid_t nametogid(const char *name)
2427 {
2428         struct group *grp;
2429         char *p;
2430         gid_t g;
2431
2432         g = strtol(name, &p, 0);
2433         if (p != name) return g;
2434
2435         grp = getgrnam(name);
2436         if (grp) return(grp->gr_gid);
2437         return (gid_t)-1;
2438 }
2439
2440 /*******************************************************************
2441 something really nasty happened - panic!
2442 ********************************************************************/
2443 void smb_panic(char *why)
2444 {
2445         char *cmd = lp_panic_action();
2446         if (cmd && *cmd) {
2447                 system(cmd);
2448         }
2449         DEBUG(0,("PANIC: %s\n", why));
2450         dbgflush();
2451         abort();
2452 }
2453
2454
2455 /*******************************************************************
2456 a readdir wrapper which just returns the file name
2457 ********************************************************************/
2458 char *readdirname(DIR *p)
2459 {
2460         SMB_STRUCT_DIRENT *ptr;
2461         char *dname;
2462
2463         if (!p) return(NULL);
2464   
2465         ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
2466         if (!ptr) return(NULL);
2467
2468         dname = ptr->d_name;
2469
2470 #ifdef NEXT2
2471         if (telldir(p) < 0) return(NULL);
2472 #endif
2473
2474 #ifdef HAVE_BROKEN_READDIR
2475         /* using /usr/ucb/cc is BAD */
2476         dname = dname - 2;
2477 #endif
2478
2479         {
2480                 static pstring buf;
2481                 memcpy(buf, dname, NAMLEN(ptr)+1);
2482                 dname = buf;
2483         }
2484
2485         return(dname);
2486 }
2487
2488 /*******************************************************************
2489  Utility function used to decide if the last component 
2490  of a path matches a (possibly wildcarded) entry in a namelist.
2491 ********************************************************************/
2492
2493 BOOL is_in_path(char *name, name_compare_entry *namelist)
2494 {
2495   pstring last_component;
2496   char *p;
2497
2498   DEBUG(8, ("is_in_path: %s\n", name));
2499
2500   /* if we have no list it's obviously not in the path */
2501   if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) 
2502   {
2503     DEBUG(8,("is_in_path: no name list.\n"));
2504     return False;
2505   }
2506
2507   /* Get the last component of the unix name. */
2508   p = strrchr(name, '/');
2509   strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
2510   last_component[sizeof(last_component)-1] = '\0'; 
2511
2512   for(; namelist->name != NULL; namelist++)
2513   {
2514     if(namelist->is_wild)
2515     {
2516       /* 
2517        * Look for a wildcard match. Use the old
2518        * 'unix style' mask match, rather than the
2519        * new NT one.
2520        */
2521       if (unix_mask_match(last_component, namelist->name, case_sensitive, False))
2522       {
2523          DEBUG(8,("is_in_path: mask match succeeded\n"));
2524          return True;
2525       }
2526     }
2527     else
2528     {
2529       if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
2530        (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0)))
2531         {
2532          DEBUG(8,("is_in_path: match succeeded\n"));
2533          return True;
2534         }
2535     }
2536   }
2537   DEBUG(8,("is_in_path: match not found\n"));
2538  
2539   return False;
2540 }
2541
2542 /*******************************************************************
2543  Strip a '/' separated list into an array of 
2544  name_compare_enties structures suitable for 
2545  passing to is_in_path(). We do this for
2546  speed so we can pre-parse all the names in the list 
2547  and don't do it for each call to is_in_path().
2548  namelist is modified here and is assumed to be 
2549  a copy owned by the caller.
2550  We also check if the entry contains a wildcard to
2551  remove a potentially expensive call to mask_match
2552  if possible.
2553 ********************************************************************/
2554  
2555 void set_namearray(name_compare_entry **ppname_array, char *namelist)
2556 {
2557   char *name_end;
2558   char *nameptr = namelist;
2559   int num_entries = 0;
2560   int i;
2561
2562   (*ppname_array) = NULL;
2563
2564   if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0'))) 
2565     return;
2566
2567   /* We need to make two passes over the string. The
2568      first to count the number of elements, the second
2569      to split it.
2570    */
2571   while(*nameptr) 
2572     {
2573       if ( *nameptr == '/' ) 
2574         {
2575           /* cope with multiple (useless) /s) */
2576           nameptr++;
2577           continue;
2578         }
2579       /* find the next / */
2580       name_end = strchr(nameptr, '/');
2581
2582       /* oops - the last check for a / didn't find one. */
2583       if (name_end == NULL)
2584         break;
2585
2586       /* next segment please */
2587       nameptr = name_end + 1;
2588       num_entries++;
2589     }
2590
2591   if(num_entries == 0)
2592     return;
2593
2594   if(( (*ppname_array) = (name_compare_entry *)malloc( 
2595            (num_entries + 1) * sizeof(name_compare_entry))) == NULL)
2596         {
2597     DEBUG(0,("set_namearray: malloc fail\n"));
2598     return;
2599         }
2600
2601   /* Now copy out the names */
2602   nameptr = namelist;
2603   i = 0;
2604   while(*nameptr)
2605              {
2606       if ( *nameptr == '/' ) 
2607       {
2608           /* cope with multiple (useless) /s) */
2609           nameptr++;
2610           continue;
2611       }
2612       /* find the next / */
2613       if ((name_end = strchr(nameptr, '/')) != NULL) 
2614       {
2615           *name_end = 0;
2616          }
2617
2618       /* oops - the last check for a / didn't find one. */
2619       if(name_end == NULL) 
2620         break;
2621
2622       (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
2623                                 (strchr( nameptr, '*')!=NULL));
2624       if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
2625       {
2626         DEBUG(0,("set_namearray: malloc fail (1)\n"));
2627         return;
2628       }
2629
2630       /* next segment please */
2631       nameptr = name_end + 1;
2632       i++;
2633     }
2634   
2635   (*ppname_array)[i].name = NULL;
2636
2637   return;
2638 }
2639
2640 /****************************************************************************
2641 routine to free a namearray.
2642 ****************************************************************************/
2643
2644 void free_namearray(name_compare_entry *name_array)
2645 {
2646   if(name_array == 0)
2647     return;
2648
2649   if(name_array->name != NULL)
2650     free(name_array->name);
2651
2652   free((char *)name_array);
2653 }
2654
2655 /****************************************************************************
2656  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
2657 ****************************************************************************/
2658
2659 uint32 map_lock_offset(uint32 high, uint32 low)
2660 {
2661   unsigned int i;
2662   uint32 mask = 0;
2663   uint32 highcopy = high;
2664
2665   /*
2666    * Try and find out how many significant bits there are in high.
2667    */
2668
2669   for(i = 0; highcopy; i++)
2670     highcopy >>= 1;
2671
2672   /*
2673    * We use 31 bits not 32 here as POSIX
2674    * lock offsets may not be negative.
2675    */
2676
2677   mask = (~0) << (31 - i);
2678
2679   if(low & mask)
2680     return 0; /* Fail. */
2681
2682   high <<= (31 - i);
2683
2684   return (high|low);
2685 }
2686
2687 /****************************************************************************
2688 routine to do file locking
2689 ****************************************************************************/
2690
2691 BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
2692 {
2693 #if HAVE_FCNTL_LOCK
2694   SMB_STRUCT_FLOCK lock;
2695   int ret;
2696 #if defined(LARGE_SMB_OFF_T)
2697   /*
2698    * In the 64 bit locking case we store the original
2699    * values in case we have to map to a 32 bit lock on
2700    * a filesystem that doesn't support 64 bit locks.
2701    */
2702   SMB_OFF_T orig_offset = offset;
2703   SMB_OFF_T orig_count = count;
2704 #endif /* LARGE_SMB_OFF_T */
2705
2706   if(lp_ole_locking_compat()) {
2707     SMB_OFF_T mask2= ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4);
2708     SMB_OFF_T mask = (mask2<<2);
2709
2710     /* make sure the count is reasonable, we might kill the lockd otherwise */
2711     count &= ~mask;
2712
2713     /* the offset is often strange - remove 2 of its bits if either of
2714        the top two bits are set. Shift the top ones by two bits. This
2715        still allows OLE2 apps to operate, but should stop lockd from
2716        dieing */
2717     if ((offset & mask) != 0)
2718       offset = (offset & ~mask) | (((offset & mask) >> 2) & mask2);
2719   } else {
2720     SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
2721     SMB_OFF_T mask = (mask2<<1);
2722     SMB_OFF_T neg_mask = ~mask;
2723
2724     /* interpret negative counts as large numbers */
2725     if (count < 0)
2726       count &= ~mask;
2727
2728     /* no negative offsets */
2729     if(offset < 0)
2730       offset &= ~mask;
2731
2732     /* count + offset must be in range */
2733     while ((offset < 0 || (offset + count < 0)) && mask)
2734     {
2735       offset &= ~mask;
2736       mask = ((mask >> 1) & neg_mask);
2737     }
2738   }
2739
2740   DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
2741
2742   lock.l_type = type;
2743   lock.l_whence = SEEK_SET;
2744   lock.l_start = offset;
2745   lock.l_len = count;
2746   lock.l_pid = 0;
2747
2748   errno = 0;
2749
2750   ret = fcntl(fd,op,&lock);
2751   if (errno == EFBIG)
2752   {
2753     if( DEBUGLVL( 0 ))
2754     {
2755       dbgtext("fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count);
2756       dbgtext("a 'file too large' error. This can happen when using 64 bit lock offsets\n");
2757       dbgtext("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n");
2758     }
2759     /* 32 bit NFS file system, retry with smaller offset */
2760     errno = 0;
2761     lock.l_len = count & 0x7fffffff;
2762     ret = fcntl(fd,op,&lock);
2763   }
2764
2765   if (errno != 0)
2766     DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
2767
2768   /* a lock query */
2769   if (op == SMB_F_GETLK)
2770   {
2771     if ((ret != -1) &&
2772         (lock.l_type != F_UNLCK) && 
2773         (lock.l_pid != 0) && 
2774         (lock.l_pid != getpid()))
2775     {
2776       DEBUG(3,("fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
2777       return(True);
2778     }
2779
2780     /* it must be not locked or locked by me */
2781     return(False);
2782   }
2783
2784   /* a lock set or unset */
2785   if (ret == -1)
2786   {
2787     DEBUG(3,("lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
2788           (double)offset,(double)count,op,type,strerror(errno)));
2789
2790     /* perhaps it doesn't support this sort of locking?? */
2791     if (errno == EINVAL)
2792     {
2793
2794 #if defined(LARGE_SMB_OFF_T)
2795       {
2796         /*
2797          * Ok - if we get here then we have a 64 bit lock request
2798          * that has returned EINVAL. Try and map to 31 bits for offset
2799          * and length and try again. This may happen if a filesystem
2800          * doesn't support 64 bit offsets (efs/ufs) although the underlying
2801          * OS does.
2802          */
2803         uint32 off_low = (orig_offset & 0xFFFFFFFF);
2804         uint32 off_high = ((orig_offset >> 32) & 0xFFFFFFFF);
2805
2806         lock.l_len = (orig_count & 0x7FFFFFFF);
2807         lock.l_start = (SMB_OFF_T)map_lock_offset(off_high, off_low);
2808         ret = fcntl(fd,op,&lock);
2809         if (ret == -1)
2810         {
2811           if (errno == EINVAL)
2812           {
2813             DEBUG(3,("locking not supported? returning True\n"));
2814             return(True);
2815           }
2816           return False;
2817         }
2818         DEBUG(3,("64 -> 32 bit modified lock call successful\n"));
2819         return True;
2820       }
2821 #else /* LARGE_SMB_OFF_T */
2822       DEBUG(3,("locking not supported? returning True\n"));
2823       return(True);
2824 #endif /* LARGE_SMB_OFF_T */
2825     }
2826
2827     return(False);
2828   }
2829
2830   /* everything went OK */
2831   DEBUG(8,("Lock call successful\n"));
2832
2833   return(True);
2834 #else
2835   return(False);
2836 #endif
2837 }
2838
2839 /*******************************************************************
2840 is the name specified one of my netbios names
2841 returns true is it is equal, false otherwise
2842 ********************************************************************/
2843 BOOL is_myname(char *s)
2844 {
2845   int n;
2846   BOOL ret = False;
2847
2848   for (n=0; my_netbios_names[n]; n++) {
2849     if (strequal(my_netbios_names[n], s))
2850       ret=True;
2851   }
2852   DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
2853   return(ret);
2854 }
2855
2856 /*******************************************************************
2857 set the horrid remote_arch string based on an enum.
2858 ********************************************************************/
2859 void set_remote_arch(enum remote_arch_types type)
2860 {
2861   ra_type = type;
2862   switch( type )
2863   {
2864   case RA_WFWG:
2865     fstrcpy(remote_arch, "WfWg");
2866     return;
2867   case RA_OS2:
2868     fstrcpy(remote_arch, "OS2");
2869     return;
2870   case RA_WIN95:
2871     fstrcpy(remote_arch, "Win95");
2872     return;
2873   case RA_WINNT:
2874     fstrcpy(remote_arch, "WinNT");
2875     return;
2876   case RA_WIN2K:
2877     fstrcpy(remote_arch, "Win2K");
2878     return;
2879   case RA_SAMBA:
2880     fstrcpy(remote_arch,"Samba");
2881     return;
2882   default:
2883     ra_type = RA_UNKNOWN;
2884     fstrcpy(remote_arch, "UNKNOWN");
2885     break;
2886   }
2887 }
2888
2889 /*******************************************************************
2890  Get the remote_arch type.
2891 ********************************************************************/
2892 enum remote_arch_types get_remote_arch(void)
2893 {
2894   return ra_type;
2895 }
2896
2897
2898 /*******************************************************************
2899 align a pointer to a multiple of 2 bytes
2900 ********************************************************************/
2901 char *align2(char *q, char *base)
2902 {
2903         if ((q - base) & 1)
2904         {
2905                 q++;
2906         }
2907         return q;
2908 }
2909
2910 void out_ascii(FILE *f, unsigned char *buf,int len)
2911 {
2912         int i;
2913         for (i=0;i<len;i++)
2914         {
2915                 fprintf(f, "%c", isprint(buf[i])?buf[i]:'.');
2916         }
2917 }
2918
2919 void out_data(FILE *f,char *buf1,int len, int per_line)
2920 {
2921         unsigned char *buf = (unsigned char *)buf1;
2922         int i=0;
2923         if (len<=0)
2924         {
2925                 return;
2926         }
2927
2928         fprintf(f, "[%03X] ",i);
2929         for (i=0;i<len;)
2930         {
2931                 fprintf(f, "%02X ",(int)buf[i]);
2932                 i++;
2933                 if (i%(per_line/2) == 0) fprintf(f, " ");
2934                 if (i%per_line == 0)
2935                 {      
2936                         out_ascii(f,&buf[i-per_line  ],per_line/2); fprintf(f, " ");
2937                         out_ascii(f,&buf[i-per_line/2],per_line/2); fprintf(f, "\n");
2938                         if (i<len) fprintf(f, "[%03X] ",i);
2939                 }
2940         }
2941         if ((i%per_line) != 0)
2942         {
2943                 int n;
2944
2945                 n = per_line - (i%per_line);
2946                 fprintf(f, " ");
2947                 if (n>(per_line/2)) fprintf(f, " ");
2948                 while (n--)
2949                 {
2950                         fprintf(f, "   ");
2951                 }
2952                 n = MIN(per_line/2,i%per_line);
2953                 out_ascii(f,&buf[i-(i%per_line)],n); fprintf(f, " ");
2954                 n = (i%per_line) - n;
2955                 if (n>0) out_ascii(f,&buf[i-n],n); 
2956                 fprintf(f, "\n");    
2957         }
2958 }
2959
2960 void print_asc(int level, unsigned char *buf,int len)
2961 {
2962         int i;
2963         for (i=0;i<len;i++)
2964                 DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
2965 }
2966
2967 void dump_data(int level,char *buf1,int len)
2968 {
2969   unsigned char *buf = (unsigned char *)buf1;
2970   int i=0;
2971   if (len<=0) return;
2972
2973   DEBUG(level,("[%03X] ",i));
2974   for (i=0;i<len;) {
2975     DEBUG(level,("%02X ",(int)buf[i]));
2976     i++;
2977     if (i%8 == 0) DEBUG(level,(" "));
2978     if (i%16 == 0) {      
2979       print_asc(level,&buf[i-16],8); DEBUG(level,(" "));
2980       print_asc(level,&buf[i-8],8); DEBUG(level,("\n"));
2981       if (i<len) DEBUG(level,("[%03X] ",i));
2982     }
2983   }
2984   if (i%16) {
2985     int n;
2986
2987     n = 16 - (i%16);
2988     DEBUG(level,(" "));
2989     if (n>8) DEBUG(level,(" "));
2990     while (n--) DEBUG(level,("   "));
2991
2992     n = MIN(8,i%16);
2993     print_asc(level,&buf[i-(i%16)],n); DEBUG(level,(" "));
2994     n = (i%16) - n;
2995     if (n>0) print_asc(level,&buf[i-n],n); 
2996     DEBUG(level,("\n"));    
2997   }
2998 }
2999
3000 char *tab_depth(int depth)
3001 {
3002         static pstring spaces;
3003         memset(spaces, ' ', depth * 4);
3004         spaces[depth * 4] = 0;
3005         return spaces;
3006 }
3007
3008 /*****************************************************************************
3009  * Provide a checksum on a string
3010  *
3011  *  Input:  s - the null-terminated character string for which the checksum
3012  *              will be calculated.
3013  *
3014  *  Output: The checksum value calculated for s.
3015  *
3016  * ****************************************************************************
3017  */
3018 int str_checksum(const char *s)
3019 {
3020         int res = 0;
3021         int c;
3022         int i=0;
3023         
3024         while(*s) {
3025                 c = *s;
3026                 res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
3027                 s++;
3028                 i++;
3029         }
3030         return(res);
3031 } /* str_checksum */
3032
3033
3034
3035 /*****************************************************************
3036 zero a memory area then free it. Used to catch bugs faster
3037 *****************************************************************/  
3038 void zero_free(void *p, size_t size)
3039 {
3040         memset(p, 0, size);
3041         free(p);
3042 }
3043
3044
3045 /*****************************************************************
3046 set our open file limit to a requested max and return the limit
3047 *****************************************************************/  
3048 int set_maxfiles(int requested_max)
3049 {
3050 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
3051         struct rlimit rlp;
3052         int saved_current_limit;
3053
3054         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
3055                 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
3056                         strerror(errno) ));
3057                 /* just guess... */
3058                 return requested_max;
3059         }
3060
3061         /* 
3062      * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
3063          * account for the extra fd we need 
3064          * as well as the log files and standard
3065          * handles etc. Save the limit we want to set in case
3066          * we are running on an OS that doesn't support this limit (AIX)
3067          * which always returns RLIM_INFINITY for rlp.rlim_max.
3068          */
3069
3070         saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
3071
3072         if(setrlimit(RLIMIT_NOFILE, &rlp)) {
3073                 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n", 
3074                         (int)rlp.rlim_cur, strerror(errno) ));
3075                 /* just guess... */
3076                 return saved_current_limit;
3077         }
3078
3079         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
3080                 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
3081                         strerror(errno) ));
3082                 /* just guess... */
3083                 return saved_current_limit;
3084     }
3085
3086 #if defined(RLIM_INFINITY)
3087         if(rlp.rlim_cur == RLIM_INFINITY)
3088                 return saved_current_limit;
3089 #endif
3090
3091     if((int)rlp.rlim_cur > saved_current_limit)
3092                 return saved_current_limit;
3093
3094         return rlp.rlim_cur;
3095 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
3096         /*
3097          * No way to know - just guess...
3098          */
3099         return requested_max;
3100 #endif
3101 }
3102
3103
3104 /*****************************************************************
3105  splits out the last subkey of a key
3106  *****************************************************************/  
3107 void reg_get_subkey(char *full_keyname, char *key_name, char *subkey_name)
3108 {
3109         split_at_last_component(full_keyname, key_name, '\\', subkey_name);
3110 }
3111
3112 /*****************************************************************
3113  splits out the start of the key (HKLM or HKU) and the rest of the key
3114  *****************************************************************/  
3115 BOOL reg_split_key(char *full_keyname, uint32 *reg_type, char *key_name)
3116 {
3117         pstring tmp;
3118
3119         if (!next_token(&full_keyname, tmp, "\\", sizeof(tmp)))
3120         {
3121                 return False;
3122         }
3123
3124         (*reg_type) = 0;
3125
3126         DEBUG(10, ("reg_split_key: hive %s\n", tmp));
3127
3128         if (strequal(tmp, "HKLM") || strequal(tmp, "HKEY_LOCAL_MACHINE"))
3129         {
3130                 (*reg_type) = HKEY_LOCAL_MACHINE;
3131         }
3132         else if (strequal(tmp, "HKU") || strequal(tmp, "HKEY_USERS"))
3133         {
3134                 (*reg_type) = HKEY_USERS;
3135         }
3136         else
3137         {
3138                 DEBUG(10,("reg_split_key: unrecognised hive key %s\n", tmp));
3139                 return False;
3140         }
3141         
3142         if (next_token(NULL, tmp, "\n\r", sizeof(tmp)))
3143         {
3144                 fstrcpy(key_name, tmp);
3145         }
3146         else
3147         {
3148                 key_name[0] = 0;
3149         }
3150
3151         DEBUG(10, ("reg_split_key: name %s\n", key_name));
3152
3153         return True;
3154 }
3155
3156
3157 /*****************************************************************
3158 like mktemp() but make sure that no % characters are used
3159 % characters are bad for us because of the macro subs
3160  *****************************************************************/  
3161 char *smbd_mktemp(char *template)
3162 {
3163         char *p = mktemp(template);
3164         char *p2;
3165         SMB_STRUCT_STAT st;
3166
3167         if (!p) return NULL;
3168
3169         while ((p2=strchr(p,'%'))) {
3170                 p2[0] = 'A';
3171                 while (sys_stat(p,&st) == 0 && p2[0] < 'Z') {
3172                         /* damn, it exists */
3173                         p2[0]++;
3174                 }
3175                 if (p2[0] == 'Z') {
3176                         /* oh well ... better return something */
3177                         p2[0] = '%';
3178                         return p;
3179                 }
3180         }
3181
3182         return p;
3183 }
3184
3185
3186 /*****************************************************************
3187 like strdup but for memory
3188  *****************************************************************/  
3189 void *memdup(void *p, size_t size)
3190 {
3191         void *p2;
3192         p2 = malloc(size);
3193         if (!p2) return NULL;
3194         memcpy(p2, p, size);
3195         return p2;
3196 }
3197
3198 /*****************************************************************
3199 get local hostname and cache result
3200  *****************************************************************/  
3201 char *myhostname(void)
3202 {
3203         static pstring ret;
3204         if (ret[0] == 0) {
3205                 get_myname(ret);
3206         }
3207         return ret;
3208 }
3209
3210
3211 /*****************************************************************
3212 a useful function for returning a path in the Samba lock directory
3213  *****************************************************************/  
3214 char *lock_path(char *name)
3215 {
3216         static pstring fname;
3217
3218         pstrcpy(fname,lp_lockdir());
3219         trim_string(fname,"","/");
3220         
3221         if (!directory_exist(fname,NULL)) {
3222                 mkdir(fname,0755);
3223         }
3224         
3225         pstrcat(fname,"/");
3226         pstrcat(fname,name);
3227
3228         return fname;
3229 }