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