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