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