first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[nivanova/samba-autobuild/.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 #ifdef MEM_MAN
1720   {
1721         extern FILE *dbf;
1722         smb_mem_write_info(ret, dbf);
1723   }
1724 #endif
1725
1726   if (!ret)
1727     DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size));
1728
1729   return(ret);
1730 }
1731
1732
1733 /****************************************************************************
1734 get my own name and IP
1735 ****************************************************************************/
1736 BOOL get_myname(char *my_name)
1737 {
1738         pstring hostname;
1739
1740         *hostname = 0;
1741
1742         /* get my host name */
1743         if (gethostname(hostname, sizeof(hostname)) == -1) {
1744                 DEBUG(0,("gethostname failed\n"));
1745                 return False;
1746         } 
1747
1748         /* Ensure null termination. */
1749         hostname[sizeof(hostname)-1] = '\0';
1750
1751         if (my_name) {
1752                 /* split off any parts after an initial . */
1753                 char *p = strchr(hostname,'.');
1754                 if (p) *p = 0;
1755                 
1756                 fstrcpy(my_name,hostname);
1757         }
1758         
1759         return(True);
1760 }
1761
1762
1763 /****************************************************************************
1764 true if two IP addresses are equal
1765 ****************************************************************************/
1766 BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
1767 {
1768         return ip1.s_addr == ip2.s_addr;
1769 }
1770
1771
1772 /****************************************************************************
1773 interpret a protocol description string, with a default
1774 ****************************************************************************/
1775 int interpret_protocol(char *str,int def)
1776 {
1777   if (strequal(str,"NT1"))
1778     return(PROTOCOL_NT1);
1779   if (strequal(str,"LANMAN2"))
1780     return(PROTOCOL_LANMAN2);
1781   if (strequal(str,"LANMAN1"))
1782     return(PROTOCOL_LANMAN1);
1783   if (strequal(str,"CORE"))
1784     return(PROTOCOL_CORE);
1785   if (strequal(str,"COREPLUS"))
1786     return(PROTOCOL_COREPLUS);
1787   if (strequal(str,"CORE+"))
1788     return(PROTOCOL_COREPLUS);
1789   
1790   DEBUG(0,("Unrecognised protocol level %s\n",str));
1791   
1792   return(def);
1793 }
1794
1795 /****************************************************************************
1796  Return true if a string could be a pure IP address.
1797 ****************************************************************************/
1798
1799 BOOL is_ipaddress(const char *str)
1800 {
1801   BOOL pure_address = True;
1802   int i;
1803   
1804   for (i=0; pure_address && str[i]; i++)
1805     if (!(isdigit((int)str[i]) || str[i] == '.'))
1806       pure_address = False;
1807
1808   /* Check that a pure number is not misinterpreted as an IP */
1809   pure_address = pure_address && (strchr(str, '.') != NULL);
1810
1811   return pure_address;
1812 }
1813
1814 /****************************************************************************
1815 interpret an internet address or name into an IP address in 4 byte form
1816 ****************************************************************************/
1817
1818 uint32 interpret_addr(char *str)
1819 {
1820   struct hostent *hp;
1821   uint32 res;
1822
1823   if (strcmp(str,"0.0.0.0") == 0) return(0);
1824   if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
1825
1826   /* if it's in the form of an IP address then get the lib to interpret it */
1827   if (is_ipaddress(str)) {
1828     res = inet_addr(str);
1829   } else {
1830     /* otherwise assume it's a network name of some sort and use 
1831        Get_Hostbyname */
1832     if ((hp = Get_Hostbyname(str)) == 0) {
1833       DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
1834       return 0;
1835     }
1836     if(hp->h_addr == NULL) {
1837       DEBUG(3,("Get_Hostbyname: host address is invalid for host %s\n",str));
1838       return 0;
1839     }
1840     putip((char *)&res,(char *)hp->h_addr);
1841   }
1842
1843   if (res == (uint32)-1) return(0);
1844
1845   return(res);
1846 }
1847
1848 /*******************************************************************
1849   a convenient addition to interpret_addr()
1850   ******************************************************************/
1851 struct in_addr *interpret_addr2(char *str)
1852 {
1853   static struct in_addr ret;
1854   uint32 a = interpret_addr(str);
1855   ret.s_addr = a;
1856   return(&ret);
1857 }
1858
1859 /*******************************************************************
1860   check if an IP is the 0.0.0.0
1861   ******************************************************************/
1862 BOOL zero_ip(struct in_addr ip)
1863 {
1864   uint32 a;
1865   putip((char *)&a,(char *)&ip);
1866   return(a == 0);
1867 }
1868
1869
1870 /*******************************************************************
1871  matchname - determine if host name matches IP address 
1872  ******************************************************************/
1873 BOOL matchname(char *remotehost,struct in_addr  addr)
1874 {
1875   struct hostent *hp;
1876   int     i;
1877   
1878   if ((hp = Get_Hostbyname(remotehost)) == 0) {
1879     DEBUG(0,("Get_Hostbyname(%s): lookup failure.\n", remotehost));
1880     return False;
1881   } 
1882
1883   /*
1884    * Make sure that gethostbyname() returns the "correct" host name.
1885    * Unfortunately, gethostbyname("localhost") sometimes yields
1886    * "localhost.domain". Since the latter host name comes from the
1887    * local DNS, we just have to trust it (all bets are off if the local
1888    * DNS is perverted). We always check the address list, though.
1889    */
1890   
1891   if (strcasecmp(remotehost, hp->h_name)
1892       && strcasecmp(remotehost, "localhost")) {
1893     DEBUG(0,("host name/name mismatch: %s != %s\n",
1894              remotehost, hp->h_name));
1895     return False;
1896   }
1897         
1898   /* Look up the host address in the address list we just got. */
1899   for (i = 0; hp->h_addr_list[i]; i++) {
1900     if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
1901       return True;
1902   }
1903
1904   /*
1905    * The host name does not map to the original host address. Perhaps
1906    * someone has compromised a name server. More likely someone botched
1907    * it, but that could be dangerous, too.
1908    */
1909   
1910   DEBUG(0,("host name/address mismatch: %s != %s\n",
1911            inet_ntoa(addr), hp->h_name));
1912   return False;
1913 }
1914
1915
1916 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1917 /******************************************************************
1918  Remove any mount options such as -rsize=2048,wsize=2048 etc.
1919  Based on a fix from <Thomas.Hepper@icem.de>.
1920 *******************************************************************/
1921
1922 static void strip_mount_options( pstring *str)
1923 {
1924   if (**str == '-')
1925   { 
1926     char *p = *str;
1927     while(*p && !isspace(*p))
1928       p++;
1929     while(*p && isspace(*p))
1930       p++;
1931     if(*p) {
1932       pstring tmp_str;
1933
1934       pstrcpy(tmp_str, p);
1935       pstrcpy(*str, tmp_str);
1936     }
1937   }
1938 }
1939
1940 /*******************************************************************
1941  Patch from jkf@soton.ac.uk
1942  Split Luke's automount_server into YP lookup and string splitter
1943  so can easily implement automount_path(). 
1944  As we may end up doing both, cache the last YP result. 
1945 *******************************************************************/
1946
1947 #ifdef WITH_NISPLUS_HOME
1948 static char *automount_lookup(char *user_name)
1949 {
1950   static fstring last_key = "";
1951   static pstring last_value = "";
1952  
1953   char *nis_map = (char *)lp_nis_home_map_name();
1954  
1955   char nis_domain[NIS_MAXNAMELEN + 1];
1956   char buffer[NIS_MAXATTRVAL + 1];
1957   nis_result *result;
1958   nis_object *object;
1959   entry_obj  *entry;
1960  
1961   strncpy(nis_domain, (char *)nis_local_directory(), NIS_MAXNAMELEN);
1962   nis_domain[NIS_MAXNAMELEN] = '\0';
1963  
1964   DEBUG(5, ("NIS+ Domain: %s\n", nis_domain));
1965  
1966   if (strcmp(user_name, last_key))
1967   {
1968     slprintf(buffer, sizeof(buffer)-1, "[%s=%s]%s.%s", "key", user_name, nis_map, nis_domain);
1969     DEBUG(5, ("NIS+ querystring: %s\n", buffer));
1970  
1971     if (result = nis_list(buffer, RETURN_RESULT, NULL, NULL))
1972     {
1973        if (result->status != NIS_SUCCESS)
1974       {
1975         DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
1976         fstrcpy(last_key, ""); pstrcpy(last_value, "");
1977       }
1978       else
1979       {
1980         object = result->objects.objects_val;
1981         if (object->zo_data.zo_type == ENTRY_OBJ)
1982         {
1983            entry = &object->zo_data.objdata_u.en_data;
1984            DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
1985            DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
1986  
1987            pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
1988            pstring_sub(last_value, "&", user_name);
1989            fstrcpy(last_key, user_name);
1990         }
1991       }
1992     }
1993     nis_freeresult(result);
1994   }
1995
1996   strip_mount_options(&last_value);
1997
1998   DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
1999   return last_value;
2000 }
2001 #else /* WITH_NISPLUS_HOME */
2002 static char *automount_lookup(char *user_name)
2003 {
2004   static fstring last_key = "";
2005   static pstring last_value = "";
2006
2007   int nis_error;        /* returned by yp all functions */
2008   char *nis_result;     /* yp_match inits this */
2009   int nis_result_len;  /* and set this */
2010   char *nis_domain;     /* yp_get_default_domain inits this */
2011   char *nis_map = (char *)lp_nis_home_map_name();
2012
2013   if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
2014   {
2015     DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
2016     return last_value;
2017   }
2018
2019   DEBUG(5, ("NIS Domain: %s\n", nis_domain));
2020
2021   if (!strcmp(user_name, last_key))
2022   {
2023     nis_result = last_value;
2024     nis_result_len = strlen(last_value);
2025     nis_error = 0;
2026   }
2027   else
2028   {
2029     if ((nis_error = yp_match(nis_domain, nis_map,
2030                               user_name, strlen(user_name),
2031                               &nis_result, &nis_result_len)) != 0)
2032     {
2033       DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n", 
2034                yperr_string(nis_error), user_name, nis_map));
2035     }
2036     if (!nis_error && nis_result_len >= sizeof(pstring))
2037     {
2038       nis_result_len = sizeof(pstring)-1;
2039     }
2040     fstrcpy(last_key, user_name);
2041     strncpy(last_value, nis_result, nis_result_len);
2042     last_value[nis_result_len] = '\0';
2043   }
2044
2045   strip_mount_options(&last_value);
2046
2047   DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
2048   return last_value;
2049 }
2050 #endif /* WITH_NISPLUS_HOME */
2051 #endif
2052
2053 /*******************************************************************
2054  Patch from jkf@soton.ac.uk
2055  This is Luke's original function with the NIS lookup code
2056  moved out to a separate function.
2057 *******************************************************************/
2058 static char *automount_server(char *user_name)
2059 {
2060         static pstring server_name;
2061
2062         /* use the local machine name as the default */
2063         /* this will be the default if WITH_AUTOMOUNT is not used or fails */
2064         pstrcpy(server_name, local_machine);
2065
2066 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2067
2068         if (lp_nis_home_map())
2069         {
2070                 int home_server_len;
2071                 char *automount_value = automount_lookup(user_name);
2072                 home_server_len = strcspn(automount_value,":");
2073                 DEBUG(5, ("NIS lookup succeeded.  Home server length: %d\n",home_server_len));
2074                 if (home_server_len > sizeof(pstring))
2075                 {
2076                         home_server_len = sizeof(pstring);
2077                 }
2078                 strncpy(server_name, automount_value, home_server_len);
2079                 server_name[home_server_len] = '\0';
2080         }
2081 #endif
2082
2083         DEBUG(4,("Home server: %s\n", server_name));
2084
2085         return server_name;
2086 }
2087
2088 /*******************************************************************
2089  Patch from jkf@soton.ac.uk
2090  Added this to implement %p (NIS auto-map version of %H)
2091 *******************************************************************/
2092 static char *automount_path(char *user_name)
2093 {
2094         static pstring server_path;
2095
2096         /* use the passwd entry as the default */
2097         /* this will be the default if WITH_AUTOMOUNT is not used or fails */
2098         /* pstrcpy() copes with get_user_home_dir() returning NULL */
2099         pstrcpy(server_path, get_user_home_dir(user_name));
2100
2101 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2102
2103         if (lp_nis_home_map())
2104         {
2105                 char *home_path_start;
2106                 char *automount_value = automount_lookup(user_name);
2107                 home_path_start = strchr(automount_value,':');
2108                 if (home_path_start != NULL)
2109                 {
2110                   DEBUG(5, ("NIS lookup succeeded.  Home path is: %s\n",
2111                         home_path_start?(home_path_start+1):""));
2112                   pstrcpy(server_path, home_path_start+1);
2113                 }
2114         }
2115 #endif
2116
2117         DEBUG(4,("Home server path: %s\n", server_path));
2118
2119         return server_path;
2120 }
2121
2122 /*******************************************************************
2123  Given a pointer to a %$(NAME) expand it as an environment variable.
2124  Return the number of characters by which the pointer should be advanced.
2125  Based on code by Branko Cibej <branko.cibej@hermes.si>
2126  When this is called p points at the '%' character.
2127 ********************************************************************/
2128
2129 static size_t expand_env_var(char *p, int len)
2130 {
2131         fstring envname;
2132         char *envval;
2133         char *q, *r;
2134         int copylen;
2135
2136         if (p[1] != '$')
2137                 return 1;
2138
2139         if (p[2] != '(')
2140                 return 2;
2141
2142         /*
2143          * Look for the terminating ')'.
2144          */
2145
2146         if ((q = strchr(p,')')) == NULL) {
2147                 DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p));
2148                 return 2;
2149         }
2150
2151         /*
2152          * Extract the name from within the %$(NAME) string.
2153          */
2154
2155         r = p+3;
2156         copylen = MIN((q-r),(sizeof(envname)-1));
2157         strncpy(envname,r,copylen);
2158         envname[copylen] = '\0';
2159
2160         if ((envval = getenv(envname)) == NULL) {
2161                 DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname));
2162                 return 2;
2163         }
2164
2165         /*
2166          * Copy the full %$(NAME) into envname so it
2167          * can be replaced.
2168          */
2169
2170         copylen = MIN((q+1-p),(sizeof(envname)-1));
2171         strncpy(envname,p,copylen);
2172         envname[copylen] = '\0';
2173         string_sub(p,envname,envval,len);
2174         return 0; /* Allow the environment contents to be parsed. */
2175 }
2176
2177 /*******************************************************************
2178  Substitute strings with useful parameters.
2179  Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
2180  Paul Rippin <pr3245@nopc.eurostat.cec.be>.
2181 ********************************************************************/
2182
2183 void standard_sub_basic(char *str)
2184 {
2185         char *s, *p;
2186         char pidstr[10];
2187         struct passwd *pass;
2188         char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user;
2189
2190         for (s = str ; s && *s && (p = strchr(s,'%')); s = p )
2191         {
2192                 int l = sizeof(pstring) - (int)(p-str);
2193
2194                 if (l < 0) {
2195                         DEBUG(0,("ERROR: string overflow by %d in standard_sub_basic(%.50s)\n", 
2196                                  -l, str));
2197                         
2198                         return;
2199                 }
2200
2201                 switch (*(p+1))
2202                 {
2203                         case 'G' :
2204                         {
2205                                 if ((pass = Get_Pwnam(username,False))!=NULL) {
2206                                         string_sub(p,"%G",gidtoname(pass->pw_gid),l);
2207                                 } else {
2208                                         p += 2;
2209                                 }
2210                                 break;
2211                         }
2212                         case 'N' : string_sub(p,"%N", automount_server(username),l); break;
2213                         case 'I' : string_sub(p,"%I", client_addr(Client),l); break;
2214                         case 'L' : string_sub(p,"%L", local_machine,l); break;
2215                         case 'M' : string_sub(p,"%M", client_name(Client),l); break;
2216                         case 'R' : string_sub(p,"%R", remote_proto,l); break;
2217                         case 'T' : string_sub(p,"%T", timestring(False),l); break;
2218                         case 'U' : string_sub(p,"%U", username,l); break;
2219                         case 'a' : string_sub(p,"%a", remote_arch,l); break;
2220                         case 'd' :
2221                         {
2222                                 slprintf(pidstr,sizeof(pidstr) - 1, "%d",(int)getpid());
2223                                 string_sub(p,"%d", pidstr,l);
2224                                 break;
2225                         }
2226                         case 'h' : string_sub(p,"%h", myhostname(),l); break;
2227                         case 'm' : string_sub(p,"%m", remote_machine,l); break;
2228                         case 'v' : string_sub(p,"%v", VERSION,l); break;
2229                         case '$' : p += expand_env_var(p,l); break; /* Expand environment variables */
2230                         case '\0': p++; break; /* don't run off end if last character is % */
2231                         default  : p+=2; break;
2232                 }
2233         }
2234         return;
2235 }
2236
2237
2238 /****************************************************************************
2239  Do some standard substitutions in a string.
2240 ****************************************************************************/
2241
2242 void standard_sub(connection_struct *conn,char *str)
2243 {
2244         char *p, *s, *home;
2245
2246         for (s=str; (p=strchr(s, '%'));s=p) {
2247                 int l = sizeof(pstring) - (int)(p-str);
2248
2249                 switch (*(p+1)) {
2250                 case 'H': 
2251                         if ((home = get_user_home_dir(conn->user))) {
2252                                 string_sub(p,"%H",home,l);
2253                         } else {
2254                                 p += 2;
2255                         }
2256                         break;
2257                         
2258                 case 'P': 
2259                         string_sub(p,"%P",conn->connectpath,l); 
2260                         break;
2261                         
2262                 case 'S': 
2263                         string_sub(p,"%S",
2264                                    lp_servicename(SNUM(conn)),l); 
2265                         break;
2266                         
2267                 case 'g': 
2268                         string_sub(p,"%g",
2269                                    gidtoname(conn->gid),l); 
2270                         break;
2271                 case 'u': 
2272                         string_sub(p,"%u",conn->user,l); 
2273                         break;
2274                         
2275                         /* Patch from jkf@soton.ac.uk Left the %N (NIS
2276                          * server name) in standard_sub_basic as it is
2277                          * a feature for logon servers, hence uses the
2278                          * username.  The %p (NIS server path) code is
2279                          * here as it is used instead of the default
2280                          * "path =" string in [homes] and so needs the
2281                          * service name, not the username.  */
2282                 case 'p': 
2283                         string_sub(p,"%p",
2284                                    automount_path(lp_servicename(SNUM(conn))),l); 
2285                         break;
2286                 case '\0': 
2287                         p++; 
2288                         break; /* don't run off the end of the string 
2289                                 */
2290                         
2291                 default: p+=2; 
2292                         break;
2293                 }
2294         }
2295         
2296         standard_sub_basic(str);
2297 }
2298
2299
2300
2301 /*******************************************************************
2302 are two IPs on the same subnet?
2303 ********************************************************************/
2304 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
2305 {
2306   uint32 net1,net2,nmask;
2307
2308   nmask = ntohl(mask.s_addr);
2309   net1  = ntohl(ip1.s_addr);
2310   net2  = ntohl(ip2.s_addr);
2311             
2312   return((net1 & nmask) == (net2 & nmask));
2313 }
2314
2315
2316 /****************************************************************************
2317 a wrapper for gethostbyname() that tries with all lower and all upper case 
2318 if the initial name fails
2319 ****************************************************************************/
2320 struct hostent *Get_Hostbyname(const char *name)
2321 {
2322   char *name2 = strdup(name);
2323   struct hostent *ret;
2324
2325   if (!name2)
2326     {
2327       DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
2328       exit(0);
2329     }
2330
2331    
2332   /* 
2333    * This next test is redundent and causes some systems (with
2334    * broken isalnum() calls) problems.
2335    * JRA.
2336    */
2337
2338 #if 0
2339   if (!isalnum(*name2))
2340     {
2341       free(name2);
2342       return(NULL);
2343     }
2344 #endif /* 0 */
2345
2346   ret = sys_gethostbyname(name2);
2347   if (ret != NULL)
2348     {
2349       free(name2);
2350       return(ret);
2351     }
2352
2353   /* try with all lowercase */
2354   strlower(name2);
2355   ret = sys_gethostbyname(name2);
2356   if (ret != NULL)
2357     {
2358       free(name2);
2359       return(ret);
2360     }
2361
2362   /* try with all uppercase */
2363   strupper(name2);
2364   ret = sys_gethostbyname(name2);
2365   if (ret != NULL)
2366     {
2367       free(name2);
2368       return(ret);
2369     }
2370   
2371   /* nothing works :-( */
2372   free(name2);
2373   return(NULL);
2374 }
2375
2376
2377 /****************************************************************************
2378 check if a process exists. Does this work on all unixes?
2379 ****************************************************************************/
2380
2381 BOOL process_exists(pid_t pid)
2382 {
2383         return(kill(pid,0) == 0 || errno != ESRCH);
2384 }
2385
2386
2387 /*******************************************************************
2388 turn a uid into a user name
2389 ********************************************************************/
2390 char *uidtoname(uid_t uid)
2391 {
2392   static char name[40];
2393   struct passwd *pass = sys_getpwuid(uid);
2394   if (pass) return(pass->pw_name);
2395   slprintf(name, sizeof(name) - 1, "%d",(int)uid);
2396   return(name);
2397 }
2398
2399
2400 /*******************************************************************
2401 turn a gid into a group name
2402 ********************************************************************/
2403
2404 char *gidtoname(gid_t gid)
2405 {
2406         static char name[40];
2407         struct group *grp = getgrgid(gid);
2408         if (grp) return(grp->gr_name);
2409         slprintf(name,sizeof(name) - 1, "%d",(int)gid);
2410         return(name);
2411 }
2412
2413 /*******************************************************************
2414 turn a user name into a uid
2415 ********************************************************************/
2416 uid_t nametouid(const char *name)
2417 {
2418         struct passwd *pass;
2419         char *p;
2420         uid_t u;
2421
2422         u = strtol(name, &p, 0);
2423         if (p != name) return u;
2424
2425         pass = sys_getpwnam(name);
2426         if (pass) return(pass->pw_uid);
2427         return (uid_t)-1;
2428 }
2429
2430 /*******************************************************************
2431 turn a group name into a gid
2432 ********************************************************************/
2433 gid_t nametogid(const char *name)
2434 {
2435         struct group *grp;
2436         char *p;
2437         gid_t g;
2438
2439         g = strtol(name, &p, 0);
2440         if (p != name) return g;
2441
2442         grp = getgrnam(name);
2443         if (grp) return(grp->gr_gid);
2444         return (gid_t)-1;
2445 }
2446
2447 /*******************************************************************
2448 something really nasty happened - panic!
2449 ********************************************************************/
2450 void smb_panic(char *why)
2451 {
2452         char *cmd = lp_panic_action();
2453         if (cmd && *cmd) {
2454                 system(cmd);
2455         }
2456         DEBUG(0,("PANIC: %s\n", why));
2457         dbgflush();
2458         abort();
2459 }
2460
2461
2462 /*******************************************************************
2463 a readdir wrapper which just returns the file name
2464 ********************************************************************/
2465 char *readdirname(DIR *p)
2466 {
2467         SMB_STRUCT_DIRENT *ptr;
2468         char *dname;
2469
2470         if (!p) return(NULL);
2471   
2472         ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
2473         if (!ptr) return(NULL);
2474
2475         dname = ptr->d_name;
2476
2477 #ifdef NEXT2
2478         if (telldir(p) < 0) return(NULL);
2479 #endif
2480
2481 #ifdef HAVE_BROKEN_READDIR
2482         /* using /usr/ucb/cc is BAD */
2483         dname = dname - 2;
2484 #endif
2485
2486         {
2487                 static pstring buf;
2488                 memcpy(buf, dname, NAMLEN(ptr)+1);
2489                 dname = buf;
2490         }
2491
2492         return(dname);
2493 }
2494
2495 /*******************************************************************
2496  Utility function used to decide if the last component 
2497  of a path matches a (possibly wildcarded) entry in a namelist.
2498 ********************************************************************/
2499
2500 BOOL is_in_path(char *name, name_compare_entry *namelist)
2501 {
2502   pstring last_component;
2503   char *p;
2504
2505   DEBUG(8, ("is_in_path: %s\n", name));
2506
2507   /* if we have no list it's obviously not in the path */
2508   if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) 
2509   {
2510     DEBUG(8,("is_in_path: no name list.\n"));
2511     return False;
2512   }
2513
2514   /* Get the last component of the unix name. */
2515   p = strrchr(name, '/');
2516   strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
2517   last_component[sizeof(last_component)-1] = '\0'; 
2518
2519   for(; namelist->name != NULL; namelist++)
2520   {
2521     if(namelist->is_wild)
2522     {
2523       /* 
2524        * Look for a wildcard match. Use the old
2525        * 'unix style' mask match, rather than the
2526        * new NT one.
2527        */
2528       if (unix_mask_match(last_component, namelist->name, case_sensitive, False))
2529       {
2530          DEBUG(8,("is_in_path: mask match succeeded\n"));
2531          return True;
2532       }
2533     }
2534     else
2535     {
2536       if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
2537        (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0)))
2538         {
2539          DEBUG(8,("is_in_path: match succeeded\n"));
2540          return True;
2541         }
2542     }
2543   }
2544   DEBUG(8,("is_in_path: match not found\n"));
2545  
2546   return False;
2547 }
2548
2549 /*******************************************************************
2550  Strip a '/' separated list into an array of 
2551  name_compare_enties structures suitable for 
2552  passing to is_in_path(). We do this for
2553  speed so we can pre-parse all the names in the list 
2554  and don't do it for each call to is_in_path().
2555  namelist is modified here and is assumed to be 
2556  a copy owned by the caller.
2557  We also check if the entry contains a wildcard to
2558  remove a potentially expensive call to mask_match
2559  if possible.
2560 ********************************************************************/
2561  
2562 void set_namearray(name_compare_entry **ppname_array, char *namelist)
2563 {
2564   char *name_end;
2565   char *nameptr = namelist;
2566   int num_entries = 0;
2567   int i;
2568
2569   (*ppname_array) = NULL;
2570
2571   if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0'))) 
2572     return;
2573
2574   /* We need to make two passes over the string. The
2575      first to count the number of elements, the second
2576      to split it.
2577    */
2578   while(*nameptr) 
2579     {
2580       if ( *nameptr == '/' ) 
2581         {
2582           /* cope with multiple (useless) /s) */
2583           nameptr++;
2584           continue;
2585         }
2586       /* find the next / */
2587       name_end = strchr(nameptr, '/');
2588
2589       /* oops - the last check for a / didn't find one. */
2590       if (name_end == NULL)
2591         break;
2592
2593       /* next segment please */
2594       nameptr = name_end + 1;
2595       num_entries++;
2596     }
2597
2598   if(num_entries == 0)
2599     return;
2600
2601   if(( (*ppname_array) = (name_compare_entry *)malloc( 
2602            (num_entries + 1) * sizeof(name_compare_entry))) == NULL)
2603         {
2604     DEBUG(0,("set_namearray: malloc fail\n"));
2605     return;
2606         }
2607
2608   /* Now copy out the names */
2609   nameptr = namelist;
2610   i = 0;
2611   while(*nameptr)
2612              {
2613       if ( *nameptr == '/' ) 
2614       {
2615           /* cope with multiple (useless) /s) */
2616           nameptr++;
2617           continue;
2618       }
2619       /* find the next / */
2620       if ((name_end = strchr(nameptr, '/')) != NULL) 
2621       {
2622           *name_end = 0;
2623          }
2624
2625       /* oops - the last check for a / didn't find one. */
2626       if(name_end == NULL) 
2627         break;
2628
2629       (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
2630                                 (strchr( nameptr, '*')!=NULL));
2631       if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
2632       {
2633         DEBUG(0,("set_namearray: malloc fail (1)\n"));
2634         return;
2635       }
2636
2637       /* next segment please */
2638       nameptr = name_end + 1;
2639       i++;
2640     }
2641   
2642   (*ppname_array)[i].name = NULL;
2643
2644   return;
2645 }
2646
2647 /****************************************************************************
2648 routine to free a namearray.
2649 ****************************************************************************/
2650
2651 void free_namearray(name_compare_entry *name_array)
2652 {
2653   if(name_array == 0)
2654     return;
2655
2656   if(name_array->name != NULL)
2657     free(name_array->name);
2658
2659   free((char *)name_array);
2660 }
2661
2662 /****************************************************************************
2663  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
2664 ****************************************************************************/
2665
2666 uint32 map_lock_offset(uint32 high, uint32 low)
2667 {
2668   unsigned int i;
2669   uint32 mask = 0;
2670   uint32 highcopy = high;
2671
2672   /*
2673    * Try and find out how many significant bits there are in high.
2674    */
2675
2676   for(i = 0; highcopy; i++)
2677     highcopy >>= 1;
2678
2679   /*
2680    * We use 31 bits not 32 here as POSIX
2681    * lock offsets may not be negative.
2682    */
2683
2684   mask = (~0) << (31 - i);
2685
2686   if(low & mask)
2687     return 0; /* Fail. */
2688
2689   high <<= (31 - i);
2690
2691   return (high|low);
2692 }
2693
2694 /****************************************************************************
2695 routine to do file locking
2696 ****************************************************************************/
2697
2698 BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
2699 {
2700 #if HAVE_FCNTL_LOCK
2701   SMB_STRUCT_FLOCK lock;
2702   int ret;
2703 #if defined(LARGE_SMB_OFF_T)
2704   /*
2705    * In the 64 bit locking case we store the original
2706    * values in case we have to map to a 32 bit lock on
2707    * a filesystem that doesn't support 64 bit locks.
2708    */
2709   SMB_OFF_T orig_offset = offset;
2710   SMB_OFF_T orig_count = count;
2711 #endif /* LARGE_SMB_OFF_T */
2712
2713   if(lp_ole_locking_compat()) {
2714     SMB_OFF_T mask2= ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4);
2715     SMB_OFF_T mask = (mask2<<2);
2716
2717     /* make sure the count is reasonable, we might kill the lockd otherwise */
2718     count &= ~mask;
2719
2720     /* the offset is often strange - remove 2 of its bits if either of
2721        the top two bits are set. Shift the top ones by two bits. This
2722        still allows OLE2 apps to operate, but should stop lockd from
2723        dieing */
2724     if ((offset & mask) != 0)
2725       offset = (offset & ~mask) | (((offset & mask) >> 2) & mask2);
2726   } else {
2727     SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
2728     SMB_OFF_T mask = (mask2<<1);
2729     SMB_OFF_T neg_mask = ~mask;
2730
2731     /* interpret negative counts as large numbers */
2732     if (count < 0)
2733       count &= ~mask;
2734
2735     /* no negative offsets */
2736     if(offset < 0)
2737       offset &= ~mask;
2738
2739     /* count + offset must be in range */
2740     while ((offset < 0 || (offset + count < 0)) && mask)
2741     {
2742       offset &= ~mask;
2743       mask = ((mask >> 1) & neg_mask);
2744     }
2745   }
2746
2747   DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
2748
2749   lock.l_type = type;
2750   lock.l_whence = SEEK_SET;
2751   lock.l_start = offset;
2752   lock.l_len = count;
2753   lock.l_pid = 0;
2754
2755   errno = 0;
2756
2757   ret = fcntl(fd,op,&lock);
2758   if (errno == EFBIG)
2759   {
2760     if( DEBUGLVL( 0 ))
2761     {
2762       dbgtext("fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count);
2763       dbgtext("a 'file too large' error. This can happen when using 64 bit lock offsets\n");
2764       dbgtext("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n");
2765     }
2766     /* 32 bit NFS file system, retry with smaller offset */
2767     errno = 0;
2768     lock.l_len = count & 0x7fffffff;
2769     ret = fcntl(fd,op,&lock);
2770   }
2771
2772   if (errno != 0)
2773     DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
2774
2775   /* a lock query */
2776   if (op == SMB_F_GETLK)
2777   {
2778     if ((ret != -1) &&
2779         (lock.l_type != F_UNLCK) && 
2780         (lock.l_pid != 0) && 
2781         (lock.l_pid != getpid()))
2782     {
2783       DEBUG(3,("fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
2784       return(True);
2785     }
2786
2787     /* it must be not locked or locked by me */
2788     return(False);
2789   }
2790
2791   /* a lock set or unset */
2792   if (ret == -1)
2793   {
2794     DEBUG(3,("lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
2795           (double)offset,(double)count,op,type,strerror(errno)));
2796
2797     /* perhaps it doesn't support this sort of locking?? */
2798     if (errno == EINVAL)
2799     {
2800
2801 #if defined(LARGE_SMB_OFF_T)
2802       {
2803         /*
2804          * Ok - if we get here then we have a 64 bit lock request
2805          * that has returned EINVAL. Try and map to 31 bits for offset
2806          * and length and try again. This may happen if a filesystem
2807          * doesn't support 64 bit offsets (efs/ufs) although the underlying
2808          * OS does.
2809          */
2810         uint32 off_low = (orig_offset & 0xFFFFFFFF);
2811         uint32 off_high = ((orig_offset >> 32) & 0xFFFFFFFF);
2812
2813         lock.l_len = (orig_count & 0x7FFFFFFF);
2814         lock.l_start = (SMB_OFF_T)map_lock_offset(off_high, off_low);
2815         ret = fcntl(fd,op,&lock);
2816         if (ret == -1)
2817         {
2818           if (errno == EINVAL)
2819           {
2820             DEBUG(3,("locking not supported? returning True\n"));
2821             return(True);
2822           }
2823           return False;
2824         }
2825         DEBUG(3,("64 -> 32 bit modified lock call successful\n"));
2826         return True;
2827       }
2828 #else /* LARGE_SMB_OFF_T */
2829       DEBUG(3,("locking not supported? returning True\n"));
2830       return(True);
2831 #endif /* LARGE_SMB_OFF_T */
2832     }
2833
2834     return(False);
2835   }
2836
2837   /* everything went OK */
2838   DEBUG(8,("Lock call successful\n"));
2839
2840   return(True);
2841 #else
2842   return(False);
2843 #endif
2844 }
2845
2846 /*******************************************************************
2847 is the name specified one of my netbios names
2848 returns true is it is equal, false otherwise
2849 ********************************************************************/
2850 BOOL is_myname(char *s)
2851 {
2852   int n;
2853   BOOL ret = False;
2854
2855   for (n=0; my_netbios_names[n]; n++) {
2856     if (strequal(my_netbios_names[n], s))
2857       ret=True;
2858   }
2859   DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
2860   return(ret);
2861 }
2862
2863 /*******************************************************************
2864 set the horrid remote_arch string based on an enum.
2865 ********************************************************************/
2866 void set_remote_arch(enum remote_arch_types type)
2867 {
2868   ra_type = type;
2869   switch( type )
2870   {
2871   case RA_WFWG:
2872     fstrcpy(remote_arch, "WfWg");
2873     return;
2874   case RA_OS2:
2875     fstrcpy(remote_arch, "OS2");
2876     return;
2877   case RA_WIN95:
2878     fstrcpy(remote_arch, "Win95");
2879     return;
2880   case RA_WINNT:
2881     fstrcpy(remote_arch, "WinNT");
2882     return;
2883   case RA_WIN2K:
2884     fstrcpy(remote_arch, "Win2K");
2885     return;
2886   case RA_SAMBA:
2887     fstrcpy(remote_arch,"Samba");
2888     return;
2889   default:
2890     ra_type = RA_UNKNOWN;
2891     fstrcpy(remote_arch, "UNKNOWN");
2892     break;
2893   }
2894 }
2895
2896 /*******************************************************************
2897  Get the remote_arch type.
2898 ********************************************************************/
2899 enum remote_arch_types get_remote_arch(void)
2900 {
2901   return ra_type;
2902 }
2903
2904
2905 /*******************************************************************
2906 align a pointer to a multiple of 2 bytes
2907 ********************************************************************/
2908 char *align2(char *q, char *base)
2909 {
2910         if ((q - base) & 1)
2911         {
2912                 q++;
2913         }
2914         return q;
2915 }
2916
2917 void out_ascii(FILE *f, unsigned char *buf,int len)
2918 {
2919         int i;
2920         for (i=0;i<len;i++)
2921         {
2922                 fprintf(f, "%c", isprint(buf[i])?buf[i]:'.');
2923         }
2924 }
2925
2926 void out_data(FILE *f,char *buf1,int len, int per_line)
2927 {
2928         unsigned char *buf = (unsigned char *)buf1;
2929         int i=0;
2930         if (len<=0)
2931         {
2932                 return;
2933         }
2934
2935         fprintf(f, "[%03X] ",i);
2936         for (i=0;i<len;)
2937         {
2938                 fprintf(f, "%02X ",(int)buf[i]);
2939                 i++;
2940                 if (i%(per_line/2) == 0) fprintf(f, " ");
2941                 if (i%per_line == 0)
2942                 {      
2943                         out_ascii(f,&buf[i-per_line  ],per_line/2); fprintf(f, " ");
2944                         out_ascii(f,&buf[i-per_line/2],per_line/2); fprintf(f, "\n");
2945                         if (i<len) fprintf(f, "[%03X] ",i);
2946                 }
2947         }
2948         if ((i%per_line) != 0)
2949         {
2950                 int n;
2951
2952                 n = per_line - (i%per_line);
2953                 fprintf(f, " ");
2954                 if (n>(per_line/2)) fprintf(f, " ");
2955                 while (n--)
2956                 {
2957                         fprintf(f, "   ");
2958                 }
2959                 n = MIN(per_line/2,i%per_line);
2960                 out_ascii(f,&buf[i-(i%per_line)],n); fprintf(f, " ");
2961                 n = (i%per_line) - n;
2962                 if (n>0) out_ascii(f,&buf[i-n],n); 
2963                 fprintf(f, "\n");    
2964         }
2965 }
2966
2967 void print_asc(int level, unsigned char *buf,int len)
2968 {
2969         int i;
2970         for (i=0;i<len;i++)
2971                 DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
2972 }
2973
2974 void dump_data(int level,char *buf1,int len)
2975 {
2976   unsigned char *buf = (unsigned char *)buf1;
2977   int i=0;
2978   if (len<=0) return;
2979
2980   DEBUG(level,("[%03X] ",i));
2981   for (i=0;i<len;) {
2982     DEBUG(level,("%02X ",(int)buf[i]));
2983     i++;
2984     if (i%8 == 0) DEBUG(level,(" "));
2985     if (i%16 == 0) {      
2986       print_asc(level,&buf[i-16],8); DEBUG(level,(" "));
2987       print_asc(level,&buf[i-8],8); DEBUG(level,("\n"));
2988       if (i<len) DEBUG(level,("[%03X] ",i));
2989     }
2990   }
2991   if (i%16) {
2992     int n;
2993
2994     n = 16 - (i%16);
2995     DEBUG(level,(" "));
2996     if (n>8) DEBUG(level,(" "));
2997     while (n--) DEBUG(level,("   "));
2998
2999     n = MIN(8,i%16);
3000     print_asc(level,&buf[i-(i%16)],n); DEBUG(level,(" "));
3001     n = (i%16) - n;
3002     if (n>0) print_asc(level,&buf[i-n],n); 
3003     DEBUG(level,("\n"));    
3004   }
3005 }
3006
3007 char *tab_depth(int depth)
3008 {
3009         static pstring spaces;
3010         memset(spaces, ' ', depth * 4);
3011         spaces[depth * 4] = 0;
3012         return spaces;
3013 }
3014
3015 /*****************************************************************************
3016  * Provide a checksum on a string
3017  *
3018  *  Input:  s - the null-terminated character string for which the checksum
3019  *              will be calculated.
3020  *
3021  *  Output: The checksum value calculated for s.
3022  *
3023  * ****************************************************************************
3024  */
3025 int str_checksum(const char *s)
3026 {
3027         int res = 0;
3028         int c;
3029         int i=0;
3030         
3031         while(*s) {
3032                 c = *s;
3033                 res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
3034                 s++;
3035                 i++;
3036         }
3037         return(res);
3038 } /* str_checksum */
3039
3040
3041
3042 /*****************************************************************
3043 zero a memory area then free it. Used to catch bugs faster
3044 *****************************************************************/  
3045 void zero_free(void *p, size_t size)
3046 {
3047         memset(p, 0, size);
3048         free(p);
3049 }
3050
3051
3052 /*****************************************************************
3053 set our open file limit to a requested max and return the limit
3054 *****************************************************************/  
3055 int set_maxfiles(int requested_max)
3056 {
3057 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
3058         struct rlimit rlp;
3059         int saved_current_limit;
3060
3061         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
3062                 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
3063                         strerror(errno) ));
3064                 /* just guess... */
3065                 return requested_max;
3066         }
3067
3068         /* 
3069      * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
3070          * account for the extra fd we need 
3071          * as well as the log files and standard
3072          * handles etc. Save the limit we want to set in case
3073          * we are running on an OS that doesn't support this limit (AIX)
3074          * which always returns RLIM_INFINITY for rlp.rlim_max.
3075          */
3076
3077         saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
3078
3079         if(setrlimit(RLIMIT_NOFILE, &rlp)) {
3080                 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n", 
3081                         (int)rlp.rlim_cur, strerror(errno) ));
3082                 /* just guess... */
3083                 return saved_current_limit;
3084         }
3085
3086         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
3087                 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
3088                         strerror(errno) ));
3089                 /* just guess... */
3090                 return saved_current_limit;
3091     }
3092
3093 #if defined(RLIM_INFINITY)
3094         if(rlp.rlim_cur == RLIM_INFINITY)
3095                 return saved_current_limit;
3096 #endif
3097
3098     if((int)rlp.rlim_cur > saved_current_limit)
3099                 return saved_current_limit;
3100
3101         return rlp.rlim_cur;
3102 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
3103         /*
3104          * No way to know - just guess...
3105          */
3106         return requested_max;
3107 #endif
3108 }
3109
3110
3111 /*****************************************************************
3112  splits out the last subkey of a key
3113  *****************************************************************/  
3114 void reg_get_subkey(char *full_keyname, char *key_name, char *subkey_name)
3115 {
3116         split_at_last_component(full_keyname, key_name, '\\', subkey_name);
3117 }
3118
3119 /*****************************************************************
3120  splits out the start of the key (HKLM or HKU) and the rest of the key
3121  *****************************************************************/  
3122 BOOL reg_split_key(char *full_keyname, uint32 *reg_type, char *key_name)
3123 {
3124         pstring tmp;
3125
3126         if (!next_token(&full_keyname, tmp, "\\", sizeof(tmp)))
3127         {
3128                 return False;
3129         }
3130
3131         (*reg_type) = 0;
3132
3133         DEBUG(10, ("reg_split_key: hive %s\n", tmp));
3134
3135         if (strequal(tmp, "HKLM") || strequal(tmp, "HKEY_LOCAL_MACHINE"))
3136         {
3137                 (*reg_type) = HKEY_LOCAL_MACHINE;
3138         }
3139         else if (strequal(tmp, "HKU") || strequal(tmp, "HKEY_USERS"))
3140         {
3141                 (*reg_type) = HKEY_USERS;
3142         }
3143         else
3144         {
3145                 DEBUG(10,("reg_split_key: unrecognised hive key %s\n", tmp));
3146                 return False;
3147         }
3148         
3149         if (next_token(NULL, tmp, "\n\r", sizeof(tmp)))
3150         {
3151                 fstrcpy(key_name, tmp);
3152         }
3153         else
3154         {
3155                 key_name[0] = 0;
3156         }
3157
3158         DEBUG(10, ("reg_split_key: name %s\n", key_name));
3159
3160         return True;
3161 }
3162
3163
3164 /*****************************************************************
3165 like mktemp() but make sure that no % characters are used
3166 % characters are bad for us because of the macro subs
3167  *****************************************************************/  
3168 char *smbd_mktemp(char *template)
3169 {
3170         char *p = mktemp(template);
3171         char *p2;
3172         SMB_STRUCT_STAT st;
3173
3174         if (!p) return NULL;
3175
3176         while ((p2=strchr(p,'%'))) {
3177                 p2[0] = 'A';
3178                 while (sys_stat(p,&st) == 0 && p2[0] < 'Z') {
3179                         /* damn, it exists */
3180                         p2[0]++;
3181                 }
3182                 if (p2[0] == 'Z') {
3183                         /* oh well ... better return something */
3184                         p2[0] = '%';
3185                         return p;
3186                 }
3187         }
3188
3189         return p;
3190 }
3191
3192
3193 /*****************************************************************
3194 like strdup but for memory
3195  *****************************************************************/  
3196 void *memdup(void *p, size_t size)
3197 {
3198         void *p2;
3199         p2 = malloc(size);
3200         if (!p2) return NULL;
3201         memcpy(p2, p, size);
3202         return p2;
3203 }
3204
3205 /*****************************************************************
3206 get local hostname and cache result
3207  *****************************************************************/  
3208 char *myhostname(void)
3209 {
3210         static pstring ret;
3211         if (ret[0] == 0) {
3212                 get_myname(ret);
3213         }
3214         return ret;
3215 }