use *SMBSERVER convention in smbwrapper to allow us to connect to
[bbaumbach/samba-autobuild/.git] / source / 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 BOOL passive = False;
44
45 int Protocol = PROTOCOL_COREPLUS;
46
47 /* a default finfo structure to ensure all fields are sensible */
48 file_info def_finfo = {-1,0,0,0,0,0,0,""};
49
50 /* the client file descriptor */
51 int Client = -1;
52
53 /* the last IP received from */
54 struct in_addr lastip;
55
56 /* the last port received from */
57 int lastport=0;
58
59 /* this is used by the chaining code */
60 int chain_size = 0;
61
62 int trans_num = 0;
63
64 /*
65    case handling on filenames 
66 */
67 int case_default = CASE_LOWER;
68
69 /* the following control case operations - they are put here so the
70    client can link easily */
71 BOOL case_sensitive;
72 BOOL case_preserve;
73 BOOL use_mangled_map = False;
74 BOOL short_case_preserve;
75 BOOL case_mangle;
76
77 fstring remote_machine="";
78 fstring local_machine="";
79 fstring remote_arch="UNKNOWN";
80 static enum remote_arch_types ra_type = RA_UNKNOWN;
81 fstring remote_proto="UNKNOWN";
82 pstring myhostname="";
83 pstring user_socket_options="";   
84
85 pstring sesssetup_user="";
86 pstring samlogon_user="";
87
88 BOOL sam_logon_in_ssb = False;
89
90 pstring global_myname = "";
91 fstring global_myworkgroup = "";
92 char **my_netbios_names;
93
94 int smb_read_error = 0;
95
96 static char *filename_dos(char *path,char *buf);
97
98
99
100 /****************************************************************************
101   find a suitable temporary directory. The result should be copied immediately
102   as it may be overwritten by a subsequent call
103   ****************************************************************************/
104 char *tmpdir(void)
105 {
106   char *p;
107   if ((p = getenv("TMPDIR"))) {
108     return p;
109   }
110   return "/tmp";
111 }
112
113
114
115 /****************************************************************************
116 determine if a file descriptor is in fact a socket
117 ****************************************************************************/
118 BOOL is_a_socket(int fd)
119 {
120   int v,l;
121   l = sizeof(int);
122   return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
123 }
124
125
126 static char *last_ptr=NULL;
127
128 /****************************************************************************
129   Get the next token from a string, return False if none found
130   handles double-quotes. 
131 Based on a routine by GJC@VILLAGE.COM. 
132 Extensively modified by Andrew.Tridgell@anu.edu.au
133 ****************************************************************************/
134 BOOL next_token(char **ptr,char *buff,char *sep, int bufsize)
135 {
136   char *s;
137   BOOL quoted;
138   int len=1;
139
140   if (!ptr) ptr = &last_ptr;
141   if (!ptr) return(False);
142
143   s = *ptr;
144
145   /* default to simple separators */
146   if (!sep) sep = " \t\n\r";
147
148   /* find the first non sep char */
149   while(*s && strchr(sep,*s)) s++;
150
151   /* nothing left? */
152   if (! *s) return(False);
153
154   /* copy over the token */
155   for (quoted = False; len < bufsize && *s && (quoted || !strchr(sep,*s)); s++)
156     {
157             if (*s == '\"') {
158                     quoted = !quoted;
159             } else {
160                     len++;
161                     *buff++ = *s;
162             }
163     }
164
165   *ptr = (*s) ? s+1 : s;  
166   *buff = 0;
167   last_ptr = *ptr;
168
169   return(True);
170 }
171
172 /****************************************************************************
173 Convert list of tokens to array; dependent on above routine.
174 Uses last_ptr from above - bit of a hack.
175 ****************************************************************************/
176 char **toktocliplist(int *ctok, char *sep)
177 {
178   char *s=last_ptr;
179   int ictok=0;
180   char **ret, **iret;
181
182   if (!sep) sep = " \t\n\r";
183
184   while(*s && strchr(sep,*s)) s++;
185
186   /* nothing left? */
187   if (!*s) return(NULL);
188
189   do {
190     ictok++;
191     while(*s && (!strchr(sep,*s))) s++;
192     while(*s && strchr(sep,*s)) *s++=0;
193   } while(*s);
194
195   *ctok=ictok;
196   s=last_ptr;
197
198   if (!(ret=iret=malloc(ictok*sizeof(char *)))) return NULL;
199   
200   while(ictok--) {    
201     *iret++=s;
202     while(*s++);
203     while(!*s) s++;
204   }
205
206   return ret;
207 }
208
209 /****************************************************************************
210 prompte a dptr (to make it recently used)
211 ****************************************************************************/
212 static void array_promote(char *array,int elsize,int element)
213 {
214   char *p;
215   if (element == 0)
216     return;
217
218   p = (char *)malloc(elsize);
219
220   if (!p)
221     {
222       DEBUG(5,("Ahh! Can't malloc\n"));
223       return;
224     }
225   memcpy(p,array + element * elsize, elsize);
226   memmove(array + elsize,array,elsize*element);
227   memcpy(array,p,elsize);
228   free(p);
229 }
230
231 enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
232
233 struct
234 {
235   char *name;
236   int level;
237   int option;
238   int value;
239   int opttype;
240 } socket_options[] = {
241   {"SO_KEEPALIVE",      SOL_SOCKET,    SO_KEEPALIVE,    0,                 OPT_BOOL},
242   {"SO_REUSEADDR",      SOL_SOCKET,    SO_REUSEADDR,    0,                 OPT_BOOL},
243   {"SO_BROADCAST",      SOL_SOCKET,    SO_BROADCAST,    0,                 OPT_BOOL},
244 #ifdef TCP_NODELAY
245   {"TCP_NODELAY",       IPPROTO_TCP,   TCP_NODELAY,     0,                 OPT_BOOL},
246 #endif
247 #ifdef IPTOS_LOWDELAY
248   {"IPTOS_LOWDELAY",    IPPROTO_IP,    IP_TOS,          IPTOS_LOWDELAY,    OPT_ON},
249 #endif
250 #ifdef IPTOS_THROUGHPUT
251   {"IPTOS_THROUGHPUT",  IPPROTO_IP,    IP_TOS,          IPTOS_THROUGHPUT,  OPT_ON},
252 #endif
253 #ifdef SO_SNDBUF
254   {"SO_SNDBUF",         SOL_SOCKET,    SO_SNDBUF,       0,                 OPT_INT},
255 #endif
256 #ifdef SO_RCVBUF
257   {"SO_RCVBUF",         SOL_SOCKET,    SO_RCVBUF,       0,                 OPT_INT},
258 #endif
259 #ifdef SO_SNDLOWAT
260   {"SO_SNDLOWAT",       SOL_SOCKET,    SO_SNDLOWAT,     0,                 OPT_INT},
261 #endif
262 #ifdef SO_RCVLOWAT
263   {"SO_RCVLOWAT",       SOL_SOCKET,    SO_RCVLOWAT,     0,                 OPT_INT},
264 #endif
265 #ifdef SO_SNDTIMEO
266   {"SO_SNDTIMEO",       SOL_SOCKET,    SO_SNDTIMEO,     0,                 OPT_INT},
267 #endif
268 #ifdef SO_RCVTIMEO
269   {"SO_RCVTIMEO",       SOL_SOCKET,    SO_RCVTIMEO,     0,                 OPT_INT},
270 #endif
271   {NULL,0,0,0,0}};
272
273         
274
275 /****************************************************************************
276 set user socket options
277 ****************************************************************************/
278 void set_socket_options(int fd, char *options)
279 {
280   fstring tok;
281
282   while (next_token(&options,tok," \t,", sizeof(tok)))
283     {
284       int ret=0,i;
285       int value = 1;
286       char *p;
287       BOOL got_value = False;
288
289       if ((p = strchr(tok,'=')))
290         {
291           *p = 0;
292           value = atoi(p+1);
293           got_value = True;
294         }
295
296       for (i=0;socket_options[i].name;i++)
297         if (strequal(socket_options[i].name,tok))
298           break;
299
300       if (!socket_options[i].name)
301         {
302           DEBUG(0,("Unknown socket option %s\n",tok));
303           continue;
304         }
305
306       switch (socket_options[i].opttype)
307         {
308         case OPT_BOOL:
309         case OPT_INT:
310           ret = setsockopt(fd,socket_options[i].level,
311                            socket_options[i].option,(char *)&value,sizeof(int));
312           break;
313
314         case OPT_ON:
315           if (got_value)
316             DEBUG(0,("syntax error - %s does not take a value\n",tok));
317
318           {
319             int on = socket_options[i].value;
320             ret = setsockopt(fd,socket_options[i].level,
321                              socket_options[i].option,(char *)&on,sizeof(int));
322           }
323           break;          
324         }
325       
326       if (ret != 0)
327         DEBUG(0,("Failed to set socket option %s\n",tok));
328     }
329 }
330
331
332
333 /****************************************************************************
334   close the socket communication
335 ****************************************************************************/
336 void close_sockets(void )
337 {
338 #ifdef WITH_SSL
339   sslutil_disconnect(Client);
340 #endif /* WITH_SSL */
341
342   close(Client);
343   Client = 0;
344 }
345
346 /****************************************************************************
347 determine whether we are in the specified group
348 ****************************************************************************/
349
350 BOOL in_group(gid_t group, gid_t current_gid, int ngroups, gid_t *groups)
351 {
352         int i;
353
354         if (group == current_gid) return(True);
355
356         for (i=0;i<ngroups;i++)
357                 if (group == groups[i])
358                         return(True);
359
360         return(False);
361 }
362
363 /****************************************************************************
364 this is a safer strcpy(), meant to prevent core dumps when nasty things happen
365 ****************************************************************************/
366 char *StrCpy(char *dest,char *src)
367 {
368   char *d = dest;
369
370   /* I don't want to get lazy with these ... */
371   SMB_ASSERT(dest && src);
372
373   if (!dest) return(NULL);
374   if (!src) {
375     *dest = 0;
376     return(dest);
377   }
378   while ((*d++ = *src++)) ;
379   return(dest);
380 }
381
382 /****************************************************************************
383 line strncpy but always null terminates. Make sure there is room!
384 ****************************************************************************/
385 char *StrnCpy(char *dest,char *src,int n)
386 {
387   char *d = dest;
388   if (!dest) return(NULL);
389   if (!src) {
390     *dest = 0;
391     return(dest);
392   }
393   while (n-- && (*d++ = *src++)) ;
394   *d = 0;
395   return(dest);
396 }
397
398
399 /*******************************************************************
400 copy an IP address from one buffer to another
401 ********************************************************************/
402 void putip(void *dest,void *src)
403 {
404   memcpy(dest,src,4);
405 }
406
407
408 #define TRUNCATE_NETBIOS_NAME 1
409
410 /*******************************************************************
411  convert, possibly using a stupid microsoft-ism which has destroyed
412  the transport independence of netbios (for CIFS vendors that usually
413  use the Win95-type methods, not for NT to NT communication, which uses
414  DCE/RPC and therefore full-length unicode strings...) a dns name into
415  a netbios name.
416
417  the netbios name (NOT necessarily null-terminated) is truncated to 15
418  characters.
419
420  ******************************************************************/
421 char *dns_to_netbios_name(char *dns_name)
422 {
423         static char netbios_name[16];
424         int i;
425         StrnCpy(netbios_name, dns_name, 15);
426         netbios_name[15] = 0;
427         
428 #ifdef TRUNCATE_NETBIOS_NAME
429         /* ok.  this is because of a stupid microsoft-ism.  if the called host
430            name contains a '.', microsoft clients expect you to truncate the
431            netbios name up to and including the '.'  this even applies, by
432            mistake, to workgroup (domain) names, which is _really_ daft.
433          */
434         for (i = 15; i >= 0; i--)
435         {
436                 if (netbios_name[i] == '.')
437                 {
438                         netbios_name[i] = 0;
439                         break;
440                 }
441         }
442 #endif /* TRUNCATE_NETBIOS_NAME */
443
444         return netbios_name;
445 }
446
447
448 /****************************************************************************
449 interpret the weird netbios "name". Return the name type
450 ****************************************************************************/
451 static int name_interpret(char *in,char *out)
452 {
453   int ret;
454   int len = (*in++) / 2;
455
456   *out=0;
457
458   if (len > 30 || len<1) return(0);
459
460   while (len--)
461     {
462       if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
463         *out = 0;
464         return(0);
465       }
466       *out = ((in[0]-'A')<<4) + (in[1]-'A');
467       in += 2;
468       out++;
469     }
470   *out = 0;
471   ret = out[-1];
472
473 #ifdef NETBIOS_SCOPE
474   /* Handle any scope names */
475   while(*in) 
476     {
477       *out++ = '.'; /* Scope names are separated by periods */
478       len = *(unsigned char *)in++;
479       StrnCpy(out, in, len);
480       out += len;
481       *out=0;
482       in += len;
483     }
484 #endif
485   return(ret);
486 }
487
488 /****************************************************************************
489 mangle a name into netbios format
490
491   Note:  <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
492 ****************************************************************************/
493 int name_mangle( char *In, char *Out, char name_type )
494   {
495   int   i;
496   int   c;
497   int   len;
498   char  buf[20];
499   char *p = Out;
500
501   /* Safely copy the input string, In, into buf[]. */
502   (void)memset( buf, 0, 20 );
503   if (strcmp(In,"*") == 0)
504     buf[0] = '*';
505   else
506     (void)slprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, name_type );
507
508   /* Place the length of the first field into the output buffer. */
509   p[0] = 32;
510   p++;
511
512   /* Now convert the name to the rfc1001/1002 format. */
513   for( i = 0; i < 16; i++ )
514     {
515     c = toupper( buf[i] );
516     p[i*2]     = ( (c >> 4) & 0x000F ) + 'A';
517     p[(i*2)+1] = (c & 0x000F) + 'A';
518     }
519   p += 32;
520   p[0] = '\0';
521
522   /* Add the scope string. */
523   for( i = 0, len = 0; NULL != scope; i++, len++ )
524     {
525     switch( scope[i] )
526       {
527       case '\0':
528         p[0]     = len;
529         if( len > 0 )
530           p[len+1] = 0;
531         return( name_len(Out) );
532       case '.':
533         p[0] = len;
534         p   += (len + 1);
535         len  = 0;
536         break;
537       default:
538         p[len+1] = scope[i];
539         break;
540       }
541     }
542
543   return( name_len(Out) );
544   } /* name_mangle */
545
546 /*******************************************************************
547   check if a file exists
548 ********************************************************************/
549 BOOL file_exist(char *fname,SMB_STRUCT_STAT *sbuf)
550 {
551   SMB_STRUCT_STAT st;
552   if (!sbuf) sbuf = &st;
553   
554   if (dos_stat(fname,sbuf) != 0) 
555     return(False);
556
557   return(S_ISREG(sbuf->st_mode));
558 }
559
560 /*******************************************************************
561 check a files mod time
562 ********************************************************************/
563 time_t file_modtime(char *fname)
564 {
565   SMB_STRUCT_STAT st;
566   
567   if (dos_stat(fname,&st) != 0) 
568     return(0);
569
570   return(st.st_mtime);
571 }
572
573 /*******************************************************************
574   check if a directory exists
575 ********************************************************************/
576 BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st)
577 {
578   SMB_STRUCT_STAT st2;
579   BOOL ret;
580
581   if (!st) st = &st2;
582
583   if (dos_stat(dname,st) != 0) 
584     return(False);
585
586   ret = S_ISDIR(st->st_mode);
587   if(!ret)
588     errno = ENOTDIR;
589   return ret;
590 }
591
592 /*******************************************************************
593 returns the size in bytes of the named file
594 ********************************************************************/
595 SMB_OFF_T file_size(char *file_name)
596 {
597   SMB_STRUCT_STAT buf;
598   buf.st_size = 0;
599   dos_stat(file_name,&buf);
600   return(buf.st_size);
601 }
602
603 /*******************************************************************
604 return a string representing an attribute for a file
605 ********************************************************************/
606 char *attrib_string(int mode)
607 {
608   static fstring attrstr;
609
610   attrstr[0] = 0;
611
612   if (mode & aVOLID) fstrcat(attrstr,"V");
613   if (mode & aDIR) fstrcat(attrstr,"D");
614   if (mode & aARCH) fstrcat(attrstr,"A");
615   if (mode & aHIDDEN) fstrcat(attrstr,"H");
616   if (mode & aSYSTEM) fstrcat(attrstr,"S");
617   if (mode & aRONLY) fstrcat(attrstr,"R");        
618
619   return(attrstr);
620 }
621
622
623 /*******************************************************************
624   case insensitive string compararison
625 ********************************************************************/
626 int StrCaseCmp(char *s, char *t)
627 {
628   /* compare until we run out of string, either t or s, or find a difference */
629   /* We *must* use toupper rather than tolower here due to the
630      asynchronous upper to lower mapping.
631    */
632 #if !defined(KANJI_WIN95_COMPATIBILITY)
633   /*
634    * For completeness we should put in equivalent code for code pages
635    * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
636    * doubt anyone wants Samba to behave differently from Win95 and WinNT
637    * here. They both treat full width ascii characters as case senstive
638    * filenames (ie. they don't do the work we do here).
639    * JRA.
640    */
641
642   if(lp_client_code_page() == KANJI_CODEPAGE)
643   {
644     /* Win95 treats full width ascii characters as case sensitive. */
645     int diff;
646     for (;;)
647     {
648       if (!*s || !*t)
649             return toupper (*s) - toupper (*t);
650       else if (is_sj_alph (*s) && is_sj_alph (*t))
651       {
652         diff = sj_toupper2 (*(s+1)) - sj_toupper2 (*(t+1));
653         if (diff)
654           return diff;
655         s += 2;
656         t += 2;
657       }
658       else if (is_shift_jis (*s) && is_shift_jis (*t))
659       {
660         diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t);
661         if (diff)
662           return diff;
663         diff = ((int) (unsigned char) *(s+1)) - ((int) (unsigned char) *(t+1));
664         if (diff)
665           return diff;
666         s += 2;
667         t += 2;
668       }
669       else if (is_shift_jis (*s))
670         return 1;
671       else if (is_shift_jis (*t))
672         return -1;
673       else 
674       {
675         diff = toupper (*s) - toupper (*t);
676         if (diff)
677           return diff;
678         s++;
679         t++;
680       }
681     }
682   }
683   else
684 #endif /* KANJI_WIN95_COMPATIBILITY */
685   {
686     while (*s && *t && toupper(*s) == toupper(*t))
687     {
688       s++;
689       t++;
690     }
691
692     return(toupper(*s) - toupper(*t));
693   }
694 }
695
696 /*******************************************************************
697   case insensitive string compararison, length limited
698 ********************************************************************/
699 int StrnCaseCmp(char *s, char *t, int n)
700 {
701   /* compare until we run out of string, either t or s, or chars */
702   /* We *must* use toupper rather than tolower here due to the
703      asynchronous upper to lower mapping.
704    */
705 #if !defined(KANJI_WIN95_COMPATIBILITY)
706   /*
707    * For completeness we should put in equivalent code for code pages
708    * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
709    * doubt anyone wants Samba to behave differently from Win95 and WinNT
710    * here. They both treat full width ascii characters as case senstive
711    * filenames (ie. they don't do the work we do here).
712    * JRA. 
713    */
714
715   if(lp_client_code_page() == KANJI_CODEPAGE)
716   {
717     /* Win95 treats full width ascii characters as case sensitive. */
718     int diff;
719     for (;n > 0;)
720     {
721       if (!*s || !*t)
722         return toupper (*s) - toupper (*t);
723       else if (is_sj_alph (*s) && is_sj_alph (*t))
724       {
725         diff = sj_toupper2 (*(s+1)) - sj_toupper2 (*(t+1));
726         if (diff)
727           return diff;
728         s += 2;
729         t += 2;
730         n -= 2;
731       }
732       else if (is_shift_jis (*s) && is_shift_jis (*t))
733       {
734         diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t);
735         if (diff)
736           return diff;
737         diff = ((int) (unsigned char) *(s+1)) - ((int) (unsigned char) *(t+1));
738         if (diff)
739           return diff;
740         s += 2;
741         t += 2;
742         n -= 2;
743       }
744       else if (is_shift_jis (*s))
745         return 1;
746       else if (is_shift_jis (*t))
747         return -1;
748       else 
749       {
750         diff = toupper (*s) - toupper (*t);
751         if (diff)
752           return diff;
753         s++;
754         t++;
755         n--;
756       }
757     }
758     return 0;
759   }
760   else
761 #endif /* KANJI_WIN95_COMPATIBILITY */
762   {
763     while (n && *s && *t && toupper(*s) == toupper(*t))
764     {
765       s++;
766       t++;
767       n--;
768     }
769
770     /* not run out of chars - strings are different lengths */
771     if (n) 
772       return(toupper(*s) - toupper(*t));
773
774     /* identical up to where we run out of chars, 
775        and strings are same length */
776     return(0);
777   }
778 }
779
780 /*******************************************************************
781   compare 2 strings 
782 ********************************************************************/
783 BOOL strequal(char *s1, char *s2)
784 {
785   if (s1 == s2) return(True);
786   if (!s1 || !s2) return(False);
787   
788   return(StrCaseCmp(s1,s2)==0);
789 }
790
791 /*******************************************************************
792   compare 2 strings up to and including the nth char.
793   ******************************************************************/
794 BOOL strnequal(char *s1,char *s2,int n)
795 {
796   if (s1 == s2) return(True);
797   if (!s1 || !s2 || !n) return(False);
798   
799   return(StrnCaseCmp(s1,s2,n)==0);
800 }
801
802 /*******************************************************************
803   compare 2 strings (case sensitive)
804 ********************************************************************/
805 BOOL strcsequal(char *s1,char *s2)
806 {
807   if (s1 == s2) return(True);
808   if (!s1 || !s2) return(False);
809   
810   return(strcmp(s1,s2)==0);
811 }
812
813
814 /*******************************************************************
815   convert a string to lower case
816 ********************************************************************/
817 void strlower(char *s)
818 {
819   while (*s)
820   {
821 #if !defined(KANJI_WIN95_COMPATIBILITY)
822   /*
823    * For completeness we should put in equivalent code for code pages
824    * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
825    * doubt anyone wants Samba to behave differently from Win95 and WinNT
826    * here. They both treat full width ascii characters as case senstive
827    * filenames (ie. they don't do the work we do here).
828    * JRA. 
829    */
830
831     if(lp_client_code_page() == KANJI_CODEPAGE)
832     {
833       /* Win95 treats full width ascii characters as case sensitive. */
834       if (is_shift_jis (*s))
835       {
836         if (is_sj_upper (s[0], s[1]))
837           s[1] = sj_tolower2 (s[1]);
838         s += 2;
839       }
840       else if (is_kana (*s))
841       {
842         s++;
843       }
844       else
845       {
846         if (isupper(*s))
847           *s = tolower(*s);
848         s++;
849       }
850     }
851     else
852 #endif /* KANJI_WIN95_COMPATIBILITY */
853     {
854       int skip = skip_multibyte_char( *s );
855       if( skip != 0 )
856         s += skip;
857       else
858       {
859         if (isupper(*s))
860           *s = tolower(*s);
861         s++;
862       }
863     }
864   }
865 }
866
867 /*******************************************************************
868   convert a string to upper case
869 ********************************************************************/
870 void strupper(char *s)
871 {
872   while (*s)
873   {
874 #if !defined(KANJI_WIN95_COMPATIBILITY)
875   /*
876    * For completeness we should put in equivalent code for code pages
877    * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
878    * doubt anyone wants Samba to behave differently from Win95 and WinNT
879    * here. They both treat full width ascii characters as case senstive
880    * filenames (ie. they don't do the work we do here).
881    * JRA. 
882    */
883
884     if(lp_client_code_page() == KANJI_CODEPAGE)
885     {
886       /* Win95 treats full width ascii characters as case sensitive. */
887       if (is_shift_jis (*s))
888       {
889         if (is_sj_lower (s[0], s[1]))
890           s[1] = sj_toupper2 (s[1]);
891         s += 2;
892       }
893       else if (is_kana (*s))
894       {
895         s++;
896       }
897       else
898       {
899         if (islower(*s))
900           *s = toupper(*s);
901         s++;
902       }
903     }
904     else
905 #endif /* KANJI_WIN95_COMPATIBILITY */
906     {
907       int skip = skip_multibyte_char( *s );
908       if( skip != 0 )
909         s += skip;
910       else
911       {
912         if (islower(*s))
913           *s = toupper(*s);
914         s++;
915       }
916     }
917   }
918 }
919
920 /*******************************************************************
921   convert a string to "normal" form
922 ********************************************************************/
923 void strnorm(char *s)
924 {
925   if (case_default == CASE_UPPER)
926     strupper(s);
927   else
928     strlower(s);
929 }
930
931 /*******************************************************************
932 check if a string is in "normal" case
933 ********************************************************************/
934 BOOL strisnormal(char *s)
935 {
936   if (case_default == CASE_UPPER)
937     return(!strhaslower(s));
938
939   return(!strhasupper(s));
940 }
941
942
943 /****************************************************************************
944   string replace
945 ****************************************************************************/
946 void string_replace(char *s,char oldc,char newc)
947 {
948   int skip;
949   while (*s)
950   {
951     skip = skip_multibyte_char( *s );
952     if( skip != 0 )
953       s += skip;
954     else
955     {
956       if (oldc == *s)
957         *s = newc;
958       s++;
959     }
960   }
961 }
962
963 /****************************************************************************
964   make a file into unix format
965 ****************************************************************************/
966 void unix_format(char *fname)
967 {
968   string_replace(fname,'\\','/');
969 }
970
971 /****************************************************************************
972   make a file into dos format
973 ****************************************************************************/
974 void dos_format(char *fname)
975 {
976   string_replace(fname,'/','\\');
977 }
978
979 /*******************************************************************
980   show a smb message structure
981 ********************************************************************/
982 void show_msg(char *buf)
983 {
984         int i;
985         int bcc=0;
986
987         if (DEBUGLEVEL < 5) return;
988
989         DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
990                         smb_len(buf),
991                         (int)CVAL(buf,smb_com),
992                         (int)CVAL(buf,smb_rcls),
993                         (int)CVAL(buf,smb_reh),
994                         (int)SVAL(buf,smb_err),
995                         (int)CVAL(buf,smb_flg),
996                         (int)SVAL(buf,smb_flg2)));
997         DEBUG(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n",
998                         (int)SVAL(buf,smb_tid),
999                         (int)SVAL(buf,smb_pid),
1000                         (int)SVAL(buf,smb_uid),
1001                         (int)SVAL(buf,smb_mid),
1002                         (int)CVAL(buf,smb_wct)));
1003
1004         for (i=0;i<(int)CVAL(buf,smb_wct);i++)
1005         {
1006                 DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i,
1007                         SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
1008         }
1009
1010         bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
1011
1012         DEBUG(5,("smb_bcc=%d\n",bcc));
1013
1014         if (DEBUGLEVEL < 10) return;
1015
1016         if (DEBUGLEVEL < 50)
1017         {
1018                 bcc = MIN(bcc, 512);
1019         }
1020
1021         dump_data(10, smb_buf(buf), bcc);
1022 }
1023 /*******************************************************************
1024   return the length of an smb packet
1025 ********************************************************************/
1026 int smb_len(char *buf)
1027 {
1028   return( PVAL(buf,3) | (PVAL(buf,2)<<8) | ((PVAL(buf,1)&1)<<16) );
1029 }
1030
1031 /*******************************************************************
1032   set the length of an smb packet
1033 ********************************************************************/
1034 void _smb_setlen(char *buf,int len)
1035 {
1036   buf[0] = 0;
1037   buf[1] = (len&0x10000)>>16;
1038   buf[2] = (len&0xFF00)>>8;
1039   buf[3] = len&0xFF;
1040 }
1041
1042 /*******************************************************************
1043   set the length and marker of an smb packet
1044 ********************************************************************/
1045 void smb_setlen(char *buf,int len)
1046 {
1047   _smb_setlen(buf,len);
1048
1049   CVAL(buf,4) = 0xFF;
1050   CVAL(buf,5) = 'S';
1051   CVAL(buf,6) = 'M';
1052   CVAL(buf,7) = 'B';
1053 }
1054
1055 /*******************************************************************
1056   setup the word count and byte count for a smb message
1057 ********************************************************************/
1058 int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
1059 {
1060   if (zero)
1061     bzero(buf + smb_size,num_words*2 + num_bytes);
1062   CVAL(buf,smb_wct) = num_words;
1063   SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);  
1064   smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
1065   return (smb_size + num_words*2 + num_bytes);
1066 }
1067
1068 /*******************************************************************
1069 return the number of smb words
1070 ********************************************************************/
1071 static int smb_numwords(char *buf)
1072 {
1073   return (CVAL(buf,smb_wct));
1074 }
1075
1076 /*******************************************************************
1077 return the size of the smb_buf region of a message
1078 ********************************************************************/
1079 int smb_buflen(char *buf)
1080 {
1081   return(SVAL(buf,smb_vwv0 + smb_numwords(buf)*2));
1082 }
1083
1084 /*******************************************************************
1085   return a pointer to the smb_buf data area
1086 ********************************************************************/
1087 static int smb_buf_ofs(char *buf)
1088 {
1089   return (smb_size + CVAL(buf,smb_wct)*2);
1090 }
1091
1092 /*******************************************************************
1093   return a pointer to the smb_buf data area
1094 ********************************************************************/
1095 char *smb_buf(char *buf)
1096 {
1097   return (buf + smb_buf_ofs(buf));
1098 }
1099
1100 /*******************************************************************
1101 return the SMB offset into an SMB buffer
1102 ********************************************************************/
1103 int smb_offset(char *p,char *buf)
1104 {
1105   return(PTR_DIFF(p,buf+4) + chain_size);
1106 }
1107
1108
1109 /*******************************************************************
1110 skip past some strings in a buffer
1111 ********************************************************************/
1112 char *skip_string(char *buf,int n)
1113 {
1114   while (n--)
1115     buf += strlen(buf) + 1;
1116   return(buf);
1117 }
1118
1119 /*******************************************************************
1120 trim the specified elements off the front and back of a string
1121 ********************************************************************/
1122 BOOL trim_string(char *s,char *front,char *back)
1123 {
1124   BOOL ret = False;
1125   size_t front_len = (front && *front) ? strlen(front) : 0;
1126   size_t back_len = (back && *back) ? strlen(back) : 0;
1127   size_t s_len;
1128
1129   while (front_len && strncmp(s, front, front_len) == 0)
1130   {
1131     char *p = s;
1132     ret = True;
1133     while (1)
1134     {
1135       if (!(*p = p[front_len]))
1136         break;
1137       p++;
1138     }
1139   }
1140
1141   s_len = strlen(s);
1142   while (back_len && s_len >= back_len && 
1143         (strncmp(s + s_len - back_len, back, back_len)==0))  
1144   {
1145     ret = True;
1146     s[s_len - back_len] = 0;
1147     s_len = strlen(s);
1148   }
1149   return(ret);
1150 }
1151
1152
1153 /*******************************************************************
1154 reduce a file name, removing .. elements.
1155 ********************************************************************/
1156 void dos_clean_name(char *s)
1157 {
1158   char *p=NULL;
1159
1160   DEBUG(3,("dos_clean_name [%s]\n",s));
1161
1162   /* remove any double slashes */
1163   string_sub(s, "\\\\", "\\");
1164
1165   while ((p = strstr(s,"\\..\\")) != NULL)
1166     {
1167       pstring s1;
1168
1169       *p = 0;
1170       pstrcpy(s1,p+3);
1171
1172       if ((p=strrchr(s,'\\')) != NULL)
1173         *p = 0;
1174       else
1175         *s = 0;
1176       pstrcat(s,s1);
1177     }  
1178
1179   trim_string(s,NULL,"\\..");
1180
1181   string_sub(s, "\\.\\", "\\");
1182 }
1183
1184 /*******************************************************************
1185 reduce a file name, removing .. elements. 
1186 ********************************************************************/
1187 void unix_clean_name(char *s)
1188 {
1189   char *p=NULL;
1190
1191   DEBUG(3,("unix_clean_name [%s]\n",s));
1192
1193   /* remove any double slashes */
1194   string_sub(s, "//","/");
1195
1196   /* Remove leading ./ characters */
1197   if(strncmp(s, "./", 2) == 0) {
1198     trim_string(s, "./", NULL);
1199     if(*s == 0)
1200       pstrcpy(s,"./");
1201   }
1202
1203   while ((p = strstr(s,"/../")) != NULL)
1204     {
1205       pstring s1;
1206
1207       *p = 0;
1208       pstrcpy(s1,p+3);
1209
1210       if ((p=strrchr(s,'/')) != NULL)
1211         *p = 0;
1212       else
1213         *s = 0;
1214       pstrcat(s,s1);
1215     }  
1216
1217   trim_string(s,NULL,"/..");
1218 }
1219
1220
1221 /*******************************************************************
1222 a wrapper for the normal chdir() function
1223 ********************************************************************/
1224 int ChDir(char *path)
1225 {
1226   int res;
1227   static pstring LastDir="";
1228
1229   if (strcsequal(path,".")) return(0);
1230
1231   if (*path == '/' && strcsequal(LastDir,path)) return(0);
1232   DEBUG(3,("chdir to %s\n",path));
1233   res = dos_chdir(path);
1234   if (!res)
1235     pstrcpy(LastDir,path);
1236   return(res);
1237 }
1238
1239 /* number of list structures for a caching GetWd function. */
1240 #define MAX_GETWDCACHE (50)
1241
1242 struct
1243 {
1244   SMB_DEV_T dev; /* These *must* be compatible with the types returned in a stat() call. */
1245   SMB_INO_T inode; /* These *must* be compatible with the types returned in a stat() call. */
1246   char *text; /* The pathname in DOS format. */
1247   BOOL valid;
1248 } ino_list[MAX_GETWDCACHE];
1249
1250 BOOL use_getwd_cache=True;
1251
1252 /*******************************************************************
1253   return the absolute current directory path - given a UNIX pathname.
1254   Note that this path is returned in DOS format, not UNIX
1255   format.
1256 ********************************************************************/
1257 char *GetWd(char *str)
1258 {
1259   pstring s;
1260   static BOOL getwd_cache_init = False;
1261   SMB_STRUCT_STAT st, st2;
1262   int i;
1263
1264   *s = 0;
1265
1266   if (!use_getwd_cache)
1267     return(dos_getwd(str));
1268
1269   /* init the cache */
1270   if (!getwd_cache_init)
1271   {
1272     getwd_cache_init = True;
1273     for (i=0;i<MAX_GETWDCACHE;i++)
1274     {
1275       string_init(&ino_list[i].text,"");
1276       ino_list[i].valid = False;
1277     }
1278   }
1279
1280   /*  Get the inode of the current directory, if this doesn't work we're
1281       in trouble :-) */
1282
1283   if (dos_stat(".",&st) == -1) 
1284   {
1285     DEBUG(0,("Very strange, couldn't stat \".\"\n"));
1286     return(dos_getwd(str));
1287   }
1288
1289
1290   for (i=0; i<MAX_GETWDCACHE; i++)
1291     if (ino_list[i].valid)
1292     {
1293
1294       /*  If we have found an entry with a matching inode and dev number
1295           then find the inode number for the directory in the cached string.
1296           If this agrees with that returned by the stat for the current
1297           directory then all is o.k. (but make sure it is a directory all
1298           the same...) */
1299       
1300       if (st.st_ino == ino_list[i].inode &&
1301           st.st_dev == ino_list[i].dev)
1302       {
1303         if (dos_stat(ino_list[i].text,&st2) == 0)
1304         {
1305           if (st.st_ino == st2.st_ino &&
1306               st.st_dev == st2.st_dev &&
1307               (st2.st_mode & S_IFMT) == S_IFDIR)
1308           {
1309             pstrcpy (str, ino_list[i].text);
1310
1311             /* promote it for future use */
1312             array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
1313             return (str);
1314           }
1315           else
1316           {
1317             /*  If the inode is different then something's changed, 
1318                 scrub the entry and start from scratch. */
1319             ino_list[i].valid = False;
1320           }
1321         }
1322       }
1323     }
1324
1325
1326   /*  We don't have the information to hand so rely on traditional methods.
1327       The very slow getcwd, which spawns a process on some systems, or the
1328       not quite so bad getwd. */
1329
1330   if (!dos_getwd(s))
1331   {
1332     DEBUG(0,("Getwd failed, errno %s\n",strerror(errno)));
1333     return (NULL);
1334   }
1335
1336   pstrcpy(str,s);
1337
1338   DEBUG(5,("GetWd %s, inode %d, dev %x\n",s,(int)st.st_ino,(int)st.st_dev));
1339
1340   /* add it to the cache */
1341   i = MAX_GETWDCACHE - 1;
1342   string_set(&ino_list[i].text,s);
1343   ino_list[i].dev = st.st_dev;
1344   ino_list[i].inode = st.st_ino;
1345   ino_list[i].valid = True;
1346
1347   /* put it at the top of the list */
1348   array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
1349
1350   return (str);
1351 }
1352
1353
1354
1355 /*******************************************************************
1356 reduce a file name, removing .. elements and checking that 
1357 it is below dir in the heirachy. This uses GetWd() and so must be run
1358 on the system that has the referenced file system.
1359
1360 widelinks are allowed if widelinks is true
1361 ********************************************************************/
1362 BOOL reduce_name(char *s,char *dir,BOOL widelinks)
1363 {
1364 #ifndef REDUCE_PATHS
1365   return True;
1366 #else
1367   pstring dir2;
1368   pstring wd;
1369   pstring base_name;
1370   pstring newname;
1371   char *p=NULL;
1372   BOOL relative = (*s != '/');
1373
1374   *dir2 = *wd = *base_name = *newname = 0;
1375
1376   if (widelinks)
1377     {
1378       unix_clean_name(s);
1379       /* can't have a leading .. */
1380       if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
1381         {
1382           DEBUG(3,("Illegal file name? (%s)\n",s));
1383           return(False);
1384         }
1385
1386       if (strlen(s) == 0)
1387         pstrcpy(s,"./");
1388
1389       return(True);
1390     }
1391   
1392   DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
1393
1394   /* remove any double slashes */
1395   string_sub(s,"//","/");
1396
1397   pstrcpy(base_name,s);
1398   p = strrchr(base_name,'/');
1399
1400   if (!p)
1401     return(True);
1402
1403   if (!GetWd(wd))
1404     {
1405       DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
1406       return(False);
1407     }
1408
1409   if (ChDir(dir) != 0)
1410     {
1411       DEBUG(0,("couldn't chdir to %s\n",dir));
1412       return(False);
1413     }
1414
1415   if (!GetWd(dir2))
1416     {
1417       DEBUG(0,("couldn't getwd for %s\n",dir));
1418       ChDir(wd);
1419       return(False);
1420     }
1421
1422
1423     if (p && (p != base_name))
1424       {
1425         *p = 0;
1426         if (strcmp(p+1,".")==0)
1427           p[1]=0;
1428         if (strcmp(p+1,"..")==0)
1429           *p = '/';
1430       }
1431
1432   if (ChDir(base_name) != 0)
1433     {
1434       ChDir(wd);
1435       DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name));
1436       return(False);
1437     }
1438
1439   if (!GetWd(newname))
1440     {
1441       ChDir(wd);
1442       DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
1443       return(False);
1444     }
1445
1446   if (p && (p != base_name))
1447     {
1448       pstrcat(newname,"/");
1449       pstrcat(newname,p+1);
1450     }
1451
1452   {
1453     int l = strlen(dir2);    
1454     if (dir2[l-1] == '/')
1455       l--;
1456
1457     if (strncmp(newname,dir2,l) != 0)
1458       {
1459         ChDir(wd);
1460         DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,l));
1461         return(False);
1462       }
1463
1464     if (relative)
1465       {
1466         if (newname[l] == '/')
1467           pstrcpy(s,newname + l + 1);
1468         else
1469           pstrcpy(s,newname+l);
1470       }
1471     else
1472       pstrcpy(s,newname);
1473   }
1474
1475   ChDir(wd);
1476
1477   if (strlen(s) == 0)
1478     pstrcpy(s,"./");
1479
1480   DEBUG(3,("reduced to %s\n",s));
1481   return(True);
1482 #endif
1483 }
1484
1485 /****************************************************************************
1486 expand some *s 
1487 ****************************************************************************/
1488 static void expand_one(char *Mask,int len)
1489 {
1490   char *p1;
1491   while ((p1 = strchr(Mask,'*')) != NULL)
1492     {
1493       int lfill = (len+1) - strlen(Mask);
1494       int l1= (p1 - Mask);
1495       pstring tmp;
1496       pstrcpy(tmp,Mask);  
1497       memset(tmp+l1,'?',lfill);
1498       pstrcpy(tmp + l1 + lfill,Mask + l1 + 1);  
1499       pstrcpy(Mask,tmp);      
1500     }
1501 }
1502
1503 /****************************************************************************
1504 parse out a directory name from a path name. Assumes dos style filenames.
1505 ****************************************************************************/
1506 static char *dirname_dos(char *path,char *buf)
1507 {
1508   char *p = strrchr(path,'\\');
1509
1510   if (!p)
1511     pstrcpy(buf,path);
1512   else
1513     {
1514       *p = 0;
1515       pstrcpy(buf,path);
1516       *p = '\\';
1517     }
1518
1519   return(buf);
1520 }
1521
1522
1523 /****************************************************************************
1524 expand a wildcard expression, replacing *s with ?s
1525 ****************************************************************************/
1526 void expand_mask(char *Mask,BOOL doext)
1527 {
1528   pstring mbeg,mext;
1529   pstring dirpart;
1530   pstring filepart;
1531   BOOL hasdot = False;
1532   char *p1;
1533   BOOL absolute = (*Mask == '\\');
1534
1535   *mbeg = *mext = *dirpart = *filepart = 0;
1536
1537   /* parse the directory and filename */
1538   if (strchr(Mask,'\\'))
1539     dirname_dos(Mask,dirpart);
1540
1541   filename_dos(Mask,filepart);
1542
1543   pstrcpy(mbeg,filepart);
1544   if ((p1 = strchr(mbeg,'.')) != NULL)
1545     {
1546       hasdot = True;
1547       *p1 = 0;
1548       p1++;
1549       pstrcpy(mext,p1);
1550     }
1551   else
1552     {
1553       pstrcpy(mext,"");
1554       if (strlen(mbeg) > 8)
1555         {
1556           pstrcpy(mext,mbeg + 8);
1557           mbeg[8] = 0;
1558         }
1559     }
1560
1561   if (*mbeg == 0)
1562     pstrcpy(mbeg,"????????");
1563   if ((*mext == 0) && doext && !hasdot)
1564     pstrcpy(mext,"???");
1565
1566   if (strequal(mbeg,"*") && *mext==0) 
1567     pstrcpy(mext,"*");
1568
1569   /* expand *'s */
1570   expand_one(mbeg,8);
1571   if (*mext)
1572     expand_one(mext,3);
1573
1574   pstrcpy(Mask,dirpart);
1575   if (*dirpart || absolute) pstrcat(Mask,"\\");
1576   pstrcat(Mask,mbeg);
1577   pstrcat(Mask,".");
1578   pstrcat(Mask,mext);
1579
1580   DEBUG(6,("Mask expanded to [%s]\n",Mask));
1581 }  
1582
1583
1584 /****************************************************************************
1585 does a string have any uppercase chars in it?
1586 ****************************************************************************/
1587 BOOL strhasupper(char *s)
1588 {
1589   while (*s) 
1590   {
1591 #if !defined(KANJI_WIN95_COMPATIBILITY)
1592   /*
1593    * For completeness we should put in equivalent code for code pages
1594    * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
1595    * doubt anyone wants Samba to behave differently from Win95 and WinNT
1596    * here. They both treat full width ascii characters as case senstive
1597    * filenames (ie. they don't do the work we do here).
1598    * JRA. 
1599    */
1600
1601     if(lp_client_code_page() == KANJI_CODEPAGE)
1602     {
1603       /* Win95 treats full width ascii characters as case sensitive. */
1604       if (is_shift_jis (*s))
1605         s += 2;
1606       else if (is_kana (*s))
1607         s++;
1608       else
1609       {
1610         if (isupper(*s))
1611           return(True);
1612         s++;
1613       }
1614     }
1615     else
1616 #endif /* KANJI_WIN95_COMPATIBILITY */
1617     {
1618       int skip = skip_multibyte_char( *s );
1619       if( skip != 0 )
1620         s += skip;
1621       else {
1622         if (isupper(*s))
1623           return(True);
1624         s++;
1625       }
1626     }
1627   }
1628   return(False);
1629 }
1630
1631 /****************************************************************************
1632 does a string have any lowercase chars in it?
1633 ****************************************************************************/
1634 BOOL strhaslower(char *s)
1635 {
1636   while (*s) 
1637   {
1638 #if !defined(KANJI_WIN95_COMPATIBILITY)
1639   /*
1640    * For completeness we should put in equivalent code for code pages
1641    * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
1642    * doubt anyone wants Samba to behave differently from Win95 and WinNT
1643    * here. They both treat full width ascii characters as case senstive
1644    * filenames (ie. they don't do the work we do here).
1645    * JRA. 
1646    */
1647
1648     if(lp_client_code_page() == KANJI_CODEPAGE)
1649     {
1650       /* Win95 treats full width ascii characters as case sensitive. */
1651       if (is_shift_jis (*s))
1652       {
1653         if (is_sj_upper (s[0], s[1]))
1654           return(True);
1655         if (is_sj_lower (s[0], s[1]))
1656           return (True);
1657         s += 2;
1658       }
1659       else if (is_kana (*s))
1660       {
1661         s++;
1662       }
1663       else
1664       {
1665         if (islower(*s))
1666           return(True);
1667         s++;
1668       }
1669     }
1670     else
1671 #endif /* KANJI_WIN95_COMPATIBILITY */
1672     {
1673       int skip = skip_multibyte_char( *s );
1674       if( skip != 0 )
1675         s += skip;
1676       else {
1677         if (islower(*s))
1678           return(True);
1679         s++;
1680       }
1681     }
1682   }
1683   return(False);
1684 }
1685
1686 /****************************************************************************
1687 find the number of chars in a string
1688 ****************************************************************************/
1689 int count_chars(char *s,char c)
1690 {
1691   int count=0;
1692
1693 #if !defined(KANJI_WIN95_COMPATIBILITY)
1694   /*
1695    * For completeness we should put in equivalent code for code pages
1696    * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
1697    * doubt anyone wants Samba to behave differently from Win95 and WinNT
1698    * here. They both treat full width ascii characters as case senstive
1699    * filenames (ie. they don't do the work we do here).
1700    * JRA. 
1701    */
1702
1703   if(lp_client_code_page() == KANJI_CODEPAGE)
1704   {
1705     /* Win95 treats full width ascii characters as case sensitive. */
1706     while (*s) 
1707     {
1708       if (is_shift_jis (*s))
1709         s += 2;
1710       else 
1711       {
1712         if (*s == c)
1713           count++;
1714         s++;
1715       }
1716     }
1717   }
1718   else
1719 #endif /* KANJI_WIN95_COMPATIBILITY */
1720   {
1721     while (*s) 
1722     {
1723       int skip = skip_multibyte_char( *s );
1724       if( skip != 0 )
1725         s += skip;
1726       else {
1727         if (*s == c)
1728           count++;
1729         s++;
1730       }
1731     }
1732   }
1733   return(count);
1734 }
1735
1736
1737 /****************************************************************************
1738   make a dir struct
1739 ****************************************************************************/
1740 void make_dir_struct(char *buf,char *mask,char *fname,SMB_OFF_T size,int mode,time_t date)
1741 {  
1742   char *p;
1743   pstring mask2;
1744
1745   pstrcpy(mask2,mask);
1746
1747   if ((mode & aDIR) != 0)
1748     size = 0;
1749
1750   memset(buf+1,' ',11);
1751   if ((p = strchr(mask2,'.')) != NULL)
1752     {
1753       *p = 0;
1754       memcpy(buf+1,mask2,MIN(strlen(mask2),8));
1755       memcpy(buf+9,p+1,MIN(strlen(p+1),3));
1756       *p = '.';
1757     }
1758   else
1759     memcpy(buf+1,mask2,MIN(strlen(mask2),11));
1760
1761   bzero(buf+21,DIR_STRUCT_SIZE-21);
1762   CVAL(buf,21) = mode;
1763   put_dos_date(buf,22,date);
1764   SSVAL(buf,26,size & 0xFFFF);
1765   SSVAL(buf,28,(size >> 16)&0xFFFF);
1766   StrnCpy(buf+30,fname,12);
1767   if (!case_sensitive)
1768     strupper(buf+30);
1769   DEBUG(8,("put name [%s] into dir struct\n",buf+30));
1770 }
1771
1772
1773 /*******************************************************************
1774 close the low 3 fd's and open dev/null in their place
1775 ********************************************************************/
1776 void close_low_fds(void)
1777 {
1778   int fd;
1779   int i;
1780   close(0); close(1); close(2);
1781   /* try and use up these file descriptors, so silly
1782      library routines writing to stdout etc won't cause havoc */
1783   for (i=0;i<3;i++) {
1784     fd = open("/dev/null",O_RDWR,0);
1785     if (fd < 0) fd = open("/dev/null",O_WRONLY,0);
1786     if (fd < 0) {
1787       DEBUG(0,("Can't open /dev/null\n"));
1788       return;
1789     }
1790     if (fd != i) {
1791       DEBUG(0,("Didn't get file descriptor %d\n",i));
1792       return;
1793     }
1794   }
1795 }
1796
1797 /****************************************************************************
1798 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
1799 else
1800 if SYSV use O_NDELAY
1801 if BSD use FNDELAY
1802 ****************************************************************************/
1803 static int set_blocking(int fd, BOOL set)
1804 {
1805   int val;
1806 #ifdef O_NONBLOCK
1807 #define FLAG_TO_SET O_NONBLOCK
1808 #else
1809 #ifdef SYSV
1810 #define FLAG_TO_SET O_NDELAY
1811 #else /* BSD */
1812 #define FLAG_TO_SET FNDELAY
1813 #endif
1814 #endif
1815
1816   if((val = fcntl(fd, F_GETFL, 0)) == -1)
1817         return -1;
1818   if(set) /* Turn blocking on - ie. clear nonblock flag */
1819         val &= ~FLAG_TO_SET;
1820   else
1821     val |= FLAG_TO_SET;
1822   return fcntl( fd, F_SETFL, val);
1823 #undef FLAG_TO_SET
1824 }
1825
1826
1827 /****************************************************************************
1828 write to a socket
1829 ****************************************************************************/
1830 ssize_t write_socket(int fd,char *buf,size_t len)
1831 {
1832   ssize_t ret=0;
1833
1834   if (passive)
1835     return(len);
1836   DEBUG(6,("write_socket(%d,%d)\n",fd,len));
1837   ret = write_data(fd,buf,len);
1838       
1839   DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,len,ret));
1840   if(ret <= 0)
1841     DEBUG(0,("write_socket: Error writing %d bytes to socket %d: ERRNO = %s\n", 
1842        len, fd, strerror(errno) ));
1843
1844   return(ret);
1845 }
1846
1847 /****************************************************************************
1848 read from a socket
1849 ****************************************************************************/
1850 ssize_t read_udp_socket(int fd,char *buf,size_t len)
1851 {
1852   ssize_t ret;
1853   struct sockaddr_in sock;
1854   int socklen;
1855   
1856   socklen = sizeof(sock);
1857   bzero((char *)&sock,socklen);
1858   bzero((char *)&lastip,sizeof(lastip));
1859   ret = (ssize_t)recvfrom(fd,buf,len,0,(struct sockaddr *)&sock,&socklen);
1860   if (ret <= 0) {
1861     DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno)));
1862     return(0);
1863   }
1864
1865   lastip = sock.sin_addr;
1866   lastport = ntohs(sock.sin_port);
1867
1868   DEBUG(10,("read_udp_socket: lastip %s lastport %d read: %d\n",
1869              inet_ntoa(lastip), lastport, ret));
1870
1871   return(ret);
1872 }
1873
1874 /****************************************************************************
1875 read data from a device with a timout in msec.
1876 mincount = if timeout, minimum to read before returning
1877 maxcount = number to be read.
1878 time_out = timeout in milliseconds
1879 ****************************************************************************/
1880
1881 ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out)
1882 {
1883   fd_set fds;
1884   int selrtn;
1885   ssize_t readret;
1886   size_t nread = 0;
1887   struct timeval timeout;
1888
1889   /* just checking .... */
1890   if (maxcnt <= 0) return(0);
1891
1892   smb_read_error = 0;
1893
1894   /* Blocking read */
1895   if (time_out <= 0) {
1896     if (mincnt == 0) mincnt = maxcnt;
1897
1898     while (nread < mincnt) {
1899 #ifdef WITH_SSL
1900       if(fd == sslFd){
1901         readret = SSL_read(ssl, buf + nread, maxcnt - nread);
1902       }else{
1903         readret = read(fd, buf + nread, maxcnt - nread);
1904       }
1905 #else /* WITH_SSL */
1906       readret = read(fd, buf + nread, maxcnt - nread);
1907 #endif /* WITH_SSL */
1908
1909       if (readret == 0) {
1910         smb_read_error = READ_EOF;
1911         return -1;
1912       }
1913
1914       if (readret == -1) {
1915         smb_read_error = READ_ERROR;
1916         return -1;
1917       }
1918       nread += readret;
1919     }
1920     return((ssize_t)nread);
1921   }
1922   
1923   /* Most difficult - timeout read */
1924   /* If this is ever called on a disk file and 
1925      mincnt is greater then the filesize then
1926      system performance will suffer severely as 
1927      select always returns true on disk files */
1928
1929   /* Set initial timeout */
1930   timeout.tv_sec = (time_t)(time_out / 1000);
1931   timeout.tv_usec = (long)(1000 * (time_out % 1000));
1932
1933   for (nread=0; nread < mincnt; ) 
1934   {      
1935     FD_ZERO(&fds);
1936     FD_SET(fd,&fds);
1937       
1938     selrtn = sys_select(fd+1,&fds,&timeout);
1939
1940     /* Check if error */
1941     if(selrtn == -1) {
1942       /* something is wrong. Maybe the socket is dead? */
1943       smb_read_error = READ_ERROR;
1944       return -1;
1945     }
1946       
1947     /* Did we timeout ? */
1948     if (selrtn == 0) {
1949       smb_read_error = READ_TIMEOUT;
1950       return -1;
1951     }
1952       
1953 #ifdef WITH_SSL
1954     if(fd == sslFd){
1955       readret = SSL_read(ssl, buf + nread, maxcnt - nread);
1956     }else{
1957       readret = read(fd, buf + nread, maxcnt - nread);
1958     }
1959 #else /* WITH_SSL */
1960     readret = read(fd, buf+nread, maxcnt-nread);
1961 #endif /* WITH_SSL */
1962
1963     if (readret == 0) {
1964       /* we got EOF on the file descriptor */
1965       smb_read_error = READ_EOF;
1966       return -1;
1967     }
1968
1969     if (readret == -1) {
1970       /* the descriptor is probably dead */
1971       smb_read_error = READ_ERROR;
1972       return -1;
1973     }
1974       
1975     nread += readret;
1976   }
1977
1978   /* Return the number we got */
1979   return((ssize_t)nread);
1980 }
1981
1982 /*******************************************************************
1983 find the difference in milliseconds between two struct timeval
1984 values
1985 ********************************************************************/
1986 int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew)
1987 {
1988   return((tvalnew->tv_sec - tvalold->tv_sec)*1000 + 
1989          ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000);  
1990 }
1991
1992 /****************************************************************************
1993 send a keepalive packet (rfc1002)
1994 ****************************************************************************/
1995 BOOL send_keepalive(int client)
1996 {
1997   unsigned char buf[4];
1998
1999   buf[0] = 0x85;
2000   buf[1] = buf[2] = buf[3] = 0;
2001
2002   return(write_data(client,(char *)buf,4) == 4);
2003 }
2004
2005
2006
2007 /****************************************************************************
2008   read data from the client, reading exactly N bytes. 
2009 ****************************************************************************/
2010 ssize_t read_data(int fd,char *buffer,size_t N)
2011 {
2012   ssize_t  ret;
2013   size_t total=0;  
2014  
2015   smb_read_error = 0;
2016
2017   while (total < N)
2018   {
2019 #ifdef WITH_SSL
2020     if(fd == sslFd){
2021       ret = SSL_read(ssl, buffer + total, N - total);
2022     }else{
2023       ret = read(fd,buffer + total,N - total);
2024     }
2025 #else /* WITH_SSL */
2026     ret = read(fd,buffer + total,N - total);
2027 #endif /* WITH_SSL */
2028
2029     if (ret == 0)
2030     {
2031       smb_read_error = READ_EOF;
2032       return 0;
2033     }
2034     if (ret == -1)
2035     {
2036       smb_read_error = READ_ERROR;
2037       return -1;
2038     }
2039     total += ret;
2040   }
2041   return (ssize_t)total;
2042 }
2043
2044
2045 /****************************************************************************
2046   write data to a fd 
2047 ****************************************************************************/
2048 ssize_t write_data(int fd,char *buffer,size_t N)
2049 {
2050   size_t total=0;
2051   ssize_t ret;
2052
2053   while (total < N)
2054   {
2055 #ifdef WITH_SSL
2056     if(fd == sslFd){
2057       ret = SSL_write(ssl,buffer + total,N - total);
2058     }else{
2059       ret = write(fd,buffer + total,N - total);
2060     }
2061 #else /* WITH_SSL */
2062     ret = write(fd,buffer + total,N - total);
2063 #endif /* WITH_SSL */
2064
2065     if (ret == -1) return -1;
2066     if (ret == 0) return total;
2067
2068     total += ret;
2069   }
2070   return (ssize_t)total;
2071 }
2072
2073
2074 /****************************************************************************
2075 transfer some data between two fd's
2076 ****************************************************************************/
2077 SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n,char *header,int headlen,int align)
2078 {
2079   static char *buf=NULL;  
2080   static int size=0;
2081   char *buf1,*abuf;
2082   SMB_OFF_T total = 0;
2083
2084   DEBUG(4,("transfer_file n=%.0f  (head=%d) called\n",(double)n,headlen));
2085
2086   if (size == 0) {
2087     size = lp_readsize();
2088     size = MAX(size,1024);
2089   }
2090
2091   while (!buf && size>0) {
2092     buf = (char *)Realloc(buf,size+8);
2093     if (!buf) size /= 2;
2094   }
2095
2096   if (!buf) {
2097     DEBUG(0,("Can't allocate transfer buffer!\n"));
2098     exit(1);
2099   }
2100
2101   abuf = buf + (align%8);
2102
2103   if (header)
2104     n += headlen;
2105
2106   while (n > 0)
2107   {
2108     int s = (int)MIN(n,(SMB_OFF_T)size);
2109     int ret,ret2=0;
2110
2111     ret = 0;
2112
2113     if (header && (headlen >= MIN(s,1024))) {
2114       buf1 = header;
2115       s = headlen;
2116       ret = headlen;
2117       headlen = 0;
2118       header = NULL;
2119     } else {
2120       buf1 = abuf;
2121     }
2122
2123     if (header && headlen > 0)
2124     {
2125       ret = MIN(headlen,size);
2126       memcpy(buf1,header,ret);
2127       headlen -= ret;
2128       header += ret;
2129       if (headlen <= 0) header = NULL;
2130     }
2131
2132     if (s > ret)
2133       ret += read(infd,buf1+ret,s-ret);
2134
2135     if (ret > 0)
2136     {
2137       ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret);
2138       if (ret2 > 0) total += ret2;
2139       /* if we can't write then dump excess data */
2140       if (ret2 != ret)
2141         transfer_file(infd,-1,n-(ret+headlen),NULL,0,0);
2142     }
2143     if (ret <= 0 || ret2 != ret)
2144       return(total);
2145     n -= ret;
2146   }
2147   return(total);
2148 }
2149
2150
2151 /****************************************************************************
2152 read 4 bytes of a smb packet and return the smb length of the packet
2153 store the result in the buffer
2154 This version of the function will return a length of zero on receiving
2155 a keepalive packet.
2156 timeout is in milliseconds.
2157 ****************************************************************************/
2158 static ssize_t read_smb_length_return_keepalive(int fd,char *inbuf,unsigned int timeout)
2159 {
2160   ssize_t len=0;
2161   int msg_type;
2162   BOOL ok = False;
2163
2164   while (!ok)
2165   {
2166     if (timeout > 0)
2167       ok = (read_with_timeout(fd,inbuf,4,4,timeout) == 4);
2168     else 
2169       ok = (read_data(fd,inbuf,4) == 4);
2170
2171     if (!ok)
2172       return(-1);
2173
2174     len = smb_len(inbuf);
2175     msg_type = CVAL(inbuf,0);
2176
2177     if (msg_type == 0x85) 
2178       DEBUG(5,("Got keepalive packet\n"));
2179   }
2180
2181   DEBUG(10,("got smb length of %d\n",len));
2182
2183   return(len);
2184 }
2185
2186 /****************************************************************************
2187 read 4 bytes of a smb packet and return the smb length of the packet
2188 store the result in the buffer. This version of the function will
2189 never return a session keepalive (length of zero).
2190 timeout is in milliseconds.
2191 ****************************************************************************/
2192 ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout)
2193 {
2194   ssize_t len;
2195
2196   for(;;)
2197   {
2198     len = read_smb_length_return_keepalive(fd, inbuf, timeout);
2199
2200     if(len < 0)
2201       return len;
2202
2203     /* Ignore session keepalives. */
2204     if(CVAL(inbuf,0) != 0x85)
2205       break;
2206   }
2207
2208   return len;
2209 }
2210
2211 /****************************************************************************
2212   read an smb from a fd. Note that the buffer *MUST* be of size
2213   BUFFER_SIZE+SAFETY_MARGIN.
2214   The timeout is in milliseconds. 
2215   This function will return on a
2216   receipt of a session keepalive packet.
2217 ****************************************************************************/
2218 BOOL receive_smb(int fd,char *buffer, unsigned int timeout)
2219 {
2220   ssize_t len,ret;
2221
2222   smb_read_error = 0;
2223
2224   bzero(buffer,smb_size + 100);
2225
2226   len = read_smb_length_return_keepalive(fd,buffer,timeout);
2227   if (len < 0)
2228     return(False);
2229
2230   if (len > BUFFER_SIZE) {
2231     DEBUG(0,("Invalid packet length! (%d bytes).\n",len));
2232     if (len > BUFFER_SIZE + (SAFETY_MARGIN/2))
2233       exit(1);
2234   }
2235
2236   if(len > 0) {
2237     ret = read_data(fd,buffer+4,len);
2238     if (ret != len) {
2239       smb_read_error = READ_ERROR;
2240       return False;
2241     }
2242   }
2243   return(True);
2244 }
2245
2246 /****************************************************************************
2247   read an smb from a fd ignoring all keepalive packets. Note that the buffer 
2248   *MUST* be of size BUFFER_SIZE+SAFETY_MARGIN.
2249   The timeout is in milliseconds
2250
2251   This is exactly the same as receive_smb except that it never returns
2252   a session keepalive packet (just as receive_smb used to do).
2253   receive_smb was changed to return keepalives as the oplock processing means this call
2254   should never go into a blocking read.
2255 ****************************************************************************/
2256
2257 BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout)
2258 {
2259   BOOL ret;
2260
2261   for(;;)
2262   {
2263     ret = receive_smb(fd, buffer, timeout);
2264
2265     if(ret == False)
2266       return ret;
2267
2268     /* Ignore session keepalive packets. */
2269     if(CVAL(buffer,0) != 0x85)
2270       break;
2271   }
2272   return ret;
2273 }
2274
2275 /****************************************************************************
2276   send an smb to a fd 
2277 ****************************************************************************/
2278 BOOL send_smb(int fd,char *buffer)
2279 {
2280   size_t len;
2281   size_t nwritten=0;
2282   ssize_t ret;
2283   len = smb_len(buffer) + 4;
2284
2285   while (nwritten < len)
2286   {
2287     ret = write_socket(fd,buffer+nwritten,len - nwritten);
2288     if (ret <= 0)
2289     {
2290       DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret));
2291       close_sockets();
2292       exit(1);
2293     }
2294     nwritten += ret;
2295   }
2296
2297   return True;
2298 }
2299
2300
2301 /****************************************************************************
2302 find a pointer to a netbios name
2303 ****************************************************************************/
2304 static char *name_ptr(char *buf,int ofs)
2305 {
2306   unsigned char c = *(unsigned char *)(buf+ofs);
2307
2308   if ((c & 0xC0) == 0xC0)
2309     {
2310       uint16 l;
2311       char p[2];
2312       memcpy(p,buf+ofs,2);
2313       p[0] &= ~0xC0;
2314       l = RSVAL(p,0);
2315       DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
2316       return(buf + l);
2317     }
2318   else
2319     return(buf+ofs);
2320 }  
2321
2322 /****************************************************************************
2323 extract a netbios name from a buf
2324 ****************************************************************************/
2325 int name_extract(char *buf,int ofs,char *name)
2326 {
2327   char *p = name_ptr(buf,ofs);
2328   int d = PTR_DIFF(p,buf+ofs);
2329   pstrcpy(name,"");
2330   if (d < -50 || d > 50) return(0);
2331   return(name_interpret(p,name));
2332 }
2333   
2334 /****************************************************************************
2335 return the total storage length of a mangled name
2336 ****************************************************************************/
2337 int name_len(unsigned char *s)
2338 {
2339   int len;
2340
2341   /* If the two high bits of the byte are set, return 2. */
2342   if (0xC0 == (*s & 0xC0))
2343     return(2);
2344
2345   /* Add up the length bytes. */
2346   for (len = 1; (*s); s += (*s) + 1) {
2347           len += *s + 1;
2348           SMB_ASSERT(len < 80);
2349   }
2350
2351   return(len);
2352 } /* name_len */
2353
2354 /****************************************************************************
2355 send a single packet to a port on another machine
2356 ****************************************************************************/
2357 BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
2358 {
2359   BOOL ret;
2360   int out_fd;
2361   struct sockaddr_in sock_out;
2362
2363   if (passive)
2364     return(True);
2365
2366   /* create a socket to write to */
2367   out_fd = socket(AF_INET, type, 0);
2368   if (out_fd == -1) 
2369     {
2370       DEBUG(0,("socket failed"));
2371       return False;
2372     }
2373
2374   /* set the address and port */
2375   bzero((char *)&sock_out,sizeof(sock_out));
2376   putip((char *)&sock_out.sin_addr,(char *)&ip);
2377   sock_out.sin_port = htons( port );
2378   sock_out.sin_family = AF_INET;
2379   
2380   if (DEBUGLEVEL > 0)
2381     DEBUG(3,("sending a packet of len %d to (%s) on port %d of type %s\n",
2382              len,inet_ntoa(ip),port,type==SOCK_DGRAM?"DGRAM":"STREAM"));
2383         
2384   /* send it */
2385   ret = (sendto(out_fd,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
2386
2387   if (!ret)
2388     DEBUG(0,("Packet send to %s(%d) failed ERRNO=%s\n",
2389              inet_ntoa(ip),port,strerror(errno)));
2390
2391   close(out_fd);
2392   return(ret);
2393 }
2394
2395 /*******************************************************************
2396 sleep for a specified number of milliseconds
2397 ********************************************************************/
2398 void msleep(int t)
2399 {
2400   int tdiff=0;
2401   struct timeval tval,t1,t2;  
2402   fd_set fds;
2403
2404   GetTimeOfDay(&t1);
2405   GetTimeOfDay(&t2);
2406   
2407   while (tdiff < t) {
2408     tval.tv_sec = (t-tdiff)/1000;
2409     tval.tv_usec = 1000*((t-tdiff)%1000);
2410  
2411     FD_ZERO(&fds);
2412     errno = 0;
2413     sys_select(0,&fds,&tval);
2414
2415     GetTimeOfDay(&t2);
2416     tdiff = TvalDiff(&t1,&t2);
2417   }
2418 }
2419
2420 /****************************************************************************
2421 check if a string is part of a list
2422 ****************************************************************************/
2423 BOOL in_list(char *s,char *list,BOOL casesensitive)
2424 {
2425   pstring tok;
2426   char *p=list;
2427
2428   if (!list) return(False);
2429
2430   while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
2431     if (casesensitive) {
2432       if (strcmp(tok,s) == 0)
2433         return(True);
2434     } else {
2435       if (StrCaseCmp(tok,s) == 0)
2436         return(True);
2437     }
2438   }
2439   return(False);
2440 }
2441
2442 /* this is used to prevent lots of mallocs of size 1 */
2443 static char *null_string = NULL;
2444
2445 /****************************************************************************
2446 set a string value, allocing the space for the string
2447 ****************************************************************************/
2448 BOOL string_init(char **dest,char *src)
2449 {
2450   int l;
2451   if (!src)     
2452     src = "";
2453
2454   l = strlen(src);
2455
2456   if (l == 0)
2457     {
2458       if (!null_string) {
2459         if((null_string = (char *)malloc(1)) == NULL) {
2460           DEBUG(0,("string_init: malloc fail for null_string.\n"));
2461           return False;
2462         }
2463         *null_string = 0;
2464       }
2465       *dest = null_string;
2466     }
2467   else
2468     {
2469       (*dest) = (char *)malloc(l+1);
2470       if ((*dest) == NULL) {
2471               DEBUG(0,("Out of memory in string_init\n"));
2472               return False;
2473       }
2474
2475       pstrcpy(*dest,src);
2476     }
2477   return(True);
2478 }
2479
2480 /****************************************************************************
2481 free a string value
2482 ****************************************************************************/
2483 void string_free(char **s)
2484 {
2485   if (!s || !(*s)) return;
2486   if (*s == null_string)
2487     *s = NULL;
2488   if (*s) free(*s);
2489   *s = NULL;
2490 }
2491
2492 /****************************************************************************
2493 set a string value, allocing the space for the string, and deallocating any 
2494 existing space
2495 ****************************************************************************/
2496 BOOL string_set(char **dest,char *src)
2497 {
2498   string_free(dest);
2499
2500   return(string_init(dest,src));
2501 }
2502
2503 /****************************************************************************
2504 substitute a string for a pattern in another string. Make sure there is 
2505 enough room!
2506
2507 This routine looks for pattern in s and replaces it with 
2508 insert. It may do multiple replacements.
2509
2510 return True if a substitution was done.
2511 ****************************************************************************/
2512 BOOL string_sub(char *s,char *pattern,char *insert)
2513 {
2514   BOOL ret = False;
2515   char *p;
2516   int ls,lp,li;
2517
2518   if (!insert || !pattern || !s) return(False);
2519
2520   ls = strlen(s);
2521   lp = strlen(pattern);
2522   li = strlen(insert);
2523
2524   if (!*pattern) return(False);
2525
2526   while (lp <= ls && (p = strstr(s,pattern)))
2527     {
2528       ret = True;
2529       memmove(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp));
2530       memcpy(p,insert,li);
2531       s = p + li;
2532       ls = strlen(s);
2533     }
2534   return(ret);
2535 }
2536
2537 /*********************************************************
2538 * Recursive routine that is called by unix_mask_match.
2539 * Does the actual matching. This is the 'original code' 
2540 * used by the unix matcher.
2541 *********************************************************/
2542 static BOOL unix_do_match(char *str, char *regexp, int case_sig)
2543 {
2544   char *p;
2545
2546   for( p = regexp; *p && *str; ) {
2547     switch(*p) {
2548     case '?':
2549       str++; p++;
2550       break;
2551
2552     case '*':
2553       /* Look for a character matching 
2554          the one after the '*' */
2555       p++;
2556       if(!*p)
2557         return True; /* Automatic match */
2558       while(*str) {
2559         while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
2560           str++;
2561         if(unix_do_match(str,p,case_sig))
2562           return True;
2563         if(!*str)
2564           return False;
2565         else
2566           str++;
2567       }
2568       return False;
2569
2570     default:
2571       if(case_sig) {
2572         if(*str != *p)
2573           return False;
2574       } else {
2575         if(toupper(*str) != toupper(*p))
2576           return False;
2577       }
2578       str++, p++;
2579       break;
2580     }
2581   }
2582   if(!*p && !*str)
2583     return True;
2584
2585   if (!*p && str[0] == '.' && str[1] == 0)
2586     return(True);
2587   
2588   if (!*str && *p == '?')
2589     {
2590       while (*p == '?') p++;
2591       return(!*p);
2592     }
2593
2594   if(!*str && (*p == '*' && p[1] == '\0'))
2595     return True;
2596   return False;
2597 }
2598
2599
2600 /*********************************************************
2601 * Routine to match a given string with a regexp - uses
2602 * simplified regexp that takes * and ? only. Case can be
2603 * significant or not.
2604 * This is the 'original code' used by the unix matcher.
2605 *********************************************************/
2606
2607 static BOOL unix_mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
2608 {
2609   char *p;
2610   pstring p1, p2;
2611   fstring ebase,eext,sbase,sext;
2612
2613   BOOL matched;
2614
2615   /* Make local copies of str and regexp */
2616   StrnCpy(p1,regexp,sizeof(pstring)-1);
2617   StrnCpy(p2,str,sizeof(pstring)-1);
2618
2619   if (!strchr(p2,'.')) {
2620     pstrcat(p2,".");
2621   }
2622
2623   /* Remove any *? and ** as they are meaningless */
2624   for(p = p1; *p; p++)
2625     while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
2626       (void)pstrcpy( &p[1], &p[2]);
2627
2628   if (strequal(p1,"*")) return(True);
2629
2630   DEBUG(8,("unix_mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
2631
2632   if (trans2) {
2633     fstrcpy(ebase,p1);
2634     fstrcpy(sbase,p2);
2635   } else {
2636     if ((p=strrchr(p1,'.'))) {
2637       *p = 0;
2638       fstrcpy(ebase,p1);
2639       fstrcpy(eext,p+1);
2640     } else {
2641       fstrcpy(ebase,p1);
2642       eext[0] = 0;
2643     }
2644
2645   if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
2646     *p = 0;
2647     fstrcpy(sbase,p2);
2648     fstrcpy(sext,p+1);
2649   } else {
2650     fstrcpy(sbase,p2);
2651     fstrcpy(sext,"");
2652   }
2653   }
2654
2655   matched = unix_do_match(sbase,ebase,case_sig) && 
2656     (trans2 || unix_do_match(sext,eext,case_sig));
2657
2658   DEBUG(8,("unix_mask_match returning %d\n", matched));
2659
2660   return matched;
2661 }
2662
2663 /*********************************************************
2664 * Recursive routine that is called by mask_match.
2665 * Does the actual matching. Returns True if matched,
2666 * False if failed. This is the 'new' NT style matcher.
2667 *********************************************************/
2668
2669 BOOL do_match(char *str, char *regexp, int case_sig)
2670 {
2671   char *p;
2672
2673   for( p = regexp; *p && *str; ) {
2674     switch(*p) {
2675     case '?':
2676       str++; p++;
2677       break;
2678
2679     case '*':
2680       /* Look for a character matching 
2681          the one after the '*' */
2682       p++;
2683       if(!*p)
2684         return True; /* Automatic match */
2685       while(*str) {
2686         while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
2687           str++;
2688         /* Now eat all characters that match, as
2689            we want the *last* character to match. */
2690         while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str))))
2691           str++;
2692         str--; /* We've eaten the match char after the '*' */
2693         if(do_match(str,p,case_sig)) {
2694           return True;
2695         }
2696         if(!*str) {
2697           return False;
2698         } else {
2699           str++;
2700         }
2701       }
2702       return False;
2703
2704     default:
2705       if(case_sig) {
2706         if(*str != *p) {
2707           return False;
2708         }
2709       } else {
2710         if(toupper(*str) != toupper(*p)) {
2711           return False;
2712         }
2713       }
2714       str++, p++;
2715       break;
2716     }
2717   }
2718
2719   if(!*p && !*str)
2720     return True;
2721
2722   if (!*p && str[0] == '.' && str[1] == 0) {
2723     return(True);
2724   }
2725   
2726   if (!*str && *p == '?') {
2727     while (*p == '?')
2728       p++;
2729     return(!*p);
2730   }
2731
2732   if(!*str && (*p == '*' && p[1] == '\0')) {
2733     return True;
2734   }
2735  
2736   return False;
2737 }
2738
2739
2740 /*********************************************************
2741 * Routine to match a given string with a regexp - uses
2742 * simplified regexp that takes * and ? only. Case can be
2743 * significant or not.
2744 * The 8.3 handling was rewritten by Ums Harald <Harald.Ums@pro-sieben.de>
2745 * This is the new 'NT style' matcher.
2746 *********************************************************/
2747
2748 BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
2749 {
2750   char *p;
2751   pstring t_pattern, t_filename, te_pattern, te_filename;
2752   fstring ebase,eext,sbase,sext;
2753
2754   BOOL matched = False;
2755
2756   /* Make local copies of str and regexp */
2757   pstrcpy(t_pattern,regexp);
2758   pstrcpy(t_filename,str);
2759
2760 #if 0
2761   /* 
2762    * Not sure if this is a good idea. JRA.
2763    */
2764   if(trans2 && is_8_3(t_pattern,False) && is_8_3(t_filename,False))
2765     trans2 = False;
2766 #endif
2767
2768 #if 0
2769   if (!strchr(t_filename,'.')) {
2770     pstrcat(t_filename,".");
2771   }
2772 #endif
2773
2774   /* Remove any *? and ** as they are meaningless */
2775   string_sub(t_pattern, "*?", "*");
2776   string_sub(t_pattern, "**", "*");
2777
2778   if (strequal(t_pattern,"*"))
2779     return(True);
2780
2781   DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", t_filename, t_pattern, case_sig));
2782
2783   if(trans2) {
2784     /*
2785      * Match each component of the regexp, split up by '.'
2786      * characters.
2787      */
2788     char *fp, *rp, *cp2, *cp1;
2789     BOOL last_wcard_was_star = False;
2790     int num_path_components, num_regexp_components;
2791
2792     pstrcpy(te_pattern,t_pattern);
2793     pstrcpy(te_filename,t_filename);
2794     /*
2795      * Remove multiple "*." patterns.
2796      */
2797     string_sub(te_pattern, "*.*.", "*.");
2798     num_regexp_components = count_chars(te_pattern, '.');
2799     num_path_components = count_chars(te_filename, '.');
2800
2801     /* 
2802      * Check for special 'hack' case of "DIR a*z". - needs to match a.b.c...z
2803      */
2804     if(num_regexp_components == 0)
2805       matched = do_match( te_filename, te_pattern, case_sig);
2806     else {
2807       for( cp1 = te_pattern, cp2 = te_filename; cp1;) {
2808         fp = strchr(cp2, '.');
2809         if(fp)
2810           *fp = '\0';
2811         rp = strchr(cp1, '.');
2812         if(rp)
2813           *rp = '\0';
2814
2815         if(cp1[strlen(cp1)-1] == '*')
2816           last_wcard_was_star = True;
2817         else
2818           last_wcard_was_star = False;
2819
2820         if(!do_match(cp2, cp1, case_sig))
2821           break;
2822
2823         cp1 = rp ? rp + 1 : NULL;
2824         cp2 = fp ? fp + 1 : "";
2825
2826         if(last_wcard_was_star || ((cp1 != NULL) && (*cp1 == '*'))) {
2827           /* Eat the extra path components. */
2828           int i;
2829
2830           for(i = 0; i < num_path_components - num_regexp_components; i++) {
2831             fp = strchr(cp2, '.');
2832             if(fp)
2833               *fp = '\0';
2834
2835             if((cp1 != NULL) && do_match( cp2, cp1, case_sig)) {
2836               cp2 = fp ? fp + 1 : "";
2837               break;
2838             }
2839             cp2 = fp ? fp + 1 : "";
2840           }
2841           num_path_components -= i;
2842         }
2843       } 
2844       if(cp1 == NULL && ((*cp2 == '\0') || last_wcard_was_star))
2845         matched = True;
2846     }
2847   } else {
2848
2849     /* -------------------------------------------------
2850      * Behaviour of Win95
2851      * for 8.3 filenames and 8.3 Wildcards
2852      * -------------------------------------------------
2853      */
2854     if (strequal (t_filename, ".")) {
2855       /*
2856        *  Patterns:  *.*  *. ?. ?  are valid
2857        *
2858        */
2859       if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
2860          strequal(t_pattern, "?.") || strequal(t_pattern, "?"))
2861         matched = True;
2862     } else if (strequal (t_filename, "..")) {
2863       /*
2864        *  Patterns:  *.*  *. ?. ? *.? are valid
2865        *
2866        */
2867       if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
2868          strequal(t_pattern, "?.") || strequal(t_pattern, "?") ||
2869          strequal(t_pattern, "*.?") || strequal(t_pattern, "?.*"))
2870         matched = True;
2871     } else {
2872
2873       if ((p = strrchr (t_pattern, '.'))) {
2874         /*
2875          * Wildcard has a suffix.
2876          */
2877         *p = 0;
2878         fstrcpy (ebase, t_pattern);
2879         if (p[1]) {
2880           fstrcpy (eext, p + 1);
2881         } else {
2882           /* pattern ends in DOT: treat as if there is no DOT */
2883           *eext = 0;
2884           if (strequal (ebase, "*"))
2885             return (True);
2886         }
2887       } else {
2888         /*
2889          * No suffix for wildcard.
2890          */
2891         fstrcpy (ebase, t_pattern);
2892         eext[0] = 0;
2893       }
2894
2895       p = strrchr (t_filename, '.');
2896       if (p && (p[1] == 0)      ) {
2897         /*
2898          * Filename has an extension of '.' only.
2899          */
2900         *p = 0; /* nuke dot at end of string */
2901         p = 0;  /* and treat it as if there is no extension */
2902       }
2903
2904       if (p) {
2905         /*
2906          * Filename has an extension.
2907          */
2908         *p = 0;
2909         fstrcpy (sbase, t_filename);
2910         fstrcpy (sext, p + 1);
2911         if (*eext) {
2912           matched = do_match(sbase, ebase, case_sig)
2913                     && do_match(sext, eext, case_sig);
2914         } else {
2915           /* pattern has no extension */
2916           /* Really: match complete filename with pattern ??? means exactly 3 chars */
2917           matched = do_match(str, ebase, case_sig);
2918         }
2919       } else {
2920         /* 
2921          * Filename has no extension.
2922          */
2923         fstrcpy (sbase, t_filename);
2924         fstrcpy (sext, "");
2925         if (*eext) {
2926           /* pattern has extension */
2927           matched = do_match(sbase, ebase, case_sig)
2928                     && do_match(sext, eext, case_sig);
2929         } else {
2930           matched = do_match(sbase, ebase, case_sig);
2931 #ifdef EMULATE_WEIRD_W95_MATCHING
2932           /*
2933            * Even Microsoft has some problems
2934            * Behaviour Win95 -> local disk 
2935            * is different from Win95 -> smb drive from Nt 4.0
2936            * This branch would reflect the Win95 local disk behaviour
2937            */
2938           if (!matched) {
2939             /* a? matches aa and a in w95 */
2940             fstrcat (sbase, ".");
2941             matched = do_match(sbase, ebase, case_sig);
2942           }
2943 #endif
2944         }
2945       }
2946     }
2947   }
2948
2949   DEBUG(8,("mask_match returning %d\n", matched));
2950
2951   return matched;
2952 }
2953
2954 /****************************************************************************
2955 become a daemon, discarding the controlling terminal
2956 ****************************************************************************/
2957 void become_daemon(void)
2958 {
2959         if (fork()) {
2960                 _exit(0);
2961         }
2962
2963   /* detach from the terminal */
2964 #ifdef HAVE_SETSID
2965         setsid();
2966 #elif defined(TIOCNOTTY)
2967         {
2968                 int i = open("/dev/tty", O_RDWR);
2969                 if (i != -1) {
2970                         ioctl(i, (int) TIOCNOTTY, (char *)0);      
2971                         close(i);
2972                 }
2973         }
2974 #endif /* HAVE_SETSID */
2975
2976         /* Close fd's 0,1,2. Needed if started by rsh */
2977         close_low_fds();
2978 }
2979
2980
2981 /****************************************************************************
2982 put up a yes/no prompt
2983 ****************************************************************************/
2984 BOOL yesno(char *p)
2985 {
2986   pstring ans;
2987   printf("%s",p);
2988
2989   if (!fgets(ans,sizeof(ans)-1,stdin))
2990     return(False);
2991
2992   if (*ans == 'y' || *ans == 'Y')
2993     return(True);
2994
2995   return(False);
2996 }
2997
2998 /****************************************************************************
2999 read a line from a file with possible \ continuation chars. 
3000 Blanks at the start or end of a line are stripped.
3001 The string will be allocated if s2 is NULL
3002 ****************************************************************************/
3003 char *fgets_slash(char *s2,int maxlen,FILE *f)
3004 {
3005   char *s=s2;
3006   int len = 0;
3007   int c;
3008   BOOL start_of_line = True;
3009
3010   if (feof(f))
3011     return(NULL);
3012
3013   if (!s2)
3014     {
3015       maxlen = MIN(maxlen,8);
3016       s = (char *)Realloc(s,maxlen);
3017     }
3018
3019   if (!s || maxlen < 2) return(NULL);
3020
3021   *s = 0;
3022
3023   while (len < maxlen-1)
3024     {
3025       c = getc(f);
3026       switch (c)
3027         {
3028         case '\r':
3029           break;
3030         case '\n':
3031           while (len > 0 && s[len-1] == ' ')
3032             {
3033               s[--len] = 0;
3034             }
3035           if (len > 0 && s[len-1] == '\\')
3036             {
3037               s[--len] = 0;
3038               start_of_line = True;
3039               break;
3040             }
3041           return(s);
3042         case EOF:
3043           if (len <= 0 && !s2) 
3044             free(s);
3045           return(len>0?s:NULL);
3046         case ' ':
3047           if (start_of_line)
3048             break;
3049         default:
3050           start_of_line = False;
3051           s[len++] = c;
3052           s[len] = 0;
3053         }
3054       if (!s2 && len > maxlen-3)
3055         {
3056           maxlen *= 2;
3057           s = (char *)Realloc(s,maxlen);
3058           if (!s) return(NULL);
3059         }
3060     }
3061   return(s);
3062 }
3063
3064
3065
3066 /****************************************************************************
3067 set the length of a file from a filedescriptor.
3068 Returns 0 on success, -1 on failure.
3069 ****************************************************************************/
3070 int set_filelen(int fd, SMB_OFF_T len)
3071 {
3072 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
3073    extend a file with ftruncate. Provide alternate implementation
3074    for this */
3075
3076 #ifdef HAVE_FTRUNCATE_EXTEND
3077   return sys_ftruncate(fd, len);
3078 #else
3079   SMB_STRUCT_STAT st;
3080   char c = 0;
3081   SMB_OFF_T currpos = sys_lseek(fd, (SMB_OFF_T)0, SEEK_CUR);
3082
3083   if(currpos < 0)
3084     return -1;
3085   /* Do an fstat to see if the file is longer than
3086      the requested size (call ftruncate),
3087      or shorter, in which case seek to len - 1 and write 1
3088      byte of zero */
3089   if(sys_fstat(fd, &st)<0)
3090     return -1;
3091
3092 #ifdef S_ISFIFO
3093   if (S_ISFIFO(st.st_mode)) return 0;
3094 #endif
3095
3096   if(st.st_size == len)
3097     return 0;
3098   if(st.st_size > len)
3099     return sys_ftruncate(fd, len);
3100
3101   if(sys_lseek(fd, len-1, SEEK_SET) != len -1)
3102     return -1;
3103   if(write(fd, &c, 1)!=1)
3104     return -1;
3105   /* Seek to where we were */
3106   sys_lseek(fd, currpos, SEEK_SET);
3107   return 0;
3108 #endif
3109 }
3110
3111
3112 #ifdef HPUX
3113 /****************************************************************************
3114 this is a version of setbuffer() for those machines that only have setvbuf
3115 ****************************************************************************/
3116  void setbuffer(FILE *f,char *buf,int bufsize)
3117 {
3118   setvbuf(f,buf,_IOFBF,bufsize);
3119 }
3120 #endif
3121
3122
3123 /****************************************************************************
3124 parse out a filename from a path name. Assumes dos style filenames.
3125 ****************************************************************************/
3126 static char *filename_dos(char *path,char *buf)
3127 {
3128   char *p = strrchr(path,'\\');
3129
3130   if (!p)
3131     pstrcpy(buf,path);
3132   else
3133     pstrcpy(buf,p+1);
3134
3135   return(buf);
3136 }
3137
3138
3139
3140 /****************************************************************************
3141 expand a pointer to be a particular size
3142 ****************************************************************************/
3143 void *Realloc(void *p,size_t size)
3144 {
3145   void *ret=NULL;
3146
3147   if (size == 0) {
3148     if (p) free(p);
3149     DEBUG(5,("Realloc asked for 0 bytes\n"));
3150     return NULL;
3151   }
3152
3153   if (!p)
3154     ret = (void *)malloc(size);
3155   else
3156     ret = (void *)realloc(p,size);
3157
3158   if (!ret)
3159     DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",size));
3160
3161   return(ret);
3162 }
3163
3164
3165 /****************************************************************************
3166 get my own name and IP
3167 ****************************************************************************/
3168 BOOL get_myname(char *my_name,struct in_addr *ip)
3169 {
3170   struct hostent *hp;
3171   pstring hostname;
3172
3173   *hostname = 0;
3174
3175   /* get my host name */
3176   if (gethostname(hostname, MAXHOSTNAMELEN) == -1) 
3177     {
3178       DEBUG(0,("gethostname failed\n"));
3179       return False;
3180     } 
3181
3182   /* get host info */
3183   if ((hp = Get_Hostbyname(hostname)) == 0) 
3184     {
3185       DEBUG(0,( "Get_Hostbyname: Unknown host %s\n",hostname));
3186       return False;
3187     }
3188
3189   if (my_name)
3190     {
3191       /* split off any parts after an initial . */
3192       char *p = strchr(hostname,'.');
3193       if (p) *p = 0;
3194
3195       fstrcpy(my_name,hostname);
3196     }
3197
3198   if (ip)
3199     putip((char *)ip,(char *)hp->h_addr);
3200
3201   return(True);
3202 }
3203
3204
3205 /****************************************************************************
3206 true if two IP addresses are equal
3207 ****************************************************************************/
3208 BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
3209 {
3210   uint32 a1,a2;
3211   a1 = ntohl(ip1.s_addr);
3212   a2 = ntohl(ip2.s_addr);
3213   return(a1 == a2);
3214 }
3215
3216
3217 /****************************************************************************
3218 open a socket of the specified type, port and address for incoming data
3219 ****************************************************************************/
3220 int open_socket_in(int type, int port, int dlevel,uint32 socket_addr)
3221 {
3222   struct hostent *hp;
3223   struct sockaddr_in sock;
3224   pstring host_name;
3225   int res;
3226
3227   /* get my host name */
3228   if (gethostname(host_name, MAXHOSTNAMELEN) == -1) 
3229     { DEBUG(0,("gethostname failed\n")); return -1; } 
3230
3231   /* get host info */
3232   if ((hp = Get_Hostbyname(host_name)) == 0) 
3233     {
3234       DEBUG(0,( "Get_Hostbyname: Unknown host %s\n",host_name));
3235       return -1;
3236     }
3237   
3238   bzero((char *)&sock,sizeof(sock));
3239   memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
3240
3241 #ifdef HAVE_SOCK_SIN_LEN
3242   sock.sin_len = sizeof(sock);
3243 #endif
3244   sock.sin_port = htons( port );
3245   sock.sin_family = hp->h_addrtype;
3246   sock.sin_addr.s_addr = socket_addr;
3247   res = socket(hp->h_addrtype, type, 0);
3248   if (res == -1) 
3249     { DEBUG(0,("socket failed\n")); return -1; }
3250
3251   {
3252     int one=1;
3253     setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
3254   }
3255
3256   /* now we've got a socket - we need to bind it */
3257   if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) 
3258     { 
3259       if (port) {
3260         if (port == SMB_PORT || port == NMB_PORT)
3261           DEBUG(dlevel,("bind failed on port %d socket_addr=%s (%s)\n",
3262                         port,inet_ntoa(sock.sin_addr),strerror(errno))); 
3263         close(res); 
3264
3265         if (dlevel > 0 && port < 1000)
3266           port = 7999;
3267
3268         if (port >= 1000 && port < 9000)
3269           return(open_socket_in(type,port+1,dlevel,socket_addr));
3270       }
3271
3272       return(-1); 
3273     }
3274   DEBUG(3,("bind succeeded on port %d\n",port));
3275
3276   return res;
3277 }
3278
3279
3280 /****************************************************************************
3281   create an outgoing socket
3282   **************************************************************************/
3283 int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
3284 {
3285   struct sockaddr_in sock_out;
3286   int res,ret;
3287   int connect_loop = 250; /* 250 milliseconds */
3288   int loops = (timeout * 1000) / connect_loop;
3289
3290   /* create a socket to write to */
3291   res = socket(PF_INET, type, 0);
3292   if (res == -1) 
3293     { DEBUG(0,("socket error\n")); return -1; }
3294
3295   if (type != SOCK_STREAM) return(res);
3296   
3297   bzero((char *)&sock_out,sizeof(sock_out));
3298   putip((char *)&sock_out.sin_addr,(char *)addr);
3299   
3300   sock_out.sin_port = htons( port );
3301   sock_out.sin_family = PF_INET;
3302
3303   /* set it non-blocking */
3304   set_blocking(res,False);
3305
3306   DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port));
3307   
3308   /* and connect it to the destination */
3309 connect_again:
3310   ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out));
3311
3312   /* Some systems return EAGAIN when they mean EINPROGRESS */
3313   if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
3314         errno == EAGAIN) && loops--) {
3315     msleep(connect_loop);
3316     goto connect_again;
3317   }
3318
3319   if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
3320          errno == EAGAIN)) {
3321       DEBUG(1,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port));
3322       close(res);
3323       return -1;
3324   }
3325
3326 #ifdef EISCONN
3327   if (ret < 0 && errno == EISCONN) {
3328     errno = 0;
3329     ret = 0;
3330   }
3331 #endif
3332
3333   if (ret < 0) {
3334     DEBUG(1,("error connecting to %s:%d (%s)\n",
3335              inet_ntoa(*addr),port,strerror(errno)));
3336     close(res);
3337     return -1;
3338   }
3339
3340   /* set it blocking again */
3341   set_blocking(res,True);
3342
3343   return res;
3344 }
3345
3346
3347 /****************************************************************************
3348 interpret a protocol description string, with a default
3349 ****************************************************************************/
3350 int interpret_protocol(char *str,int def)
3351 {
3352   if (strequal(str,"NT1"))
3353     return(PROTOCOL_NT1);
3354   if (strequal(str,"LANMAN2"))
3355     return(PROTOCOL_LANMAN2);
3356   if (strequal(str,"LANMAN1"))
3357     return(PROTOCOL_LANMAN1);
3358   if (strequal(str,"CORE"))
3359     return(PROTOCOL_CORE);
3360   if (strequal(str,"COREPLUS"))
3361     return(PROTOCOL_COREPLUS);
3362   if (strequal(str,"CORE+"))
3363     return(PROTOCOL_COREPLUS);
3364   
3365   DEBUG(0,("Unrecognised protocol level %s\n",str));
3366   
3367   return(def);
3368 }
3369
3370
3371 /****************************************************************************
3372 interpret an internet address or name into an IP address in 4 byte form
3373 ****************************************************************************/
3374 uint32 interpret_addr(char *str)
3375 {
3376   struct hostent *hp;
3377   uint32 res;
3378   int i;
3379   BOOL pure_address = True;
3380
3381   if (strcmp(str,"0.0.0.0") == 0) return(0);
3382   if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
3383
3384   for (i=0; pure_address && str[i]; i++)
3385     if (!(isdigit((int)str[i]) || str[i] == '.')) 
3386       pure_address = False;
3387
3388   /* if it's in the form of an IP address then get the lib to interpret it */
3389   if (pure_address) {
3390     res = inet_addr(str);
3391   } else {
3392     /* otherwise assume it's a network name of some sort and use 
3393        Get_Hostbyname */
3394     if ((hp = Get_Hostbyname(str)) == 0) {
3395       DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
3396       return 0;
3397     }
3398     if(hp->h_addr == NULL) {
3399       DEBUG(3,("Get_Hostbyname: host address is invalid for host %s\n",str));
3400       return 0;
3401     }
3402     putip((char *)&res,(char *)hp->h_addr);
3403   }
3404
3405   if (res == (uint32)-1) return(0);
3406
3407   return(res);
3408 }
3409
3410 /*******************************************************************
3411   a convenient addition to interpret_addr()
3412   ******************************************************************/
3413 struct in_addr *interpret_addr2(char *str)
3414 {
3415   static struct in_addr ret;
3416   uint32 a = interpret_addr(str);
3417   ret.s_addr = a;
3418   return(&ret);
3419 }
3420
3421 /*******************************************************************
3422   check if an IP is the 0.0.0.0
3423   ******************************************************************/
3424 BOOL zero_ip(struct in_addr ip)
3425 {
3426   uint32 a;
3427   putip((char *)&a,(char *)&ip);
3428   return(a == 0);
3429 }
3430
3431
3432 /*******************************************************************
3433  matchname - determine if host name matches IP address 
3434  ******************************************************************/
3435 static BOOL matchname(char *remotehost,struct in_addr  addr)
3436 {
3437   struct hostent *hp;
3438   int     i;
3439   
3440   if ((hp = Get_Hostbyname(remotehost)) == 0) {
3441     DEBUG(0,("Get_Hostbyname(%s): lookup failure", remotehost));
3442     return False;
3443   } 
3444
3445   /*
3446    * Make sure that gethostbyname() returns the "correct" host name.
3447    * Unfortunately, gethostbyname("localhost") sometimes yields
3448    * "localhost.domain". Since the latter host name comes from the
3449    * local DNS, we just have to trust it (all bets are off if the local
3450    * DNS is perverted). We always check the address list, though.
3451    */
3452   
3453   if (strcasecmp(remotehost, hp->h_name)
3454       && strcasecmp(remotehost, "localhost")) {
3455     DEBUG(0,("host name/name mismatch: %s != %s",
3456              remotehost, hp->h_name));
3457     return False;
3458   }
3459         
3460   /* Look up the host address in the address list we just got. */
3461   for (i = 0; hp->h_addr_list[i]; i++) {
3462     if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
3463       return True;
3464   }
3465
3466   /*
3467    * The host name does not map to the original host address. Perhaps
3468    * someone has compromised a name server. More likely someone botched
3469    * it, but that could be dangerous, too.
3470    */
3471   
3472   DEBUG(0,("host name/address mismatch: %s != %s",
3473            inet_ntoa(addr), hp->h_name));
3474   return False;
3475 }
3476
3477 /*******************************************************************
3478  Reset the 'done' variables so after a client process is created
3479  from a fork call these calls will be re-done. This should be
3480  expanded if more variables need reseting.
3481  ******************************************************************/
3482
3483 static BOOL global_client_name_done = False;
3484 static BOOL global_client_addr_done = False;
3485
3486 void reset_globals_after_fork(void)
3487 {
3488   global_client_name_done = False;
3489   global_client_addr_done = False;
3490
3491   /*
3492    * Re-seed the random crypto generator, so all smbd's
3493    * started from the same parent won't generate the same
3494    * sequence.
3495    */
3496   {
3497     unsigned char dummy;
3498     generate_random_buffer( &dummy, 1, True);
3499   } 
3500 }
3501  
3502 /*******************************************************************
3503  return the DNS name of the client 
3504  ******************************************************************/
3505 char *client_name(int fd)
3506 {
3507         struct sockaddr sa;
3508         struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
3509         int     length = sizeof(sa);
3510         static pstring name_buf;
3511         struct hostent *hp;
3512         static int last_fd=-1;
3513         
3514         if (global_client_name_done && last_fd == fd) 
3515                 return name_buf;
3516         
3517         last_fd = fd;
3518         global_client_name_done = False;
3519         
3520         pstrcpy(name_buf,"UNKNOWN");
3521         
3522         if (fd == -1) {
3523                 return name_buf;
3524         }
3525         
3526         if (getpeername(fd, &sa, &length) < 0) {
3527                 DEBUG(0,("getpeername failed\n"));
3528                 return name_buf;
3529         }
3530         
3531         /* Look up the remote host name. */
3532         if ((hp = gethostbyaddr((char *) &sockin->sin_addr,
3533                                 sizeof(sockin->sin_addr),
3534                                 AF_INET)) == 0) {
3535                 DEBUG(1,("Gethostbyaddr failed for %s\n",client_addr(fd)));
3536                 StrnCpy(name_buf,client_addr(fd),sizeof(name_buf) - 1);
3537         } else {
3538                 StrnCpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1);
3539                 if (!matchname(name_buf, sockin->sin_addr)) {
3540                         DEBUG(0,("Matchname failed on %s %s\n",name_buf,client_addr(fd)));
3541                         pstrcpy(name_buf,"UNKNOWN");
3542                 }
3543         }
3544         global_client_name_done = True;
3545         return name_buf;
3546 }
3547
3548 /*******************************************************************
3549  return the IP addr of the client as a string 
3550  ******************************************************************/
3551 char *client_addr(int fd)
3552 {
3553         struct sockaddr sa;
3554         struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
3555         int     length = sizeof(sa);
3556         static fstring addr_buf;
3557         static int last_fd = -1;
3558
3559         if (global_client_addr_done && fd == last_fd) 
3560                 return addr_buf;
3561
3562         last_fd = fd;
3563         global_client_addr_done = False;
3564
3565         fstrcpy(addr_buf,"0.0.0.0");
3566
3567         if (fd == -1) {
3568                 return addr_buf;
3569         }
3570         
3571         if (getpeername(fd, &sa, &length) < 0) {
3572                 DEBUG(0,("getpeername failed\n"));
3573                 return addr_buf;
3574         }
3575         
3576         fstrcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr));
3577         
3578         global_client_addr_done = True;
3579         return addr_buf;
3580 }
3581
3582 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
3583 /******************************************************************
3584  Remove any mount options such as -rsize=2048,wsize=2048 etc.
3585  Based on a fix from <Thomas.Hepper@icem.de>.
3586 *******************************************************************/
3587
3588 static void strip_mount_options( pstring *str)
3589 {
3590   if (**str == '-')
3591   { 
3592     char *p = *str;
3593     while(*p && !isspace(*p))
3594       p++;
3595     while(*p && isspace(*p))
3596       p++;
3597     if(*p) {
3598       pstring tmp_str;
3599
3600       pstrcpy(tmp_str, p);
3601       pstrcpy(*str, tmp_str);
3602     }
3603   }
3604 }
3605
3606 /*******************************************************************
3607  Patch from jkf@soton.ac.uk
3608  Split Luke's automount_server into YP lookup and string splitter
3609  so can easily implement automount_path(). 
3610  As we may end up doing both, cache the last YP result. 
3611 *******************************************************************/
3612
3613 #ifdef WITH_NISPLUS_HOME
3614 static char *automount_lookup(char *user_name)
3615 {
3616   static fstring last_key = "";
3617   static pstring last_value = "";
3618  
3619   char *nis_map = (char *)lp_nis_home_map_name();
3620  
3621   char nis_domain[NIS_MAXNAMELEN + 1];
3622   char buffer[NIS_MAXATTRVAL + 1];
3623   nis_result *result;
3624   nis_object *object;
3625   entry_obj  *entry;
3626  
3627   strncpy(nis_domain, (char *)nis_local_directory(), NIS_MAXNAMELEN);
3628   nis_domain[NIS_MAXNAMELEN] = '\0';
3629  
3630   DEBUG(5, ("NIS+ Domain: %s\n", nis_domain));
3631  
3632   if (strcmp(user_name, last_key))
3633   {
3634     slprintf(buffer, sizeof(buffer)-1, "[%s=%s]%s.%s", "key", user_name, nis_map, nis_domain);
3635     DEBUG(5, ("NIS+ querystring: %s\n", buffer));
3636  
3637     if (result = nis_list(buffer, RETURN_RESULT, NULL, NULL))
3638     {
3639        if (result->status != NIS_SUCCESS)
3640       {
3641         DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
3642         fstrcpy(last_key, ""); pstrcpy(last_value, "");
3643       }
3644       else
3645       {
3646         object = result->objects.objects_val;
3647         if (object->zo_data.zo_type == ENTRY_OBJ)
3648         {
3649            entry = &object->zo_data.objdata_u.en_data;
3650            DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
3651            DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
3652  
3653            pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
3654            string_sub(last_value, "&", user_name);
3655            fstrcpy(last_key, user_name);
3656         }
3657       }
3658     }
3659     nis_freeresult(result);
3660   }
3661
3662   strip_mount_options(&last_value);
3663
3664   DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
3665   return last_value;
3666 }
3667 #else /* WITH_NISPLUS_HOME */
3668 static char *automount_lookup(char *user_name)
3669 {
3670   static fstring last_key = "";
3671   static pstring last_value = "";
3672
3673   int nis_error;        /* returned by yp all functions */
3674   char *nis_result;     /* yp_match inits this */
3675   int nis_result_len;  /* and set this */
3676   char *nis_domain;     /* yp_get_default_domain inits this */
3677   char *nis_map = (char *)lp_nis_home_map_name();
3678
3679   if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
3680   {
3681     DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
3682     return last_value;
3683   }
3684
3685   DEBUG(5, ("NIS Domain: %s\n", nis_domain));
3686
3687   if (!strcmp(user_name, last_key))
3688   {
3689     nis_result = last_value;
3690     nis_result_len = strlen(last_value);
3691     nis_error = 0;
3692   }
3693   else
3694   {
3695     if ((nis_error = yp_match(nis_domain, nis_map,
3696                               user_name, strlen(user_name),
3697                               &nis_result, &nis_result_len)) != 0)
3698     {
3699       DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n", 
3700                yperr_string(nis_error), user_name, nis_map));
3701     }
3702     if (!nis_error && nis_result_len >= sizeof(pstring))
3703     {
3704       nis_result_len = sizeof(pstring)-1;
3705     }
3706     fstrcpy(last_key, user_name);
3707     strncpy(last_value, nis_result, nis_result_len);
3708     last_value[nis_result_len] = '\0';
3709   }
3710
3711   strip_mount_options(&last_value);
3712
3713   DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
3714   return last_value;
3715 }
3716 #endif /* WITH_NISPLUS_HOME */
3717 #endif
3718
3719 /*******************************************************************
3720  Patch from jkf@soton.ac.uk
3721  This is Luke's original function with the NIS lookup code
3722  moved out to a separate function.
3723 *******************************************************************/
3724 static char *automount_server(char *user_name)
3725 {
3726         static pstring server_name;
3727
3728         /* use the local machine name as the default */
3729         /* this will be the default if WITH_AUTOMOUNT is not used or fails */
3730         pstrcpy(server_name, local_machine);
3731
3732 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
3733
3734         if (lp_nis_home_map())
3735         {
3736                 int home_server_len;
3737                 char *automount_value = automount_lookup(user_name);
3738                 home_server_len = strcspn(automount_value,":");
3739                 DEBUG(5, ("NIS lookup succeeded.  Home server length: %d\n",home_server_len));
3740                 if (home_server_len > sizeof(pstring))
3741                 {
3742                         home_server_len = sizeof(pstring);
3743                 }
3744                 strncpy(server_name, automount_value, home_server_len);
3745                 server_name[home_server_len] = '\0';
3746         }
3747 #endif
3748
3749         DEBUG(4,("Home server: %s\n", server_name));
3750
3751         return server_name;
3752 }
3753
3754 /*******************************************************************
3755  Patch from jkf@soton.ac.uk
3756  Added this to implement %p (NIS auto-map version of %H)
3757 *******************************************************************/
3758 static char *automount_path(char *user_name)
3759 {
3760         static pstring server_path;
3761
3762         /* use the passwd entry as the default */
3763         /* this will be the default if WITH_AUTOMOUNT is not used or fails */
3764         /* pstrcpy() copes with get_home_dir() returning NULL */
3765         pstrcpy(server_path, get_home_dir(user_name));
3766
3767 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
3768
3769         if (lp_nis_home_map())
3770         {
3771                 char *home_path_start;
3772                 char *automount_value = automount_lookup(user_name);
3773                 home_path_start = strchr(automount_value,':');
3774                 if (home_path_start != NULL)
3775                 {
3776                   DEBUG(5, ("NIS lookup succeeded.  Home path is: %s\n",
3777                         home_path_start?(home_path_start+1):""));
3778                   pstrcpy(server_path, home_path_start+1);
3779                 }
3780         }
3781 #endif
3782
3783         DEBUG(4,("Home server path: %s\n", server_path));
3784
3785         return server_path;
3786 }
3787
3788
3789 /*******************************************************************
3790 sub strings with useful parameters
3791 Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
3792 Paul Rippin <pr3245@nopc.eurostat.cec.be>
3793 ********************************************************************/
3794 void standard_sub_basic(char *str)
3795 {
3796         char *s, *p;
3797         char pidstr[10];
3798         struct passwd *pass;
3799         char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user;
3800
3801         for (s = str ; s && *s && (p = strchr(s,'%')); s = p )
3802         {
3803                 switch (*(p+1))
3804                 {
3805                         case 'G' :
3806                         {
3807                                 if ((pass = Get_Pwnam(username,False))!=NULL)
3808                                 {
3809                                         string_sub(p,"%G",gidtoname(pass->pw_gid));
3810                                 }
3811                                 else
3812                                 {
3813                                         p += 2;
3814                                 }
3815                                 break;
3816                         }
3817                         case 'N' : string_sub(p,"%N", automount_server(username)); break;
3818                         case 'I' : string_sub(p,"%I", client_addr(Client)); break;
3819                         case 'L' : string_sub(p,"%L", local_machine); break;
3820                         case 'M' : string_sub(p,"%M", client_name(Client)); break;
3821                         case 'R' : string_sub(p,"%R", remote_proto); break;
3822                         case 'T' : string_sub(p,"%T", timestring()); break;
3823                         case 'U' : string_sub(p,"%U", username); break;
3824                         case 'a' : string_sub(p,"%a", remote_arch); break;
3825                         case 'd' :
3826                         {
3827                                 slprintf(pidstr,sizeof(pidstr) - 1, "%d",(int)getpid());
3828                                 string_sub(p,"%d", pidstr);
3829                                 break;
3830                         }
3831                         case 'h' : string_sub(p,"%h", myhostname); break;
3832                         case 'm' : string_sub(p,"%m", remote_machine); break;
3833                         case 'v' : string_sub(p,"%v", VERSION); break;
3834                         case '$' : /* Expand environment variables */
3835                         {
3836                                 /* Contributed by Branko Cibej <branko.cibej@hermes.si> */
3837                                 fstring envname;
3838                                 char *envval;
3839                                 char *q, *r;
3840                                 int copylen;
3841
3842                                 if (*(p+2) != '(')
3843                                 {
3844                                         p+=2;
3845                                         break;
3846                                 }
3847                                 if ((q = strchr(p,')')) == NULL)
3848                                 {
3849                                         DEBUG(0,("standard_sub_basic: Unterminated environment \
3850                                         variable [%s]\n", p));
3851                                         p+=2;
3852                                         break;
3853                                 }
3854
3855                                 r = p+3;
3856                                 copylen = MIN((q-r),(sizeof(envname)-1));
3857                                 strncpy(envname,r,copylen);
3858                                 envname[copylen] = '\0';
3859
3860                                 if ((envval = getenv(envname)) == NULL)
3861                                 {
3862                                         DEBUG(0,("standard_sub_basic: Environment variable [%s] not set\n",
3863                                         envname));
3864                                         p+=2;
3865                                         break;
3866                                 }
3867
3868                                 copylen = MIN((q+1-p),(sizeof(envname)-1));
3869                                 strncpy(envname,p,copylen);
3870                                 envname[copylen] = '\0';
3871                                 string_sub(p,envname,envval);
3872                                 break;
3873                         }
3874                         case '\0': p++; break; /* don't run off end if last character is % */
3875                         default  : p+=2; break;
3876                 }
3877         }
3878         return;
3879 }
3880
3881
3882 /****************************************************************************
3883 do some standard substitutions in a string
3884 ****************************************************************************/
3885 void standard_sub(connection_struct *conn,char *str)
3886 {
3887         char *p, *s, *home;
3888
3889         for (s=str; (p=strchr(s, '%'));s=p) {
3890                 switch (*(p+1)) {
3891                 case 'H': 
3892                         if ((home = get_home_dir(conn->user))) {
3893                                 string_sub(p,"%H",home);
3894                         } else {
3895                                 p += 2;
3896                         }
3897                         break;
3898                         
3899                 case 'P': 
3900                         string_sub(p,"%P",conn->connectpath); 
3901                         break;
3902                         
3903                 case 'S': 
3904                         string_sub(p,"%S",
3905                                    lp_servicename(SNUM(conn))); 
3906                         break;
3907                         
3908                 case 'g': 
3909                         string_sub(p,"%g",
3910                                    gidtoname(conn->gid)); 
3911                         break;
3912                 case 'u': 
3913                         string_sub(p,"%u",conn->user); 
3914                         break;
3915                         
3916                         /* Patch from jkf@soton.ac.uk Left the %N (NIS
3917                          * server name) in standard_sub_basic as it is
3918                          * a feature for logon servers, hence uses the
3919                          * username.  The %p (NIS server path) code is
3920                          * here as it is used instead of the default
3921                          * "path =" string in [homes] and so needs the
3922                          * service name, not the username.  */
3923                 case 'p': 
3924                         string_sub(p,"%p",
3925                                    automount_path(lp_servicename(SNUM(conn)))); 
3926                         break;
3927                 case '\0': 
3928                         p++; 
3929                         break; /* don't run off the end of the string 
3930                                 */
3931                         
3932                 default: p+=2; 
3933                         break;
3934                 }
3935         }
3936         
3937         standard_sub_basic(str);
3938 }
3939
3940
3941
3942 /*******************************************************************
3943 are two IPs on the same subnet?
3944 ********************************************************************/
3945 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
3946 {
3947   uint32 net1,net2,nmask;
3948
3949   nmask = ntohl(mask.s_addr);
3950   net1  = ntohl(ip1.s_addr);
3951   net2  = ntohl(ip2.s_addr);
3952             
3953   return((net1 & nmask) == (net2 & nmask));
3954 }
3955
3956
3957 /*******************************************************************
3958 write a string in unicoode format
3959 ********************************************************************/
3960 int PutUniCode(char *dst,char *src)
3961 {
3962   int ret = 0;
3963   while (*src) {
3964     dst[ret++] = src[0];
3965     dst[ret++] = 0;    
3966     src++;
3967   }
3968   dst[ret++]=0;
3969   dst[ret++]=0;
3970   return(ret);
3971 }
3972
3973 /****************************************************************************
3974 a wrapper for gethostbyname() that tries with all lower and all upper case 
3975 if the initial name fails
3976 ****************************************************************************/
3977 struct hostent *Get_Hostbyname(char *name)
3978 {
3979   char *name2 = strdup(name);
3980   struct hostent *ret;
3981
3982   if (!name2)
3983     {
3984       DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
3985       exit(0);
3986     }
3987
3988    
3989   /* 
3990    * This next test is redundent and causes some systems (with
3991    * broken isalnum() calls) problems.
3992    * JRA.
3993    */
3994
3995 #if 0
3996   if (!isalnum(*name2))
3997     {
3998       free(name2);
3999       return(NULL);
4000     }
4001 #endif /* 0 */
4002
4003   ret = sys_gethostbyname(name2);
4004   if (ret != NULL)
4005     {
4006       free(name2);
4007       return(ret);
4008     }
4009
4010   /* try with all lowercase */
4011   strlower(name2);
4012   ret = sys_gethostbyname(name2);
4013   if (ret != NULL)
4014     {
4015       free(name2);
4016       return(ret);
4017     }
4018
4019   /* try with all uppercase */
4020   strupper(name2);
4021   ret = sys_gethostbyname(name2);
4022   if (ret != NULL)
4023     {
4024       free(name2);
4025       return(ret);
4026     }
4027   
4028   /* nothing works :-( */
4029   free(name2);
4030   return(NULL);
4031 }
4032
4033
4034 /****************************************************************************
4035 check if a process exists. Does this work on all unixes?
4036 ****************************************************************************/
4037
4038 BOOL process_exists(int pid)
4039 {
4040         return(kill(pid,0) == 0 || errno != ESRCH);
4041 }
4042
4043
4044 /*******************************************************************
4045 turn a uid into a user name
4046 ********************************************************************/
4047 char *uidtoname(uid_t uid)
4048 {
4049   static char name[40];
4050   struct passwd *pass = getpwuid(uid);
4051   if (pass) return(pass->pw_name);
4052   slprintf(name, sizeof(name) - 1, "%d",(int)uid);
4053   return(name);
4054 }
4055
4056
4057 /*******************************************************************
4058 turn a gid into a group name
4059 ********************************************************************/
4060
4061 char *gidtoname(gid_t gid)
4062 {
4063         static char name[40];
4064         struct group *grp = getgrgid(gid);
4065         if (grp) return(grp->gr_name);
4066         slprintf(name,sizeof(name) - 1, "%d",(int)gid);
4067         return(name);
4068 }
4069
4070 /*******************************************************************
4071 turn a user name into a uid
4072 ********************************************************************/
4073 uid_t nametouid(const char *name)
4074 {
4075         struct passwd *pass = getpwnam(name);
4076         if (pass) return(pass->pw_uid);
4077         return (uid_t)-1;
4078 }
4079
4080 /*******************************************************************
4081 something really nasty happened - panic!
4082 ********************************************************************/
4083 void smb_panic(char *why)
4084 {
4085         char *cmd = lp_panic_action();
4086         if (cmd && *cmd) {
4087                 system(cmd);
4088         }
4089         DEBUG(0,("PANIC: %s\n", why));
4090         exit(1);
4091 }
4092
4093
4094 /*******************************************************************
4095 a readdir wrapper which just returns the file name
4096 ********************************************************************/
4097 char *readdirname(void *p)
4098 {
4099         struct dirent *ptr;
4100         char *dname;
4101
4102         if (!p) return(NULL);
4103   
4104         ptr = (struct dirent *)readdir(p);
4105         if (!ptr) return(NULL);
4106
4107         dname = ptr->d_name;
4108
4109 #ifdef NEXT2
4110         if (telldir(p) < 0) return(NULL);
4111 #endif
4112
4113 #ifdef HAVE_BROKEN_READDIR
4114         /* using /usr/ucb/cc is BAD */
4115         dname = dname - 2;
4116 #endif
4117
4118         {
4119                 static pstring buf;
4120                 memcpy(buf, dname, NAMLEN(ptr)+1);
4121                 unix_to_dos(buf, True);
4122                 dname = buf;
4123         }
4124
4125         return(dname);
4126 }
4127
4128 /*******************************************************************
4129  Utility function used to decide if the last component 
4130  of a path matches a (possibly wildcarded) entry in a namelist.
4131 ********************************************************************/
4132
4133 BOOL is_in_path(char *name, name_compare_entry *namelist)
4134 {
4135   pstring last_component;
4136   char *p;
4137
4138   DEBUG(8, ("is_in_path: %s\n", name));
4139
4140   /* if we have no list it's obviously not in the path */
4141   if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) 
4142   {
4143     DEBUG(8,("is_in_path: no name list.\n"));
4144     return False;
4145   }
4146
4147   /* Get the last component of the unix name. */
4148   p = strrchr(name, '/');
4149   strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
4150   last_component[sizeof(last_component)-1] = '\0'; 
4151
4152   for(; namelist->name != NULL; namelist++)
4153   {
4154     if(namelist->is_wild)
4155     {
4156       /* 
4157        * Look for a wildcard match. Use the old
4158        * 'unix style' mask match, rather than the
4159        * new NT one.
4160        */
4161       if (unix_mask_match(last_component, namelist->name, case_sensitive, False))
4162       {
4163          DEBUG(8,("is_in_path: mask match succeeded\n"));
4164          return True;
4165       }
4166     }
4167     else
4168     {
4169       if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
4170        (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0)))
4171         {
4172          DEBUG(8,("is_in_path: match succeeded\n"));
4173          return True;
4174         }
4175     }
4176   }
4177   DEBUG(8,("is_in_path: match not found\n"));
4178  
4179   return False;
4180 }
4181
4182 /*******************************************************************
4183  Strip a '/' separated list into an array of 
4184  name_compare_enties structures suitable for 
4185  passing to is_in_path(). We do this for
4186  speed so we can pre-parse all the names in the list 
4187  and don't do it for each call to is_in_path().
4188  namelist is modified here and is assumed to be 
4189  a copy owned by the caller.
4190  We also check if the entry contains a wildcard to
4191  remove a potentially expensive call to mask_match
4192  if possible.
4193 ********************************************************************/
4194  
4195 void set_namearray(name_compare_entry **ppname_array, char *namelist)
4196 {
4197   char *name_end;
4198   char *nameptr = namelist;
4199   int num_entries = 0;
4200   int i;
4201
4202   (*ppname_array) = NULL;
4203
4204   if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0'))) 
4205     return;
4206
4207   /* We need to make two passes over the string. The
4208      first to count the number of elements, the second
4209      to split it.
4210    */
4211   while(*nameptr) 
4212     {
4213       if ( *nameptr == '/' ) 
4214         {
4215           /* cope with multiple (useless) /s) */
4216           nameptr++;
4217           continue;
4218         }
4219       /* find the next / */
4220       name_end = strchr(nameptr, '/');
4221
4222       /* oops - the last check for a / didn't find one. */
4223       if (name_end == NULL)
4224         break;
4225
4226       /* next segment please */
4227       nameptr = name_end + 1;
4228       num_entries++;
4229     }
4230
4231   if(num_entries == 0)
4232     return;
4233
4234   if(( (*ppname_array) = (name_compare_entry *)malloc( 
4235            (num_entries + 1) * sizeof(name_compare_entry))) == NULL)
4236         {
4237     DEBUG(0,("set_namearray: malloc fail\n"));
4238     return;
4239         }
4240
4241   /* Now copy out the names */
4242   nameptr = namelist;
4243   i = 0;
4244   while(*nameptr)
4245              {
4246       if ( *nameptr == '/' ) 
4247       {
4248           /* cope with multiple (useless) /s) */
4249           nameptr++;
4250           continue;
4251       }
4252       /* find the next / */
4253       if ((name_end = strchr(nameptr, '/')) != NULL) 
4254       {
4255           *name_end = 0;
4256          }
4257
4258       /* oops - the last check for a / didn't find one. */
4259       if(name_end == NULL) 
4260         break;
4261
4262       (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
4263                                 (strchr( nameptr, '*')!=NULL));
4264       if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
4265       {
4266         DEBUG(0,("set_namearray: malloc fail (1)\n"));
4267         return;
4268       }
4269
4270       /* next segment please */
4271       nameptr = name_end + 1;
4272       i++;
4273     }
4274   
4275   (*ppname_array)[i].name = NULL;
4276
4277   return;
4278 }
4279
4280 /****************************************************************************
4281 routine to free a namearray.
4282 ****************************************************************************/
4283
4284 void free_namearray(name_compare_entry *name_array)
4285 {
4286   if(name_array == 0)
4287     return;
4288
4289   if(name_array->name != NULL)
4290     free(name_array->name);
4291
4292   free((char *)name_array);
4293 }
4294
4295 /****************************************************************************
4296 routine to do file locking
4297 ****************************************************************************/
4298 BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
4299 {
4300 #if HAVE_FCNTL_LOCK
4301   SMB_STRUCT_FLOCK lock;
4302   int ret;
4303
4304   if(lp_ole_locking_compat()) {
4305     SMB_OFF_T mask = ((SMB_OFF_T)0xC) << (SMB_OFF_T_BITS-4);
4306     SMB_OFF_T mask2= ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4);
4307
4308     /* make sure the count is reasonable, we might kill the lockd otherwise */
4309     count &= ~mask;
4310
4311     /* the offset is often strange - remove 2 of its bits if either of
4312        the top two bits are set. Shift the top ones by two bits. This
4313        still allows OLE2 apps to operate, but should stop lockd from
4314        dieing */
4315     if ((offset & mask) != 0)
4316       offset = (offset & ~mask) | (((offset & mask) >> 2) & mask2);
4317   } else {
4318     SMB_OFF_T mask = ((SMB_OFF_T)0x8) << (SMB_OFF_T_BITS-4);
4319     SMB_OFF_T neg_mask = ~mask;
4320
4321     /* interpret negative counts as large numbers */
4322     if (count < 0)
4323       count &= ~mask;
4324
4325     /* no negative offsets */
4326     if(offset < 0)
4327       offset &= ~mask;
4328
4329     /* count + offset must be in range */
4330     while ((offset < 0 || (offset + count < 0)) && mask)
4331     {
4332       offset &= ~mask;
4333       mask = ((mask >> 1) & neg_mask);
4334     }
4335   }
4336
4337   DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
4338
4339   lock.l_type = type;
4340   lock.l_whence = SEEK_SET;
4341   lock.l_start = offset;
4342   lock.l_len = count;
4343   lock.l_pid = 0;
4344
4345   errno = 0;
4346
4347   ret = fcntl(fd,op,&lock);
4348   if (errno == EFBIG)
4349   {
4350     if( DEBUGLVL( 0 ))
4351     {
4352       dbgtext("fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count);
4353       dbgtext("a 'file too large' error. This can happen when using 64 bit lock offsets\n");
4354       dbgtext("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n");
4355     }
4356     /* 32 bit NFS file system, retry with smaller offset */
4357     errno = 0;
4358     lock.l_len = count & 0xffffffff;
4359     ret = fcntl(fd,op,&lock);
4360   }
4361
4362   if (errno != 0)
4363     DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
4364
4365   /* a lock query */
4366   if (op == SMB_F_GETLK)
4367   {
4368     if ((ret != -1) &&
4369         (lock.l_type != F_UNLCK) && 
4370         (lock.l_pid != 0) && 
4371         (lock.l_pid != getpid()))
4372     {
4373       DEBUG(3,("fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
4374       return(True);
4375     }
4376
4377     /* it must be not locked or locked by me */
4378     return(False);
4379   }
4380
4381   /* a lock set or unset */
4382   if (ret == -1)
4383   {
4384     DEBUG(3,("lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
4385           (double)offset,(double)count,op,type,strerror(errno)));
4386
4387     /* perhaps it doesn't support this sort of locking?? */
4388     if (errno == EINVAL)
4389     {
4390       DEBUG(3,("locking not supported? returning True\n"));
4391       return(True);
4392     }
4393
4394     return(False);
4395   }
4396
4397   /* everything went OK */
4398   DEBUG(8,("Lock call successful\n"));
4399
4400   return(True);
4401 #else
4402   return(False);
4403 #endif
4404 }
4405
4406 /*******************************************************************
4407 is the name specified one of my netbios names
4408 returns true is it is equal, false otherwise
4409 ********************************************************************/
4410 BOOL is_myname(char *s)
4411 {
4412   int n;
4413   BOOL ret = False;
4414
4415   for (n=0; my_netbios_names[n]; n++) {
4416     if (strequal(my_netbios_names[n], s))
4417       ret=True;
4418   }
4419   DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
4420   return(ret);
4421 }
4422
4423 /*******************************************************************
4424 set the horrid remote_arch string based on an enum.
4425 ********************************************************************/
4426 void set_remote_arch(enum remote_arch_types type)
4427 {
4428   ra_type = type;
4429   switch( type )
4430   {
4431   case RA_WFWG:
4432     fstrcpy(remote_arch, "WfWg");
4433     return;
4434   case RA_OS2:
4435     fstrcpy(remote_arch, "OS2");
4436     return;
4437   case RA_WIN95:
4438     fstrcpy(remote_arch, "Win95");
4439     return;
4440   case RA_WINNT:
4441     fstrcpy(remote_arch, "WinNT");
4442     return;
4443   case RA_SAMBA:
4444     fstrcpy(remote_arch,"Samba");
4445     return;
4446   default:
4447     ra_type = RA_UNKNOWN;
4448     fstrcpy(remote_arch, "UNKNOWN");
4449     break;
4450   }
4451 }
4452
4453 /*******************************************************************
4454  Get the remote_arch type.
4455 ********************************************************************/
4456 enum remote_arch_types get_remote_arch(void)
4457 {
4458   return ra_type;
4459 }
4460
4461
4462 /*******************************************************************
4463 skip past some unicode strings in a buffer
4464 ********************************************************************/
4465 char *skip_unicode_string(char *buf,int n)
4466 {
4467   while (n--)
4468   {
4469     while (*buf)
4470       buf += 2;
4471     buf += 2;
4472   }
4473   return(buf);
4474 }
4475
4476 /*******************************************************************
4477 Return a ascii version of a unicode string
4478 Hack alert: uses fixed buffer(s) and only handles ascii strings
4479 ********************************************************************/
4480 #define MAXUNI 1024
4481 char *unistrn2(uint16 *buf, int len)
4482 {
4483         static char lbufs[8][MAXUNI];
4484         static int nexti;
4485         char *lbuf = lbufs[nexti];
4486         char *p;
4487
4488         nexti = (nexti+1)%8;
4489
4490         DEBUG(10, ("unistrn2: "));
4491
4492         for (p = lbuf; *buf && p-lbuf < MAXUNI-2 && len > 0; len--, p++, buf++)
4493         {
4494                 DEBUG(10, ("%4x ", *buf));
4495                 *p = *buf;
4496         }
4497
4498         DEBUG(10,("\n"));
4499
4500         *p = 0;
4501         return lbuf;
4502 }
4503
4504 /*******************************************************************
4505 Return a ascii version of a unicode string
4506 Hack alert: uses fixed buffer(s) and only handles ascii strings
4507 ********************************************************************/
4508 #define MAXUNI 1024
4509 char *unistr2(uint16 *buf)
4510 {
4511         static char lbufs[8][MAXUNI];
4512         static int nexti;
4513         char *lbuf = lbufs[nexti];
4514         char *p;
4515
4516         nexti = (nexti+1)%8;
4517
4518         DEBUG(10, ("unistr2: "));
4519
4520         for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf++)
4521         {
4522                 DEBUG(10, ("%4x ", *buf));
4523                 *p = *buf;
4524         }
4525
4526         DEBUG(10,("\n"));
4527
4528         *p = 0;
4529         return lbuf;
4530 }
4531
4532 /*******************************************************************
4533 create a null-terminated unicode string from a null-terminated ascii string.
4534 return number of unicode chars copied, excluding the null character.
4535
4536 only handles ascii strings
4537 ********************************************************************/
4538 #define MAXUNI 1024
4539 int struni2(uint16 *p, char *buf)
4540 {
4541         int len = 0;
4542
4543         if (p == NULL) return 0;
4544
4545         DEBUG(10, ("struni2: "));
4546
4547         if (buf != NULL)
4548         {
4549                 for (; *buf && len < MAXUNI-2; len++, p++, buf++)
4550                 {
4551                         DEBUG(10, ("%2x ", *buf));
4552                         *p = *buf;
4553                 }
4554
4555                 DEBUG(10,("\n"));
4556         }
4557
4558         *p = 0;
4559
4560         return len;
4561 }
4562
4563 /*******************************************************************
4564 Return a ascii version of a unicode string
4565 Hack alert: uses fixed buffer(s) and only handles ascii strings
4566 ********************************************************************/
4567 #define MAXUNI 1024
4568 char *unistr(char *buf)
4569 {
4570         static char lbufs[8][MAXUNI];
4571         static int nexti;
4572         char *lbuf = lbufs[nexti];
4573         char *p;
4574
4575         nexti = (nexti+1)%8;
4576
4577         for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf += 2)
4578         {
4579                 *p = *buf;
4580         }
4581         *p = 0;
4582         return lbuf;
4583 }
4584
4585
4586 /*******************************************************************
4587 strcpy for unicode strings.  returns length (in num of wide chars)
4588 ********************************************************************/
4589 int unistrcpy(char *dst, char *src)
4590 {
4591         int num_wchars = 0;
4592
4593         while (*src)
4594         {
4595                 *dst++ = *src++;
4596                 *dst++ = *src++;
4597                 num_wchars++;
4598         }
4599         *dst++ = 0;
4600         *dst++ = 0;
4601
4602         return num_wchars;
4603 }
4604
4605 /*******************************************************************
4606 safe string copy into a known length string. maxlength does not
4607 include the terminating zero.
4608 ********************************************************************/
4609 char *safe_strcpy(char *dest,const char *src, int maxlength)
4610 {
4611     int len;
4612
4613     if (!dest) {
4614         DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
4615         return NULL;
4616     }
4617
4618     if (!src) {
4619         *dest = 0;
4620         return dest;
4621     }  
4622
4623     len = strlen(src);
4624
4625     if (len > maxlength) {
4626             DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
4627                      len-maxlength, src));
4628             len = maxlength;
4629     }
4630       
4631     memcpy(dest, src, len);
4632     dest[len] = 0;
4633     return dest;
4634 }  
4635
4636 /*******************************************************************
4637 safe string cat into a string. maxlength does not
4638 include the terminating zero.
4639 ********************************************************************/
4640 char *safe_strcat(char *dest, char *src, int maxlength)
4641 {
4642     int src_len, dest_len;
4643
4644     if (!dest) {
4645         DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
4646         return NULL;
4647     }
4648
4649     if (!src) {
4650         return dest;
4651     }  
4652
4653     src_len = strlen(src);
4654     dest_len = strlen(dest);
4655
4656     if (src_len + dest_len > maxlength) {
4657             DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
4658                      src_len + dest_len - maxlength, src));
4659             src_len = maxlength - dest_len;
4660     }
4661       
4662     memcpy(&dest[dest_len], src, src_len);
4663     dest[dest_len + src_len] = 0;
4664     return dest;
4665 }
4666
4667 /*******************************************************************
4668 align a pointer to a multiple of 2 bytes
4669 ********************************************************************/
4670 char *align2(char *q, char *base)
4671 {
4672         if ((q - base) & 1)
4673         {
4674                 q++;
4675         }
4676         return q;
4677 }
4678
4679 void print_asc(int level, unsigned char *buf,int len)
4680 {
4681         int i;
4682         for (i=0;i<len;i++)
4683                 DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
4684 }
4685
4686 void dump_data(int level,char *buf1,int len)
4687 {
4688   unsigned char *buf = (unsigned char *)buf1;
4689   int i=0;
4690   if (len<=0) return;
4691
4692   DEBUG(level,("[%03X] ",i));
4693   for (i=0;i<len;) {
4694     DEBUG(level,("%02X ",(int)buf[i]));
4695     i++;
4696     if (i%8 == 0) DEBUG(level,(" "));
4697     if (i%16 == 0) {      
4698       print_asc(level,&buf[i-16],8); DEBUG(level,(" "));
4699       print_asc(level,&buf[i-8],8); DEBUG(level,("\n"));
4700       if (i<len) DEBUG(level,("[%03X] ",i));
4701     }
4702   }
4703   if (i%16) {
4704     int n;
4705
4706     n = 16 - (i%16);
4707     DEBUG(level,(" "));
4708     if (n>8) DEBUG(level,(" "));
4709     while (n--) DEBUG(level,("   "));
4710
4711     n = MIN(8,i%16);
4712     print_asc(level,&buf[i-(i%16)],n); DEBUG(level,(" "));
4713     n = (i%16) - n;
4714     if (n>0) print_asc(level,&buf[i-n],n); 
4715     DEBUG(level,("\n"));    
4716   }
4717 }
4718
4719 char *tab_depth(int depth)
4720 {
4721         static pstring spaces;
4722         memset(spaces, ' ', depth * 4);
4723         spaces[depth * 4] = 0;
4724         return spaces;
4725 }
4726
4727 /*****************************************************************
4728  Convert a SID to an ascii string.
4729 *****************************************************************/
4730
4731 char *sid_to_string(pstring sidstr_out, DOM_SID *sid)
4732 {
4733   char subauth[16];
4734   int i;
4735   /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
4736   uint32 ia = (sid->id_auth[5]) +
4737               (sid->id_auth[4] << 8 ) +
4738               (sid->id_auth[3] << 16) +
4739               (sid->id_auth[2] << 24);
4740
4741   slprintf(sidstr_out, sizeof(pstring) - 1, "S-%d-%d", sid->sid_rev_num, ia);
4742
4743   for (i = 0; i < sid->num_auths; i++)
4744   {
4745     slprintf(subauth, sizeof(subauth)-1, "-%d", sid->sub_auths[i]);
4746     pstrcat(sidstr_out, subauth);
4747   }
4748
4749   DEBUG(7,("sid_to_string returning %s\n", sidstr_out));
4750   return sidstr_out;
4751 }
4752
4753 /*****************************************************************
4754  Convert a string to a SID. Returns True on success, False on fail.
4755 *****************************************************************/  
4756    
4757 BOOL string_to_sid(DOM_SID *sidout, char *sidstr)
4758 {
4759   pstring tok;
4760   char *p = sidstr;
4761   /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
4762   uint32 ia;
4763
4764   memset((char *)sidout, '\0', sizeof(DOM_SID));
4765
4766   if(StrnCaseCmp( sidstr, "S-", 2)) {
4767     DEBUG(0,("string_to_sid: Sid %s does not start with 'S-'.\n", sidstr));
4768     return False;
4769   }
4770
4771   p += 2;
4772   if(!next_token(&p, tok, "-", sizeof(tok))) {
4773     DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr));
4774     return False;
4775   }
4776
4777   /* Get the revision number. */
4778   sidout->sid_rev_num = atoi(tok);
4779
4780   if(!next_token(&p, tok, "-", sizeof(tok))) {
4781     DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr));
4782     return False;
4783   }
4784
4785   /* identauth in decimal should be <  2^32 */
4786   ia = atoi(tok);
4787
4788   /* NOTE - the ia value is in big-endian format. */
4789   sidout->id_auth[0] = 0;
4790   sidout->id_auth[1] = 0;
4791   sidout->id_auth[2] = (ia & 0xff000000) >> 24;
4792   sidout->id_auth[3] = (ia & 0x00ff0000) >> 16;
4793   sidout->id_auth[4] = (ia & 0x0000ff00) >> 8;
4794   sidout->id_auth[5] = (ia & 0x000000ff);
4795
4796   sidout->num_auths = 0;
4797
4798   while(next_token(&p, tok, "-", sizeof(tok)) && 
4799         sidout->num_auths < MAXSUBAUTHS) {
4800     /* 
4801      * NOTE - the subauths are in native machine-endian format. They
4802      * are converted to little-endian when linearized onto the wire.
4803      */
4804     sidout->sub_auths[sidout->num_auths++] = atoi(tok);
4805   }
4806
4807   DEBUG(7,("string_to_sid: converted SID %s ok\n", sidstr));
4808
4809   return True;
4810 }
4811
4812 /*****************************************************************************
4813  * Provide a checksum on a string
4814  *
4815  *  Input:  s - the nul-terminated character string for which the checksum
4816  *              will be calculated.
4817  *
4818  *  Output: The checksum value calculated for s.
4819  *
4820  * ****************************************************************************
4821  */
4822 int str_checksum(const char *s)
4823 {
4824         int res = 0;
4825         int c;
4826         int i=0;
4827         
4828         while(*s) {
4829                 c = *s;
4830                 res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
4831                 s++;
4832                 i++;
4833         }
4834         return(res);
4835 } /* str_checksum */
4836
4837
4838
4839 /*****************************************************************
4840 zero a memory area then free it. Used to catch bugs faster
4841 *****************************************************************/  
4842 void zero_free(void *p, size_t size)
4843 {
4844         memset(p, 0, size);
4845         free(p);
4846 }