e5486e6159e949d326d207c9d2194cedf91d829e
[samba.git] / source3 / lib / util.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Samba utility functions
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
25 #ifdef WITH_NISPLUS_HOME
26 #include <rpcsvc/nis.h>
27 #else
28 #include "rpcsvc/ypclnt.h"
29 #endif
30 #endif
31
32 #ifdef WITH_SSL
33 #include <ssl.h>
34 #undef Realloc  /* SSLeay defines this and samba has a function of this name */
35 extern SSL  *ssl;
36 extern int  sslFd;
37 #endif  /* WITH_SSL */
38
39 pstring scope = "";
40
41 extern int DEBUGLEVEL;
42
43 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)
2266     {
2267       return ret;
2268     }
2269
2270     /* Ignore session keepalive packets. */
2271     if(CVAL(buffer,0) != 0x85)
2272       break;
2273   }
2274   return ret;
2275 }
2276
2277 /****************************************************************************
2278   send an smb to a fd 
2279 ****************************************************************************/
2280 BOOL send_smb(int fd,char *buffer)
2281 {
2282   size_t len;
2283   size_t nwritten=0;
2284   ssize_t ret;
2285   len = smb_len(buffer) + 4;
2286
2287   while (nwritten < len)
2288   {
2289     ret = write_socket(fd,buffer+nwritten,len - nwritten);
2290     if (ret <= 0)
2291     {
2292       DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret));
2293       close_sockets();
2294       exit(1);
2295     }
2296     nwritten += ret;
2297   }
2298
2299   return True;
2300 }
2301
2302
2303 /****************************************************************************
2304 find a pointer to a netbios name
2305 ****************************************************************************/
2306 static char *name_ptr(char *buf,int ofs)
2307 {
2308   unsigned char c = *(unsigned char *)(buf+ofs);
2309
2310   if ((c & 0xC0) == 0xC0)
2311     {
2312       uint16 l;
2313       char p[2];
2314       memcpy(p,buf+ofs,2);
2315       p[0] &= ~0xC0;
2316       l = RSVAL(p,0);
2317       DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
2318       return(buf + l);
2319     }
2320   else
2321     return(buf+ofs);
2322 }  
2323
2324 /****************************************************************************
2325 extract a netbios name from a buf
2326 ****************************************************************************/
2327 int name_extract(char *buf,int ofs,char *name)
2328 {
2329   char *p = name_ptr(buf,ofs);
2330   int d = PTR_DIFF(p,buf+ofs);
2331   pstrcpy(name,"");
2332   if (d < -50 || d > 50) return(0);
2333   return(name_interpret(p,name));
2334 }
2335   
2336 /****************************************************************************
2337 return the total storage length of a mangled name
2338 ****************************************************************************/
2339 int name_len(char *s1)
2340 {
2341         /* NOTE: this argument _must_ be unsigned */
2342         unsigned char *s = (unsigned char *)s1;
2343         int len;
2344
2345         /* If the two high bits of the byte are set, return 2. */
2346         if (0xC0 == (*s & 0xC0))
2347                 return(2);
2348
2349         /* Add up the length bytes. */
2350         for (len = 1; (*s); s += (*s) + 1) {
2351                 len += *s + 1;
2352                 SMB_ASSERT(len < 80);
2353         }
2354
2355         return(len);
2356 } /* name_len */
2357
2358 /****************************************************************************
2359 send a single packet to a port on another machine
2360 ****************************************************************************/
2361 BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
2362 {
2363   BOOL ret;
2364   int out_fd;
2365   struct sockaddr_in sock_out;
2366
2367   if (passive)
2368     return(True);
2369
2370   /* create a socket to write to */
2371   out_fd = socket(AF_INET, type, 0);
2372   if (out_fd == -1) 
2373     {
2374       DEBUG(0,("socket failed"));
2375       return False;
2376     }
2377
2378   /* set the address and port */
2379   bzero((char *)&sock_out,sizeof(sock_out));
2380   putip((char *)&sock_out.sin_addr,(char *)&ip);
2381   sock_out.sin_port = htons( port );
2382   sock_out.sin_family = AF_INET;
2383   
2384   if (DEBUGLEVEL > 0)
2385     DEBUG(3,("sending a packet of len %d to (%s) on port %d of type %s\n",
2386              len,inet_ntoa(ip),port,type==SOCK_DGRAM?"DGRAM":"STREAM"));
2387         
2388   /* send it */
2389   ret = (sendto(out_fd,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
2390
2391   if (!ret)
2392     DEBUG(0,("Packet send to %s(%d) failed ERRNO=%s\n",
2393              inet_ntoa(ip),port,strerror(errno)));
2394
2395   close(out_fd);
2396   return(ret);
2397 }
2398
2399 /*******************************************************************
2400 sleep for a specified number of milliseconds
2401 ********************************************************************/
2402 void msleep(int t)
2403 {
2404   int tdiff=0;
2405   struct timeval tval,t1,t2;  
2406   fd_set fds;
2407
2408   GetTimeOfDay(&t1);
2409   GetTimeOfDay(&t2);
2410   
2411   while (tdiff < t) {
2412     tval.tv_sec = (t-tdiff)/1000;
2413     tval.tv_usec = 1000*((t-tdiff)%1000);
2414  
2415     FD_ZERO(&fds);
2416     errno = 0;
2417     sys_select(0,&fds,&tval);
2418
2419     GetTimeOfDay(&t2);
2420     tdiff = TvalDiff(&t1,&t2);
2421   }
2422 }
2423
2424 /****************************************************************************
2425 check if a string is part of a list
2426 ****************************************************************************/
2427 BOOL in_list(char *s,char *list,BOOL casesensitive)
2428 {
2429   pstring tok;
2430   char *p=list;
2431
2432   if (!list) return(False);
2433
2434   while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
2435     if (casesensitive) {
2436       if (strcmp(tok,s) == 0)
2437         return(True);
2438     } else {
2439       if (StrCaseCmp(tok,s) == 0)
2440         return(True);
2441     }
2442   }
2443   return(False);
2444 }
2445
2446 /* this is used to prevent lots of mallocs of size 1 */
2447 static char *null_string = NULL;
2448
2449 /****************************************************************************
2450 set a string value, allocing the space for the string
2451 ****************************************************************************/
2452 BOOL string_init(char **dest,char *src)
2453 {
2454   int l;
2455   if (!src)     
2456     src = "";
2457
2458   l = strlen(src);
2459
2460   if (l == 0)
2461     {
2462       if (!null_string) {
2463         if((null_string = (char *)malloc(1)) == NULL) {
2464           DEBUG(0,("string_init: malloc fail for null_string.\n"));
2465           return False;
2466         }
2467         *null_string = 0;
2468       }
2469       *dest = null_string;
2470     }
2471   else
2472     {
2473       (*dest) = (char *)malloc(l+1);
2474       if ((*dest) == NULL) {
2475               DEBUG(0,("Out of memory in string_init\n"));
2476               return False;
2477       }
2478
2479       pstrcpy(*dest,src);
2480     }
2481   return(True);
2482 }
2483
2484 /****************************************************************************
2485 free a string value
2486 ****************************************************************************/
2487 void string_free(char **s)
2488 {
2489   if (!s || !(*s)) return;
2490   if (*s == null_string)
2491     *s = NULL;
2492   if (*s) free(*s);
2493   *s = NULL;
2494 }
2495
2496 /****************************************************************************
2497 set a string value, allocing the space for the string, and deallocating any 
2498 existing space
2499 ****************************************************************************/
2500 BOOL string_set(char **dest,char *src)
2501 {
2502   string_free(dest);
2503
2504   return(string_init(dest,src));
2505 }
2506
2507 /****************************************************************************
2508 substitute a string for a pattern in another string. Make sure there is 
2509 enough room!
2510
2511 This routine looks for pattern in s and replaces it with 
2512 insert. It may do multiple replacements.
2513
2514 return True if a substitution was done.
2515 ****************************************************************************/
2516 BOOL string_sub(char *s,char *pattern,char *insert)
2517 {
2518   BOOL ret = False;
2519   char *p;
2520   int ls,lp,li;
2521
2522   if (!insert || !pattern || !s) return(False);
2523
2524   ls = strlen(s);
2525   lp = strlen(pattern);
2526   li = strlen(insert);
2527
2528   if (!*pattern) return(False);
2529
2530   while (lp <= ls && (p = strstr(s,pattern)))
2531     {
2532       ret = True;
2533       memmove(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp));
2534       memcpy(p,insert,li);
2535       s = p + li;
2536       ls = strlen(s);
2537     }
2538   return(ret);
2539 }
2540
2541 /*********************************************************
2542 * Recursive routine that is called by unix_mask_match.
2543 * Does the actual matching. This is the 'original code' 
2544 * used by the unix matcher.
2545 *********************************************************/
2546 static BOOL unix_do_match(char *str, char *regexp, int case_sig)
2547 {
2548   char *p;
2549
2550   for( p = regexp; *p && *str; ) {
2551     switch(*p) {
2552     case '?':
2553       str++; p++;
2554       break;
2555
2556     case '*':
2557       /* Look for a character matching 
2558          the one after the '*' */
2559       p++;
2560       if(!*p)
2561         return True; /* Automatic match */
2562       while(*str) {
2563         while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
2564           str++;
2565         if(unix_do_match(str,p,case_sig))
2566           return True;
2567         if(!*str)
2568           return False;
2569         else
2570           str++;
2571       }
2572       return False;
2573
2574     default:
2575       if(case_sig) {
2576         if(*str != *p)
2577           return False;
2578       } else {
2579         if(toupper(*str) != toupper(*p))
2580           return False;
2581       }
2582       str++, p++;
2583       break;
2584     }
2585   }
2586   if(!*p && !*str)
2587     return True;
2588
2589   if (!*p && str[0] == '.' && str[1] == 0)
2590     return(True);
2591   
2592   if (!*str && *p == '?')
2593     {
2594       while (*p == '?') p++;
2595       return(!*p);
2596     }
2597
2598   if(!*str && (*p == '*' && p[1] == '\0'))
2599     return True;
2600   return False;
2601 }
2602
2603
2604 /*********************************************************
2605 * Routine to match a given string with a regexp - uses
2606 * simplified regexp that takes * and ? only. Case can be
2607 * significant or not.
2608 * This is the 'original code' used by the unix matcher.
2609 *********************************************************/
2610
2611 static BOOL unix_mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
2612 {
2613   char *p;
2614   pstring p1, p2;
2615   fstring ebase,eext,sbase,sext;
2616
2617   BOOL matched;
2618
2619   /* Make local copies of str and regexp */
2620   StrnCpy(p1,regexp,sizeof(pstring)-1);
2621   StrnCpy(p2,str,sizeof(pstring)-1);
2622
2623   if (!strchr(p2,'.')) {
2624     pstrcat(p2,".");
2625   }
2626
2627   /* Remove any *? and ** as they are meaningless */
2628   for(p = p1; *p; p++)
2629     while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
2630       (void)pstrcpy( &p[1], &p[2]);
2631
2632   if (strequal(p1,"*")) return(True);
2633
2634   DEBUG(8,("unix_mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
2635
2636   if (trans2) {
2637     fstrcpy(ebase,p1);
2638     fstrcpy(sbase,p2);
2639   } else {
2640     if ((p=strrchr(p1,'.'))) {
2641       *p = 0;
2642       fstrcpy(ebase,p1);
2643       fstrcpy(eext,p+1);
2644     } else {
2645       fstrcpy(ebase,p1);
2646       eext[0] = 0;
2647     }
2648
2649   if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
2650     *p = 0;
2651     fstrcpy(sbase,p2);
2652     fstrcpy(sext,p+1);
2653   } else {
2654     fstrcpy(sbase,p2);
2655     fstrcpy(sext,"");
2656   }
2657   }
2658
2659   matched = unix_do_match(sbase,ebase,case_sig) && 
2660     (trans2 || unix_do_match(sext,eext,case_sig));
2661
2662   DEBUG(8,("unix_mask_match returning %d\n", matched));
2663
2664   return matched;
2665 }
2666
2667 /*********************************************************
2668 * Recursive routine that is called by mask_match.
2669 * Does the actual matching. Returns True if matched,
2670 * False if failed. This is the 'new' NT style matcher.
2671 *********************************************************/
2672
2673 BOOL do_match(char *str, char *regexp, int case_sig)
2674 {
2675   char *p;
2676
2677   for( p = regexp; *p && *str; ) {
2678     switch(*p) {
2679     case '?':
2680       str++; p++;
2681       break;
2682
2683     case '*':
2684       /* Look for a character matching 
2685          the one after the '*' */
2686       p++;
2687       if(!*p)
2688         return True; /* Automatic match */
2689       while(*str) {
2690         while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
2691           str++;
2692         /* Now eat all characters that match, as
2693            we want the *last* character to match. */
2694         while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str))))
2695           str++;
2696         str--; /* We've eaten the match char after the '*' */
2697         if(do_match(str,p,case_sig)) {
2698           return True;
2699         }
2700         if(!*str) {
2701           return False;
2702         } else {
2703           str++;
2704         }
2705       }
2706       return False;
2707
2708     default:
2709       if(case_sig) {
2710         if(*str != *p) {
2711           return False;
2712         }
2713       } else {
2714         if(toupper(*str) != toupper(*p)) {
2715           return False;
2716         }
2717       }
2718       str++, p++;
2719       break;
2720     }
2721   }
2722
2723   if(!*p && !*str)
2724     return True;
2725
2726   if (!*p && str[0] == '.' && str[1] == 0) {
2727     return(True);
2728   }
2729   
2730   if (!*str && *p == '?') {
2731     while (*p == '?')
2732       p++;
2733     return(!*p);
2734   }
2735
2736   if(!*str && (*p == '*' && p[1] == '\0')) {
2737     return True;
2738   }
2739  
2740   return False;
2741 }
2742
2743
2744 /*********************************************************
2745 * Routine to match a given string with a regexp - uses
2746 * simplified regexp that takes * and ? only. Case can be
2747 * significant or not.
2748 * The 8.3 handling was rewritten by Ums Harald <Harald.Ums@pro-sieben.de>
2749 * This is the new 'NT style' matcher.
2750 *********************************************************/
2751
2752 BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
2753 {
2754   char *p;
2755   pstring t_pattern, t_filename, te_pattern, te_filename;
2756   fstring ebase,eext,sbase,sext;
2757
2758   BOOL matched = False;
2759
2760   /* Make local copies of str and regexp */
2761   pstrcpy(t_pattern,regexp);
2762   pstrcpy(t_filename,str);
2763
2764 #if 0
2765   /* 
2766    * Not sure if this is a good idea. JRA.
2767    */
2768   if(trans2 && is_8_3(t_pattern,False) && is_8_3(t_filename,False))
2769     trans2 = False;
2770 #endif
2771
2772 #if 0
2773   if (!strchr(t_filename,'.')) {
2774     pstrcat(t_filename,".");
2775   }
2776 #endif
2777
2778   /* Remove any *? and ** as they are meaningless */
2779   string_sub(t_pattern, "*?", "*");
2780   string_sub(t_pattern, "**", "*");
2781
2782   if (strequal(t_pattern,"*"))
2783     return(True);
2784
2785   DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", t_filename, t_pattern, case_sig));
2786
2787   if(trans2) {
2788     /*
2789      * Match each component of the regexp, split up by '.'
2790      * characters.
2791      */
2792     char *fp, *rp, *cp2, *cp1;
2793     BOOL last_wcard_was_star = False;
2794     int num_path_components, num_regexp_components;
2795
2796     pstrcpy(te_pattern,t_pattern);
2797     pstrcpy(te_filename,t_filename);
2798     /*
2799      * Remove multiple "*." patterns.
2800      */
2801     string_sub(te_pattern, "*.*.", "*.");
2802     num_regexp_components = count_chars(te_pattern, '.');
2803     num_path_components = count_chars(te_filename, '.');
2804
2805     /* 
2806      * Check for special 'hack' case of "DIR a*z". - needs to match a.b.c...z
2807      */
2808     if(num_regexp_components == 0)
2809       matched = do_match( te_filename, te_pattern, case_sig);
2810     else {
2811       for( cp1 = te_pattern, cp2 = te_filename; cp1;) {
2812         fp = strchr(cp2, '.');
2813         if(fp)
2814           *fp = '\0';
2815         rp = strchr(cp1, '.');
2816         if(rp)
2817           *rp = '\0';
2818
2819         if(cp1[strlen(cp1)-1] == '*')
2820           last_wcard_was_star = True;
2821         else
2822           last_wcard_was_star = False;
2823
2824         if(!do_match(cp2, cp1, case_sig))
2825           break;
2826
2827         cp1 = rp ? rp + 1 : NULL;
2828         cp2 = fp ? fp + 1 : "";
2829
2830         if(last_wcard_was_star || ((cp1 != NULL) && (*cp1 == '*'))) {
2831           /* Eat the extra path components. */
2832           int i;
2833
2834           for(i = 0; i < num_path_components - num_regexp_components; i++) {
2835             fp = strchr(cp2, '.');
2836             if(fp)
2837               *fp = '\0';
2838
2839             if((cp1 != NULL) && do_match( cp2, cp1, case_sig)) {
2840               cp2 = fp ? fp + 1 : "";
2841               break;
2842             }
2843             cp2 = fp ? fp + 1 : "";
2844           }
2845           num_path_components -= i;
2846         }
2847       } 
2848       if(cp1 == NULL && ((*cp2 == '\0') || last_wcard_was_star))
2849         matched = True;
2850     }
2851   } else {
2852
2853     /* -------------------------------------------------
2854      * Behaviour of Win95
2855      * for 8.3 filenames and 8.3 Wildcards
2856      * -------------------------------------------------
2857      */
2858     if (strequal (t_filename, ".")) {
2859       /*
2860        *  Patterns:  *.*  *. ?. ?  are valid
2861        *
2862        */
2863       if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
2864          strequal(t_pattern, "?.") || strequal(t_pattern, "?"))
2865         matched = True;
2866     } else if (strequal (t_filename, "..")) {
2867       /*
2868        *  Patterns:  *.*  *. ?. ? *.? are valid
2869        *
2870        */
2871       if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
2872          strequal(t_pattern, "?.") || strequal(t_pattern, "?") ||
2873          strequal(t_pattern, "*.?") || strequal(t_pattern, "?.*"))
2874         matched = True;
2875     } else {
2876
2877       if ((p = strrchr (t_pattern, '.'))) {
2878         /*
2879          * Wildcard has a suffix.
2880          */
2881         *p = 0;
2882         fstrcpy (ebase, t_pattern);
2883         if (p[1]) {
2884           fstrcpy (eext, p + 1);
2885         } else {
2886           /* pattern ends in DOT: treat as if there is no DOT */
2887           *eext = 0;
2888           if (strequal (ebase, "*"))
2889             return (True);
2890         }
2891       } else {
2892         /*
2893          * No suffix for wildcard.
2894          */
2895         fstrcpy (ebase, t_pattern);
2896         eext[0] = 0;
2897       }
2898
2899       p = strrchr (t_filename, '.');
2900       if (p && (p[1] == 0)      ) {
2901         /*
2902          * Filename has an extension of '.' only.
2903          */
2904         *p = 0; /* nuke dot at end of string */
2905         p = 0;  /* and treat it as if there is no extension */
2906       }
2907
2908       if (p) {
2909         /*
2910          * Filename has an extension.
2911          */
2912         *p = 0;
2913         fstrcpy (sbase, t_filename);
2914         fstrcpy (sext, p + 1);
2915         if (*eext) {
2916           matched = do_match(sbase, ebase, case_sig)
2917                     && do_match(sext, eext, case_sig);
2918         } else {
2919           /* pattern has no extension */
2920           /* Really: match complete filename with pattern ??? means exactly 3 chars */
2921           matched = do_match(str, ebase, case_sig);
2922         }
2923       } else {
2924         /* 
2925          * Filename has no extension.
2926          */
2927         fstrcpy (sbase, t_filename);
2928         fstrcpy (sext, "");
2929         if (*eext) {
2930           /* pattern has extension */
2931           matched = do_match(sbase, ebase, case_sig)
2932                     && do_match(sext, eext, case_sig);
2933         } else {
2934           matched = do_match(sbase, ebase, case_sig);
2935 #ifdef EMULATE_WEIRD_W95_MATCHING
2936           /*
2937            * Even Microsoft has some problems
2938            * Behaviour Win95 -> local disk 
2939            * is different from Win95 -> smb drive from Nt 4.0
2940            * This branch would reflect the Win95 local disk behaviour
2941            */
2942           if (!matched) {
2943             /* a? matches aa and a in w95 */
2944             fstrcat (sbase, ".");
2945             matched = do_match(sbase, ebase, case_sig);
2946           }
2947 #endif
2948         }
2949       }
2950     }
2951   }
2952
2953   DEBUG(8,("mask_match returning %d\n", matched));
2954
2955   return matched;
2956 }
2957
2958 /****************************************************************************
2959 become a daemon, discarding the controlling terminal
2960 ****************************************************************************/
2961 void become_daemon(void)
2962 {
2963         if (fork()) {
2964                 _exit(0);
2965         }
2966
2967   /* detach from the terminal */
2968 #ifdef HAVE_SETSID
2969         setsid();
2970 #elif defined(TIOCNOTTY)
2971         {
2972                 int i = open("/dev/tty", O_RDWR);
2973                 if (i != -1) {
2974                         ioctl(i, (int) TIOCNOTTY, (char *)0);      
2975                         close(i);
2976                 }
2977         }
2978 #endif /* HAVE_SETSID */
2979
2980         /* Close fd's 0,1,2. Needed if started by rsh */
2981         close_low_fds();
2982 }
2983
2984
2985 /****************************************************************************
2986 put up a yes/no prompt
2987 ****************************************************************************/
2988 BOOL yesno(char *p)
2989 {
2990   pstring ans;
2991   printf("%s",p);
2992
2993   if (!fgets(ans,sizeof(ans)-1,stdin))
2994     return(False);
2995
2996   if (*ans == 'y' || *ans == 'Y')
2997     return(True);
2998
2999   return(False);
3000 }
3001
3002 /****************************************************************************
3003 read a line from a file with possible \ continuation chars. 
3004 Blanks at the start or end of a line are stripped.
3005 The string will be allocated if s2 is NULL
3006 ****************************************************************************/
3007 char *fgets_slash(char *s2,int maxlen,FILE *f)
3008 {
3009   char *s=s2;
3010   int len = 0;
3011   int c;
3012   BOOL start_of_line = True;
3013
3014   if (feof(f))
3015     return(NULL);
3016
3017   if (!s2)
3018     {
3019       maxlen = MIN(maxlen,8);
3020       s = (char *)Realloc(s,maxlen);
3021     }
3022
3023   if (!s || maxlen < 2) return(NULL);
3024
3025   *s = 0;
3026
3027   while (len < maxlen-1)
3028     {
3029       c = getc(f);
3030       switch (c)
3031         {
3032         case '\r':
3033           break;
3034         case '\n':
3035           while (len > 0 && s[len-1] == ' ')
3036             {
3037               s[--len] = 0;
3038             }
3039           if (len > 0 && s[len-1] == '\\')
3040             {
3041               s[--len] = 0;
3042               start_of_line = True;
3043               break;
3044             }
3045           return(s);
3046         case EOF:
3047           if (len <= 0 && !s2) 
3048             free(s);
3049           return(len>0?s:NULL);
3050         case ' ':
3051           if (start_of_line)
3052             break;
3053         default:
3054           start_of_line = False;
3055           s[len++] = c;
3056           s[len] = 0;
3057         }
3058       if (!s2 && len > maxlen-3)
3059         {
3060           maxlen *= 2;
3061           s = (char *)Realloc(s,maxlen);
3062           if (!s) return(NULL);
3063         }
3064     }
3065   return(s);
3066 }
3067
3068
3069
3070 /****************************************************************************
3071 set the length of a file from a filedescriptor.
3072 Returns 0 on success, -1 on failure.
3073 ****************************************************************************/
3074 int set_filelen(int fd, SMB_OFF_T len)
3075 {
3076 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
3077    extend a file with ftruncate. Provide alternate implementation
3078    for this */
3079
3080 #ifdef HAVE_FTRUNCATE_EXTEND
3081   return sys_ftruncate(fd, len);
3082 #else
3083   SMB_STRUCT_STAT st;
3084   char c = 0;
3085   SMB_OFF_T currpos = sys_lseek(fd, (SMB_OFF_T)0, SEEK_CUR);
3086
3087   if(currpos == -1)
3088     return -1;
3089   /* Do an fstat to see if the file is longer than
3090      the requested size (call ftruncate),
3091      or shorter, in which case seek to len - 1 and write 1
3092      byte of zero */
3093   if(sys_fstat(fd, &st)<0)
3094     return -1;
3095
3096 #ifdef S_ISFIFO
3097   if (S_ISFIFO(st.st_mode)) return 0;
3098 #endif
3099
3100   if(st.st_size == len)
3101     return 0;
3102   if(st.st_size > len)
3103     return sys_ftruncate(fd, len);
3104
3105   if(sys_lseek(fd, len-1, SEEK_SET) != len -1)
3106     return -1;
3107   if(write(fd, &c, 1)!=1)
3108     return -1;
3109   /* Seek to where we were */
3110   if(sys_lseek(fd, currpos, SEEK_SET) != currpos)
3111     return -1;
3112   return 0;
3113 #endif
3114 }
3115
3116
3117 #ifdef HPUX
3118 /****************************************************************************
3119 this is a version of setbuffer() for those machines that only have setvbuf
3120 ****************************************************************************/
3121  void setbuffer(FILE *f,char *buf,int bufsize)
3122 {
3123   setvbuf(f,buf,_IOFBF,bufsize);
3124 }
3125 #endif
3126
3127
3128 /****************************************************************************
3129 parse out a filename from a path name. Assumes dos style filenames.
3130 ****************************************************************************/
3131 static char *filename_dos(char *path,char *buf)
3132 {
3133   char *p = strrchr(path,'\\');
3134
3135   if (!p)
3136     pstrcpy(buf,path);
3137   else
3138     pstrcpy(buf,p+1);
3139
3140   return(buf);
3141 }
3142
3143
3144
3145 /****************************************************************************
3146 expand a pointer to be a particular size
3147 ****************************************************************************/
3148 void *Realloc(void *p,size_t size)
3149 {
3150   void *ret=NULL;
3151
3152   if (size == 0) {
3153     if (p) free(p);
3154     DEBUG(5,("Realloc asked for 0 bytes\n"));
3155     return NULL;
3156   }
3157
3158   if (!p)
3159     ret = (void *)malloc(size);
3160   else
3161     ret = (void *)realloc(p,size);
3162
3163   if (!ret)
3164     DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",size));
3165
3166   return(ret);
3167 }
3168
3169
3170 /****************************************************************************
3171 get my own name and IP
3172 ****************************************************************************/
3173 BOOL get_myname(char *my_name,struct in_addr *ip)
3174 {
3175   struct hostent *hp;
3176   pstring hostname;
3177
3178   *hostname = 0;
3179
3180   /* get my host name */
3181   if (gethostname(hostname, MAXHOSTNAMELEN) == -1) 
3182     {
3183       DEBUG(0,("gethostname failed\n"));
3184       return False;
3185     } 
3186
3187   /* get host info */
3188   if ((hp = Get_Hostbyname(hostname)) == 0) 
3189     {
3190       DEBUG(0,( "Get_Hostbyname: Unknown host %s\n",hostname));
3191       return False;
3192     }
3193
3194   if (my_name)
3195     {
3196       /* split off any parts after an initial . */
3197       char *p = strchr(hostname,'.');
3198       if (p) *p = 0;
3199
3200       fstrcpy(my_name,hostname);
3201     }
3202
3203   if (ip)
3204     putip((char *)ip,(char *)hp->h_addr);
3205
3206   return(True);
3207 }
3208
3209
3210 /****************************************************************************
3211 true if two IP addresses are equal
3212 ****************************************************************************/
3213 BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
3214 {
3215   uint32 a1,a2;
3216   a1 = ntohl(ip1.s_addr);
3217   a2 = ntohl(ip2.s_addr);
3218   return(a1 == a2);
3219 }
3220
3221
3222 /****************************************************************************
3223 open a socket of the specified type, port and address for incoming data
3224 ****************************************************************************/
3225 int open_socket_in(int type, int port, int dlevel,uint32 socket_addr)
3226 {
3227   struct hostent *hp;
3228   struct sockaddr_in sock;
3229   pstring host_name;
3230   int res;
3231
3232   /* get my host name */
3233   if (gethostname(host_name, MAXHOSTNAMELEN) == -1) 
3234     { DEBUG(0,("gethostname failed\n")); return -1; } 
3235
3236   /* get host info */
3237   if ((hp = Get_Hostbyname(host_name)) == 0) 
3238     {
3239       DEBUG(0,( "Get_Hostbyname: Unknown host %s\n",host_name));
3240       return -1;
3241     }
3242   
3243   bzero((char *)&sock,sizeof(sock));
3244   memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
3245
3246 #ifdef HAVE_SOCK_SIN_LEN
3247   sock.sin_len = sizeof(sock);
3248 #endif
3249   sock.sin_port = htons( port );
3250   sock.sin_family = hp->h_addrtype;
3251   sock.sin_addr.s_addr = socket_addr;
3252   res = socket(hp->h_addrtype, type, 0);
3253   if (res == -1) 
3254     { DEBUG(0,("socket failed\n")); return -1; }
3255
3256   {
3257     int one=1;
3258     setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
3259   }
3260
3261   /* now we've got a socket - we need to bind it */
3262   if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) 
3263     { 
3264       if (port) {
3265         if (port == SMB_PORT || port == NMB_PORT)
3266           DEBUG(dlevel,("bind failed on port %d socket_addr=%s (%s)\n",
3267                         port,inet_ntoa(sock.sin_addr),strerror(errno))); 
3268         close(res); 
3269
3270         if (dlevel > 0 && port < 1000)
3271           port = 7999;
3272
3273         if (port >= 1000 && port < 9000)
3274           return(open_socket_in(type,port+1,dlevel,socket_addr));
3275       }
3276
3277       return(-1); 
3278     }
3279   DEBUG(3,("bind succeeded on port %d\n",port));
3280
3281   return res;
3282 }
3283
3284
3285 /****************************************************************************
3286   create an outgoing socket
3287   **************************************************************************/
3288 int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
3289 {
3290   struct sockaddr_in sock_out;
3291   int res,ret;
3292   int connect_loop = 250; /* 250 milliseconds */
3293   int loops = (timeout * 1000) / connect_loop;
3294
3295   /* create a socket to write to */
3296   res = socket(PF_INET, type, 0);
3297   if (res == -1) 
3298     { DEBUG(0,("socket error\n")); return -1; }
3299
3300   if (type != SOCK_STREAM) return(res);
3301   
3302   bzero((char *)&sock_out,sizeof(sock_out));
3303   putip((char *)&sock_out.sin_addr,(char *)addr);
3304   
3305   sock_out.sin_port = htons( port );
3306   sock_out.sin_family = PF_INET;
3307
3308   /* set it non-blocking */
3309   set_blocking(res,False);
3310
3311   DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port));
3312   
3313   /* and connect it to the destination */
3314 connect_again:
3315   ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out));
3316
3317   /* Some systems return EAGAIN when they mean EINPROGRESS */
3318   if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
3319         errno == EAGAIN) && loops--) {
3320     msleep(connect_loop);
3321     goto connect_again;
3322   }
3323
3324   if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
3325          errno == EAGAIN)) {
3326       DEBUG(1,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port));
3327       close(res);
3328       return -1;
3329   }
3330
3331 #ifdef EISCONN
3332   if (ret < 0 && errno == EISCONN) {
3333     errno = 0;
3334     ret = 0;
3335   }
3336 #endif
3337
3338   if (ret < 0) {
3339     DEBUG(1,("error connecting to %s:%d (%s)\n",
3340              inet_ntoa(*addr),port,strerror(errno)));
3341     close(res);
3342     return -1;
3343   }
3344
3345   /* set it blocking again */
3346   set_blocking(res,True);
3347
3348   return res;
3349 }
3350
3351
3352 /****************************************************************************
3353 interpret a protocol description string, with a default
3354 ****************************************************************************/
3355 int interpret_protocol(char *str,int def)
3356 {
3357   if (strequal(str,"NT1"))
3358     return(PROTOCOL_NT1);
3359   if (strequal(str,"LANMAN2"))
3360     return(PROTOCOL_LANMAN2);
3361   if (strequal(str,"LANMAN1"))
3362     return(PROTOCOL_LANMAN1);
3363   if (strequal(str,"CORE"))
3364     return(PROTOCOL_CORE);
3365   if (strequal(str,"COREPLUS"))
3366     return(PROTOCOL_COREPLUS);
3367   if (strequal(str,"CORE+"))
3368     return(PROTOCOL_COREPLUS);
3369   
3370   DEBUG(0,("Unrecognised protocol level %s\n",str));
3371   
3372   return(def);
3373 }
3374
3375
3376 /****************************************************************************
3377 interpret an internet address or name into an IP address in 4 byte form
3378 ****************************************************************************/
3379 uint32 interpret_addr(char *str)
3380 {
3381   struct hostent *hp;
3382   uint32 res;
3383   int i;
3384   BOOL pure_address = True;
3385
3386   if (strcmp(str,"0.0.0.0") == 0) return(0);
3387   if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
3388
3389   for (i=0; pure_address && str[i]; i++)
3390     if (!(isdigit((int)str[i]) || str[i] == '.')) 
3391       pure_address = False;
3392
3393   /* if it's in the form of an IP address then get the lib to interpret it */
3394   if (pure_address) {
3395     res = inet_addr(str);
3396   } else {
3397     /* otherwise assume it's a network name of some sort and use 
3398        Get_Hostbyname */
3399     if ((hp = Get_Hostbyname(str)) == 0) {
3400       DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
3401       return 0;
3402     }
3403     if(hp->h_addr == NULL) {
3404       DEBUG(3,("Get_Hostbyname: host address is invalid for host %s\n",str));
3405       return 0;
3406     }
3407     putip((char *)&res,(char *)hp->h_addr);
3408   }
3409
3410   if (res == (uint32)-1) return(0);
3411
3412   return(res);
3413 }
3414
3415 /*******************************************************************
3416   a convenient addition to interpret_addr()
3417   ******************************************************************/
3418 struct in_addr *interpret_addr2(char *str)
3419 {
3420   static struct in_addr ret;
3421   uint32 a = interpret_addr(str);
3422   ret.s_addr = a;
3423   return(&ret);
3424 }
3425
3426 /*******************************************************************
3427   check if an IP is the 0.0.0.0
3428   ******************************************************************/
3429 BOOL zero_ip(struct in_addr ip)
3430 {
3431   uint32 a;
3432   putip((char *)&a,(char *)&ip);
3433   return(a == 0);
3434 }
3435
3436
3437 /*******************************************************************
3438  matchname - determine if host name matches IP address 
3439  ******************************************************************/
3440 static BOOL matchname(char *remotehost,struct in_addr  addr)
3441 {
3442   struct hostent *hp;
3443   int     i;
3444   
3445   if ((hp = Get_Hostbyname(remotehost)) == 0) {
3446     DEBUG(0,("Get_Hostbyname(%s): lookup failure", remotehost));
3447     return False;
3448   } 
3449
3450   /*
3451    * Make sure that gethostbyname() returns the "correct" host name.
3452    * Unfortunately, gethostbyname("localhost") sometimes yields
3453    * "localhost.domain". Since the latter host name comes from the
3454    * local DNS, we just have to trust it (all bets are off if the local
3455    * DNS is perverted). We always check the address list, though.
3456    */
3457   
3458   if (strcasecmp(remotehost, hp->h_name)
3459       && strcasecmp(remotehost, "localhost")) {
3460     DEBUG(0,("host name/name mismatch: %s != %s",
3461              remotehost, hp->h_name));
3462     return False;
3463   }
3464         
3465   /* Look up the host address in the address list we just got. */
3466   for (i = 0; hp->h_addr_list[i]; i++) {
3467     if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
3468       return True;
3469   }
3470
3471   /*
3472    * The host name does not map to the original host address. Perhaps
3473    * someone has compromised a name server. More likely someone botched
3474    * it, but that could be dangerous, too.
3475    */
3476   
3477   DEBUG(0,("host name/address mismatch: %s != %s",
3478            inet_ntoa(addr), hp->h_name));
3479   return False;
3480 }
3481
3482 /*******************************************************************
3483  Reset the 'done' variables so after a client process is created
3484  from a fork call these calls will be re-done. This should be
3485  expanded if more variables need reseting.
3486  ******************************************************************/
3487
3488 static BOOL global_client_name_done = False;
3489 static BOOL global_client_addr_done = False;
3490
3491 void reset_globals_after_fork(void)
3492 {
3493   global_client_name_done = False;
3494   global_client_addr_done = False;
3495
3496   /*
3497    * Re-seed the random crypto generator, so all smbd's
3498    * started from the same parent won't generate the same
3499    * sequence.
3500    */
3501   {
3502     unsigned char dummy;
3503     generate_random_buffer( &dummy, 1, True);
3504   } 
3505 }
3506  
3507 /*******************************************************************
3508  return the DNS name of the client 
3509  ******************************************************************/
3510 char *client_name(int fd)
3511 {
3512         struct sockaddr sa;
3513         struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
3514         int     length = sizeof(sa);
3515         static pstring name_buf;
3516         struct hostent *hp;
3517         static int last_fd=-1;
3518         
3519         if (global_client_name_done && last_fd == fd) 
3520                 return name_buf;
3521         
3522         last_fd = fd;
3523         global_client_name_done = False;
3524         
3525         pstrcpy(name_buf,"UNKNOWN");
3526         
3527         if (fd == -1) {
3528                 return name_buf;
3529         }
3530         
3531         if (getpeername(fd, &sa, &length) < 0) {
3532                 DEBUG(0,("getpeername failed\n"));
3533                 return name_buf;
3534         }
3535         
3536         /* Look up the remote host name. */
3537         if ((hp = gethostbyaddr((char *) &sockin->sin_addr,
3538                                 sizeof(sockin->sin_addr),
3539                                 AF_INET)) == 0) {
3540                 DEBUG(1,("Gethostbyaddr failed for %s\n",client_addr(fd)));
3541                 StrnCpy(name_buf,client_addr(fd),sizeof(name_buf) - 1);
3542         } else {
3543                 StrnCpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1);
3544                 if (!matchname(name_buf, sockin->sin_addr)) {
3545                         DEBUG(0,("Matchname failed on %s %s\n",name_buf,client_addr(fd)));
3546                         pstrcpy(name_buf,"UNKNOWN");
3547                 }
3548         }
3549         global_client_name_done = True;
3550         return name_buf;
3551 }
3552
3553 /*******************************************************************
3554  return the IP addr of the client as a string 
3555  ******************************************************************/
3556 char *client_addr(int fd)
3557 {
3558         struct sockaddr sa;
3559         struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
3560         int     length = sizeof(sa);
3561         static fstring addr_buf;
3562         static int last_fd = -1;
3563
3564         if (global_client_addr_done && fd == last_fd) 
3565                 return addr_buf;
3566
3567         last_fd = fd;
3568         global_client_addr_done = False;
3569
3570         fstrcpy(addr_buf,"0.0.0.0");
3571
3572         if (fd == -1) {
3573                 return addr_buf;
3574         }
3575         
3576         if (getpeername(fd, &sa, &length) < 0) {
3577                 DEBUG(0,("getpeername failed\n"));
3578                 return addr_buf;
3579         }
3580         
3581         fstrcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr));
3582         
3583         global_client_addr_done = True;
3584         return addr_buf;
3585 }
3586
3587 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
3588 /******************************************************************
3589  Remove any mount options such as -rsize=2048,wsize=2048 etc.
3590  Based on a fix from <Thomas.Hepper@icem.de>.
3591 *******************************************************************/
3592
3593 static void strip_mount_options( pstring *str)
3594 {
3595   if (**str == '-')
3596   { 
3597     char *p = *str;
3598     while(*p && !isspace(*p))
3599       p++;
3600     while(*p && isspace(*p))
3601       p++;
3602     if(*p) {
3603       pstring tmp_str;
3604
3605       pstrcpy(tmp_str, p);
3606       pstrcpy(*str, tmp_str);
3607     }
3608   }
3609 }
3610
3611 /*******************************************************************
3612  Patch from jkf@soton.ac.uk
3613  Split Luke's automount_server into YP lookup and string splitter
3614  so can easily implement automount_path(). 
3615  As we may end up doing both, cache the last YP result. 
3616 *******************************************************************/
3617
3618 #ifdef WITH_NISPLUS_HOME
3619 static char *automount_lookup(char *user_name)
3620 {
3621   static fstring last_key = "";
3622   static pstring last_value = "";
3623  
3624   char *nis_map = (char *)lp_nis_home_map_name();
3625  
3626   char nis_domain[NIS_MAXNAMELEN + 1];
3627   char buffer[NIS_MAXATTRVAL + 1];
3628   nis_result *result;
3629   nis_object *object;
3630   entry_obj  *entry;
3631  
3632   strncpy(nis_domain, (char *)nis_local_directory(), NIS_MAXNAMELEN);
3633   nis_domain[NIS_MAXNAMELEN] = '\0';
3634  
3635   DEBUG(5, ("NIS+ Domain: %s\n", nis_domain));
3636  
3637   if (strcmp(user_name, last_key))
3638   {
3639     slprintf(buffer, sizeof(buffer)-1, "[%s=%s]%s.%s", "key", user_name, nis_map, nis_domain);
3640     DEBUG(5, ("NIS+ querystring: %s\n", buffer));
3641  
3642     if (result = nis_list(buffer, RETURN_RESULT, NULL, NULL))
3643     {
3644        if (result->status != NIS_SUCCESS)
3645       {
3646         DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
3647         fstrcpy(last_key, ""); pstrcpy(last_value, "");
3648       }
3649       else
3650       {
3651         object = result->objects.objects_val;
3652         if (object->zo_data.zo_type == ENTRY_OBJ)
3653         {
3654            entry = &object->zo_data.objdata_u.en_data;
3655            DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
3656            DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
3657  
3658            pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
3659            string_sub(last_value, "&", user_name);
3660            fstrcpy(last_key, user_name);
3661         }
3662       }
3663     }
3664     nis_freeresult(result);
3665   }
3666
3667   strip_mount_options(&last_value);
3668
3669   DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
3670   return last_value;
3671 }
3672 #else /* WITH_NISPLUS_HOME */
3673 static char *automount_lookup(char *user_name)
3674 {
3675   static fstring last_key = "";
3676   static pstring last_value = "";
3677
3678   int nis_error;        /* returned by yp all functions */
3679   char *nis_result;     /* yp_match inits this */
3680   int nis_result_len;  /* and set this */
3681   char *nis_domain;     /* yp_get_default_domain inits this */
3682   char *nis_map = (char *)lp_nis_home_map_name();
3683
3684   if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
3685   {
3686     DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
3687     return last_value;
3688   }
3689
3690   DEBUG(5, ("NIS Domain: %s\n", nis_domain));
3691
3692   if (!strcmp(user_name, last_key))
3693   {
3694     nis_result = last_value;
3695     nis_result_len = strlen(last_value);
3696     nis_error = 0;
3697   }
3698   else
3699   {
3700     if ((nis_error = yp_match(nis_domain, nis_map,
3701                               user_name, strlen(user_name),
3702                               &nis_result, &nis_result_len)) != 0)
3703     {
3704       DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n", 
3705                yperr_string(nis_error), user_name, nis_map));
3706     }
3707     if (!nis_error && nis_result_len >= sizeof(pstring))
3708     {
3709       nis_result_len = sizeof(pstring)-1;
3710     }
3711     fstrcpy(last_key, user_name);
3712     strncpy(last_value, nis_result, nis_result_len);
3713     last_value[nis_result_len] = '\0';
3714   }
3715
3716   strip_mount_options(&last_value);
3717
3718   DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
3719   return last_value;
3720 }
3721 #endif /* WITH_NISPLUS_HOME */
3722 #endif
3723
3724 /*******************************************************************
3725  Patch from jkf@soton.ac.uk
3726  This is Luke's original function with the NIS lookup code
3727  moved out to a separate function.
3728 *******************************************************************/
3729 static char *automount_server(char *user_name)
3730 {
3731         static pstring server_name;
3732
3733         /* use the local machine name as the default */
3734         /* this will be the default if WITH_AUTOMOUNT is not used or fails */
3735         pstrcpy(server_name, local_machine);
3736
3737 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
3738
3739         if (lp_nis_home_map())
3740         {
3741                 int home_server_len;
3742                 char *automount_value = automount_lookup(user_name);
3743                 home_server_len = strcspn(automount_value,":");
3744                 DEBUG(5, ("NIS lookup succeeded.  Home server length: %d\n",home_server_len));
3745                 if (home_server_len > sizeof(pstring))
3746                 {
3747                         home_server_len = sizeof(pstring);
3748                 }
3749                 strncpy(server_name, automount_value, home_server_len);
3750                 server_name[home_server_len] = '\0';
3751         }
3752 #endif
3753
3754         DEBUG(4,("Home server: %s\n", server_name));
3755
3756         return server_name;
3757 }
3758
3759 /*******************************************************************
3760  Patch from jkf@soton.ac.uk
3761  Added this to implement %p (NIS auto-map version of %H)
3762 *******************************************************************/
3763 static char *automount_path(char *user_name)
3764 {
3765         static pstring server_path;
3766
3767         /* use the passwd entry as the default */
3768         /* this will be the default if WITH_AUTOMOUNT is not used or fails */
3769         /* pstrcpy() copes with get_home_dir() returning NULL */
3770         pstrcpy(server_path, get_home_dir(user_name));
3771
3772 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
3773
3774         if (lp_nis_home_map())
3775         {
3776                 char *home_path_start;
3777                 char *automount_value = automount_lookup(user_name);
3778                 home_path_start = strchr(automount_value,':');
3779                 if (home_path_start != NULL)
3780                 {
3781                   DEBUG(5, ("NIS lookup succeeded.  Home path is: %s\n",
3782                         home_path_start?(home_path_start+1):""));
3783                   pstrcpy(server_path, home_path_start+1);
3784                 }
3785         }
3786 #endif
3787
3788         DEBUG(4,("Home server path: %s\n", server_path));
3789
3790         return server_path;
3791 }
3792
3793
3794 /*******************************************************************
3795 sub strings with useful parameters
3796 Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
3797 Paul Rippin <pr3245@nopc.eurostat.cec.be>
3798 ********************************************************************/
3799 void standard_sub_basic(char *str)
3800 {
3801         char *s, *p;
3802         char pidstr[10];
3803         struct passwd *pass;
3804         char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user;
3805
3806         for (s = str ; s && *s && (p = strchr(s,'%')); s = p )
3807         {
3808                 switch (*(p+1))
3809                 {
3810                         case 'G' :
3811                         {
3812                                 if ((pass = Get_Pwnam(username,False))!=NULL)
3813                                 {
3814                                         string_sub(p,"%G",gidtoname(pass->pw_gid));
3815                                 }
3816                                 else
3817                                 {
3818                                         p += 2;
3819                                 }
3820                                 break;
3821                         }
3822                         case 'N' : string_sub(p,"%N", automount_server(username)); break;
3823                         case 'I' : string_sub(p,"%I", client_addr(Client)); break;
3824                         case 'L' : string_sub(p,"%L", local_machine); break;
3825                         case 'M' : string_sub(p,"%M", client_name(Client)); break;
3826                         case 'R' : string_sub(p,"%R", remote_proto); break;
3827                         case 'T' : string_sub(p,"%T", timestring()); break;
3828                         case 'U' : string_sub(p,"%U", username); break;
3829                         case 'a' : string_sub(p,"%a", remote_arch); break;
3830                         case 'd' :
3831                         {
3832                                 slprintf(pidstr,sizeof(pidstr) - 1, "%d",(int)getpid());
3833                                 string_sub(p,"%d", pidstr);
3834                                 break;
3835                         }
3836                         case 'h' : string_sub(p,"%h", myhostname); break;
3837                         case 'm' : string_sub(p,"%m", remote_machine); break;
3838                         case 'v' : string_sub(p,"%v", VERSION); break;
3839                         case '$' : /* Expand environment variables */
3840                         {
3841                                 /* Contributed by Branko Cibej <branko.cibej@hermes.si> */
3842                                 fstring envname;
3843                                 char *envval;
3844                                 char *q, *r;
3845                                 int copylen;
3846
3847                                 if (*(p+2) != '(')
3848                                 {
3849                                         p+=2;
3850                                         break;
3851                                 }
3852                                 if ((q = strchr(p,')')) == NULL)
3853                                 {
3854                                         DEBUG(0,("standard_sub_basic: Unterminated environment \
3855                                         variable [%s]\n", p));
3856                                         p+=2;
3857                                         break;
3858                                 }
3859
3860                                 r = p+3;
3861                                 copylen = MIN((q-r),(sizeof(envname)-1));
3862                                 strncpy(envname,r,copylen);
3863                                 envname[copylen] = '\0';
3864
3865                                 if ((envval = getenv(envname)) == NULL)
3866                                 {
3867                                         DEBUG(0,("standard_sub_basic: Environment variable [%s] not set\n",
3868                                         envname));
3869                                         p+=2;
3870                                         break;
3871                                 }
3872
3873                                 copylen = MIN((q+1-p),(sizeof(envname)-1));
3874                                 strncpy(envname,p,copylen);
3875                                 envname[copylen] = '\0';
3876                                 string_sub(p,envname,envval);
3877                                 break;
3878                         }
3879                         case '\0': p++; break; /* don't run off end if last character is % */
3880                         default  : p+=2; break;
3881                 }
3882         }
3883         return;
3884 }
3885
3886
3887 /****************************************************************************
3888 do some standard substitutions in a string
3889 ****************************************************************************/
3890 void standard_sub(connection_struct *conn,char *str)
3891 {
3892         char *p, *s, *home;
3893
3894         for (s=str; (p=strchr(s, '%'));s=p) {
3895                 switch (*(p+1)) {
3896                 case 'H': 
3897                         if ((home = get_home_dir(conn->user))) {
3898                                 string_sub(p,"%H",home);
3899                         } else {
3900                                 p += 2;
3901                         }
3902                         break;
3903                         
3904                 case 'P': 
3905                         string_sub(p,"%P",conn->connectpath); 
3906                         break;
3907                         
3908                 case 'S': 
3909                         string_sub(p,"%S",
3910                                    lp_servicename(SNUM(conn))); 
3911                         break;
3912                         
3913                 case 'g': 
3914                         string_sub(p,"%g",
3915                                    gidtoname(conn->gid)); 
3916                         break;
3917                 case 'u': 
3918                         string_sub(p,"%u",conn->user); 
3919                         break;
3920                         
3921                         /* Patch from jkf@soton.ac.uk Left the %N (NIS
3922                          * server name) in standard_sub_basic as it is
3923                          * a feature for logon servers, hence uses the
3924                          * username.  The %p (NIS server path) code is
3925                          * here as it is used instead of the default
3926                          * "path =" string in [homes] and so needs the
3927                          * service name, not the username.  */
3928                 case 'p': 
3929                         string_sub(p,"%p",
3930                                    automount_path(lp_servicename(SNUM(conn)))); 
3931                         break;
3932                 case '\0': 
3933                         p++; 
3934                         break; /* don't run off the end of the string 
3935                                 */
3936                         
3937                 default: p+=2; 
3938                         break;
3939                 }
3940         }
3941         
3942         standard_sub_basic(str);
3943 }
3944
3945
3946
3947 /*******************************************************************
3948 are two IPs on the same subnet?
3949 ********************************************************************/
3950 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
3951 {
3952   uint32 net1,net2,nmask;
3953
3954   nmask = ntohl(mask.s_addr);
3955   net1  = ntohl(ip1.s_addr);
3956   net2  = ntohl(ip2.s_addr);
3957             
3958   return((net1 & nmask) == (net2 & nmask));
3959 }
3960
3961
3962 /*******************************************************************
3963 write a string in unicoode format
3964 ********************************************************************/
3965 int PutUniCode(char *dst,char *src)
3966 {
3967   int ret = 0;
3968   while (*src) {
3969     dst[ret++] = src[0];
3970     dst[ret++] = 0;    
3971     src++;
3972   }
3973   dst[ret++]=0;
3974   dst[ret++]=0;
3975   return(ret);
3976 }
3977
3978 /****************************************************************************
3979 a wrapper for gethostbyname() that tries with all lower and all upper case 
3980 if the initial name fails
3981 ****************************************************************************/
3982 struct hostent *Get_Hostbyname(char *name)
3983 {
3984   char *name2 = strdup(name);
3985   struct hostent *ret;
3986
3987   if (!name2)
3988     {
3989       DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
3990       exit(0);
3991     }
3992
3993    
3994   /* 
3995    * This next test is redundent and causes some systems (with
3996    * broken isalnum() calls) problems.
3997    * JRA.
3998    */
3999
4000 #if 0
4001   if (!isalnum(*name2))
4002     {
4003       free(name2);
4004       return(NULL);
4005     }
4006 #endif /* 0 */
4007
4008   ret = sys_gethostbyname(name2);
4009   if (ret != NULL)
4010     {
4011       free(name2);
4012       return(ret);
4013     }
4014
4015   /* try with all lowercase */
4016   strlower(name2);
4017   ret = sys_gethostbyname(name2);
4018   if (ret != NULL)
4019     {
4020       free(name2);
4021       return(ret);
4022     }
4023
4024   /* try with all uppercase */
4025   strupper(name2);
4026   ret = sys_gethostbyname(name2);
4027   if (ret != NULL)
4028     {
4029       free(name2);
4030       return(ret);
4031     }
4032   
4033   /* nothing works :-( */
4034   free(name2);
4035   return(NULL);
4036 }
4037
4038
4039 /****************************************************************************
4040 check if a process exists. Does this work on all unixes?
4041 ****************************************************************************/
4042
4043 BOOL process_exists(int pid)
4044 {
4045         return(kill(pid,0) == 0 || errno != ESRCH);
4046 }
4047
4048
4049 /*******************************************************************
4050 turn a uid into a user name
4051 ********************************************************************/
4052 char *uidtoname(uid_t uid)
4053 {
4054   static char name[40];
4055   struct passwd *pass = getpwuid(uid);
4056   if (pass) return(pass->pw_name);
4057   slprintf(name, sizeof(name) - 1, "%d",(int)uid);
4058   return(name);
4059 }
4060
4061
4062 /*******************************************************************
4063 turn a gid into a group name
4064 ********************************************************************/
4065
4066 char *gidtoname(gid_t gid)
4067 {
4068         static char name[40];
4069         struct group *grp = getgrgid(gid);
4070         if (grp) return(grp->gr_name);
4071         slprintf(name,sizeof(name) - 1, "%d",(int)gid);
4072         return(name);
4073 }
4074
4075 /*******************************************************************
4076 turn a user name into a uid
4077 ********************************************************************/
4078 uid_t nametouid(const char *name)
4079 {
4080         struct passwd *pass = getpwnam(name);
4081         if (pass) return(pass->pw_uid);
4082         return (uid_t)-1;
4083 }
4084
4085 /*******************************************************************
4086 something really nasty happened - panic!
4087 ********************************************************************/
4088 void smb_panic(char *why)
4089 {
4090         char *cmd = lp_panic_action();
4091         if (cmd && *cmd) {
4092                 system(cmd);
4093         }
4094         DEBUG(0,("PANIC: %s\n", why));
4095         exit(1);
4096 }
4097
4098
4099 /*******************************************************************
4100 a readdir wrapper which just returns the file name
4101 ********************************************************************/
4102 char *readdirname(void *p)
4103 {
4104         struct dirent *ptr;
4105         char *dname;
4106
4107         if (!p) return(NULL);
4108   
4109         ptr = (struct dirent *)readdir(p);
4110         if (!ptr) return(NULL);
4111
4112         dname = ptr->d_name;
4113
4114 #ifdef NEXT2
4115         if (telldir(p) < 0) return(NULL);
4116 #endif
4117
4118 #ifdef HAVE_BROKEN_READDIR
4119         /* using /usr/ucb/cc is BAD */
4120         dname = dname - 2;
4121 #endif
4122
4123         {
4124                 static pstring buf;
4125                 memcpy(buf, dname, NAMLEN(ptr)+1);
4126                 unix_to_dos(buf, True);
4127                 dname = buf;
4128         }
4129
4130         return(dname);
4131 }
4132
4133 /*******************************************************************
4134  Utility function used to decide if the last component 
4135  of a path matches a (possibly wildcarded) entry in a namelist.
4136 ********************************************************************/
4137
4138 BOOL is_in_path(char *name, name_compare_entry *namelist)
4139 {
4140   pstring last_component;
4141   char *p;
4142
4143   DEBUG(8, ("is_in_path: %s\n", name));
4144
4145   /* if we have no list it's obviously not in the path */
4146   if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) 
4147   {
4148     DEBUG(8,("is_in_path: no name list.\n"));
4149     return False;
4150   }
4151
4152   /* Get the last component of the unix name. */
4153   p = strrchr(name, '/');
4154   strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
4155   last_component[sizeof(last_component)-1] = '\0'; 
4156
4157   for(; namelist->name != NULL; namelist++)
4158   {
4159     if(namelist->is_wild)
4160     {
4161       /* 
4162        * Look for a wildcard match. Use the old
4163        * 'unix style' mask match, rather than the
4164        * new NT one.
4165        */
4166       if (unix_mask_match(last_component, namelist->name, case_sensitive, False))
4167       {
4168          DEBUG(8,("is_in_path: mask match succeeded\n"));
4169          return True;
4170       }
4171     }
4172     else
4173     {
4174       if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
4175        (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0)))
4176         {
4177          DEBUG(8,("is_in_path: match succeeded\n"));
4178          return True;
4179         }
4180     }
4181   }
4182   DEBUG(8,("is_in_path: match not found\n"));
4183  
4184   return False;
4185 }
4186
4187 /*******************************************************************
4188  Strip a '/' separated list into an array of 
4189  name_compare_enties structures suitable for 
4190  passing to is_in_path(). We do this for
4191  speed so we can pre-parse all the names in the list 
4192  and don't do it for each call to is_in_path().
4193  namelist is modified here and is assumed to be 
4194  a copy owned by the caller.
4195  We also check if the entry contains a wildcard to
4196  remove a potentially expensive call to mask_match
4197  if possible.
4198 ********************************************************************/
4199  
4200 void set_namearray(name_compare_entry **ppname_array, char *namelist)
4201 {
4202   char *name_end;
4203   char *nameptr = namelist;
4204   int num_entries = 0;
4205   int i;
4206
4207   (*ppname_array) = NULL;
4208
4209   if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0'))) 
4210     return;
4211
4212   /* We need to make two passes over the string. The
4213      first to count the number of elements, the second
4214      to split it.
4215    */
4216   while(*nameptr) 
4217     {
4218       if ( *nameptr == '/' ) 
4219         {
4220           /* cope with multiple (useless) /s) */
4221           nameptr++;
4222           continue;
4223         }
4224       /* find the next / */
4225       name_end = strchr(nameptr, '/');
4226
4227       /* oops - the last check for a / didn't find one. */
4228       if (name_end == NULL)
4229         break;
4230
4231       /* next segment please */
4232       nameptr = name_end + 1;
4233       num_entries++;
4234     }
4235
4236   if(num_entries == 0)
4237     return;
4238
4239   if(( (*ppname_array) = (name_compare_entry *)malloc( 
4240            (num_entries + 1) * sizeof(name_compare_entry))) == NULL)
4241         {
4242     DEBUG(0,("set_namearray: malloc fail\n"));
4243     return;
4244         }
4245
4246   /* Now copy out the names */
4247   nameptr = namelist;
4248   i = 0;
4249   while(*nameptr)
4250              {
4251       if ( *nameptr == '/' ) 
4252       {
4253           /* cope with multiple (useless) /s) */
4254           nameptr++;
4255           continue;
4256       }
4257       /* find the next / */
4258       if ((name_end = strchr(nameptr, '/')) != NULL) 
4259       {
4260           *name_end = 0;
4261          }
4262
4263       /* oops - the last check for a / didn't find one. */
4264       if(name_end == NULL) 
4265         break;
4266
4267       (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
4268                                 (strchr( nameptr, '*')!=NULL));
4269       if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
4270       {
4271         DEBUG(0,("set_namearray: malloc fail (1)\n"));
4272         return;
4273       }
4274
4275       /* next segment please */
4276       nameptr = name_end + 1;
4277       i++;
4278     }
4279   
4280   (*ppname_array)[i].name = NULL;
4281
4282   return;
4283 }
4284
4285 /****************************************************************************
4286 routine to free a namearray.
4287 ****************************************************************************/
4288
4289 void free_namearray(name_compare_entry *name_array)
4290 {
4291   if(name_array == 0)
4292     return;
4293
4294   if(name_array->name != NULL)
4295     free(name_array->name);
4296
4297   free((char *)name_array);
4298 }
4299
4300 /****************************************************************************
4301 routine to do file locking
4302 ****************************************************************************/
4303 BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
4304 {
4305 #if HAVE_FCNTL_LOCK
4306   SMB_STRUCT_FLOCK lock;
4307   int ret;
4308
4309   if(lp_ole_locking_compat()) {
4310     SMB_OFF_T mask = ((SMB_OFF_T)0xC) << (SMB_OFF_T_BITS-4);
4311     SMB_OFF_T mask2= ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4);
4312
4313     /* make sure the count is reasonable, we might kill the lockd otherwise */
4314     count &= ~mask;
4315
4316     /* the offset is often strange - remove 2 of its bits if either of
4317        the top two bits are set. Shift the top ones by two bits. This
4318        still allows OLE2 apps to operate, but should stop lockd from
4319        dieing */
4320     if ((offset & mask) != 0)
4321       offset = (offset & ~mask) | (((offset & mask) >> 2) & mask2);
4322   } else {
4323     SMB_OFF_T mask = ((SMB_OFF_T)0x8) << (SMB_OFF_T_BITS-4);
4324     SMB_OFF_T neg_mask = ~mask;
4325
4326     /* interpret negative counts as large numbers */
4327     if (count < 0)
4328       count &= ~mask;
4329
4330     /* no negative offsets */
4331     if(offset < 0)
4332       offset &= ~mask;
4333
4334     /* count + offset must be in range */
4335     while ((offset < 0 || (offset + count < 0)) && mask)
4336     {
4337       offset &= ~mask;
4338       mask = ((mask >> 1) & neg_mask);
4339     }
4340   }
4341
4342   DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
4343
4344   lock.l_type = type;
4345   lock.l_whence = SEEK_SET;
4346   lock.l_start = offset;
4347   lock.l_len = count;
4348   lock.l_pid = 0;
4349
4350   errno = 0;
4351
4352   ret = fcntl(fd,op,&lock);
4353   if (errno == EFBIG)
4354   {
4355     if( DEBUGLVL( 0 ))
4356     {
4357       dbgtext("fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count);
4358       dbgtext("a 'file too large' error. This can happen when using 64 bit lock offsets\n");
4359       dbgtext("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n");
4360     }
4361     /* 32 bit NFS file system, retry with smaller offset */
4362     errno = 0;
4363     lock.l_len = count & 0xffffffff;
4364     ret = fcntl(fd,op,&lock);
4365   }
4366
4367   if (errno != 0)
4368     DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
4369
4370   /* a lock query */
4371   if (op == SMB_F_GETLK)
4372   {
4373     if ((ret != -1) &&
4374         (lock.l_type != F_UNLCK) && 
4375         (lock.l_pid != 0) && 
4376         (lock.l_pid != getpid()))
4377     {
4378       DEBUG(3,("fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
4379       return(True);
4380     }
4381
4382     /* it must be not locked or locked by me */
4383     return(False);
4384   }
4385
4386   /* a lock set or unset */
4387   if (ret == -1)
4388   {
4389     DEBUG(3,("lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
4390           (double)offset,(double)count,op,type,strerror(errno)));
4391
4392     /* perhaps it doesn't support this sort of locking?? */
4393     if (errno == EINVAL)
4394     {
4395       DEBUG(3,("locking not supported? returning True\n"));
4396       return(True);
4397     }
4398
4399     return(False);
4400   }
4401
4402   /* everything went OK */
4403   DEBUG(8,("Lock call successful\n"));
4404
4405   return(True);
4406 #else
4407   return(False);
4408 #endif
4409 }
4410
4411 /*******************************************************************
4412 is the name specified one of my netbios names
4413 returns true is it is equal, false otherwise
4414 ********************************************************************/
4415 BOOL is_myname(char *s)
4416 {
4417   int n;
4418   BOOL ret = False;
4419
4420   for (n=0; my_netbios_names[n]; n++) {
4421     if (strequal(my_netbios_names[n], s))
4422       ret=True;
4423   }
4424   DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
4425   return(ret);
4426 }
4427
4428 /*******************************************************************
4429 set the horrid remote_arch string based on an enum.
4430 ********************************************************************/
4431 void set_remote_arch(enum remote_arch_types type)
4432 {
4433   ra_type = type;
4434   switch( type )
4435   {
4436   case RA_WFWG:
4437     fstrcpy(remote_arch, "WfWg");
4438     return;
4439   case RA_OS2:
4440     fstrcpy(remote_arch, "OS2");
4441     return;
4442   case RA_WIN95:
4443     fstrcpy(remote_arch, "Win95");
4444     return;
4445   case RA_WINNT:
4446     fstrcpy(remote_arch, "WinNT");
4447     return;
4448   case RA_SAMBA:
4449     fstrcpy(remote_arch,"Samba");
4450     return;
4451   default:
4452     ra_type = RA_UNKNOWN;
4453     fstrcpy(remote_arch, "UNKNOWN");
4454     break;
4455   }
4456 }
4457
4458 /*******************************************************************
4459  Get the remote_arch type.
4460 ********************************************************************/
4461 enum remote_arch_types get_remote_arch(void)
4462 {
4463   return ra_type;
4464 }
4465
4466
4467 /*******************************************************************
4468 skip past some unicode strings in a buffer
4469 ********************************************************************/
4470 char *skip_unicode_string(char *buf,int n)
4471 {
4472   while (n--)
4473   {
4474     while (*buf)
4475       buf += 2;
4476     buf += 2;
4477   }
4478   return(buf);
4479 }
4480
4481 /*******************************************************************
4482 Return a ascii version of a unicode string
4483 Hack alert: uses fixed buffer(s) and only handles ascii strings
4484 ********************************************************************/
4485 #define MAXUNI 1024
4486 char *unistrn2(uint16 *buf, int len)
4487 {
4488         static char lbufs[8][MAXUNI];
4489         static int nexti;
4490         char *lbuf = lbufs[nexti];
4491         char *p;
4492
4493         nexti = (nexti+1)%8;
4494
4495         for (p = lbuf; *buf && p-lbuf < MAXUNI-2 && len > 0; len--, p++, buf++)
4496         {
4497                 *p = *buf;
4498         }
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         for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf++)
4519         {
4520                 *p = *buf;
4521         }
4522
4523         *p = 0;
4524         return lbuf;
4525 }
4526
4527 /*******************************************************************
4528 create a null-terminated unicode string from a null-terminated ascii string.
4529 return number of unicode chars copied, excluding the null character.
4530
4531 only handles ascii strings
4532 ********************************************************************/
4533 #define MAXUNI 1024
4534 int struni2(uint16 *p, char *buf)
4535 {
4536         int len = 0;
4537
4538         if (p == NULL) return 0;
4539
4540         if (buf != NULL)
4541         {
4542                 for (; *buf && len < MAXUNI-2; len++, p++, buf++)
4543                 {
4544                         *p = *buf;
4545                 }
4546         }
4547
4548         *p = 0;
4549
4550         return len;
4551 }
4552
4553 /*******************************************************************
4554 Return a ascii version of a unicode string
4555 Hack alert: uses fixed buffer(s) and only handles ascii strings
4556 ********************************************************************/
4557 #define MAXUNI 1024
4558 char *unistr(char *buf)
4559 {
4560         static char lbufs[8][MAXUNI];
4561         static int nexti;
4562         char *lbuf = lbufs[nexti];
4563         char *p;
4564
4565         nexti = (nexti+1)%8;
4566
4567         for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf += 2)
4568         {
4569                 *p = *buf;
4570         }
4571         *p = 0;
4572         return lbuf;
4573 }
4574
4575
4576 /*******************************************************************
4577 strcpy for unicode strings.  returns length (in num of wide chars)
4578 ********************************************************************/
4579 int unistrcpy(char *dst, char *src)
4580 {
4581         int num_wchars = 0;
4582
4583         while (*src)
4584         {
4585                 *dst++ = *src++;
4586                 *dst++ = *src++;
4587                 num_wchars++;
4588         }
4589         *dst++ = 0;
4590         *dst++ = 0;
4591
4592         return num_wchars;
4593 }
4594
4595 /*******************************************************************
4596 safe string copy into a known length string. maxlength does not
4597 include the terminating zero.
4598 ********************************************************************/
4599 char *safe_strcpy(char *dest,const char *src, int maxlength)
4600 {
4601     int len;
4602
4603     if (!dest) {
4604         DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
4605         return NULL;
4606     }
4607
4608     if (!src) {
4609         *dest = 0;
4610         return dest;
4611     }  
4612
4613     len = strlen(src);
4614
4615     if (len > maxlength) {
4616             DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
4617                      len-maxlength, src));
4618             len = maxlength;
4619     }
4620       
4621     memcpy(dest, src, len);
4622     dest[len] = 0;
4623     return dest;
4624 }  
4625
4626 /*******************************************************************
4627 safe string cat into a string. maxlength does not
4628 include the terminating zero.
4629 ********************************************************************/
4630 char *safe_strcat(char *dest, char *src, int maxlength)
4631 {
4632     int src_len, dest_len;
4633
4634     if (!dest) {
4635         DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
4636         return NULL;
4637     }
4638
4639     if (!src) {
4640         return dest;
4641     }  
4642
4643     src_len = strlen(src);
4644     dest_len = strlen(dest);
4645
4646     if (src_len + dest_len > maxlength) {
4647             DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
4648                      src_len + dest_len - maxlength, src));
4649             src_len = maxlength - dest_len;
4650     }
4651       
4652     memcpy(&dest[dest_len], src, src_len);
4653     dest[dest_len + src_len] = 0;
4654     return dest;
4655 }
4656
4657 /*******************************************************************
4658 align a pointer to a multiple of 2 bytes
4659 ********************************************************************/
4660 char *align2(char *q, char *base)
4661 {
4662         if ((q - base) & 1)
4663         {
4664                 q++;
4665         }
4666         return q;
4667 }
4668
4669 void print_asc(int level, unsigned char *buf,int len)
4670 {
4671         int i;
4672         for (i=0;i<len;i++)
4673                 DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
4674 }
4675
4676 void dump_data(int level,char *buf1,int len)
4677 {
4678   unsigned char *buf = (unsigned char *)buf1;
4679   int i=0;
4680   if (len<=0) return;
4681
4682   DEBUG(level,("[%03X] ",i));
4683   for (i=0;i<len;) {
4684     DEBUG(level,("%02X ",(int)buf[i]));
4685     i++;
4686     if (i%8 == 0) DEBUG(level,(" "));
4687     if (i%16 == 0) {      
4688       print_asc(level,&buf[i-16],8); DEBUG(level,(" "));
4689       print_asc(level,&buf[i-8],8); DEBUG(level,("\n"));
4690       if (i<len) DEBUG(level,("[%03X] ",i));
4691     }
4692   }
4693   if (i%16) {
4694     int n;
4695
4696     n = 16 - (i%16);
4697     DEBUG(level,(" "));
4698     if (n>8) DEBUG(level,(" "));
4699     while (n--) DEBUG(level,("   "));
4700
4701     n = MIN(8,i%16);
4702     print_asc(level,&buf[i-(i%16)],n); DEBUG(level,(" "));
4703     n = (i%16) - n;
4704     if (n>0) print_asc(level,&buf[i-n],n); 
4705     DEBUG(level,("\n"));    
4706   }
4707 }
4708
4709 char *tab_depth(int depth)
4710 {
4711         static pstring spaces;
4712         memset(spaces, ' ', depth * 4);
4713         spaces[depth * 4] = 0;
4714         return spaces;
4715 }
4716
4717 /*****************************************************************
4718  Convert a SID to an ascii string.
4719 *****************************************************************/
4720
4721 char *sid_to_string(pstring sidstr_out, DOM_SID *sid)
4722 {
4723   char subauth[16];
4724   int i;
4725   /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
4726   uint32 ia = (sid->id_auth[5]) +
4727               (sid->id_auth[4] << 8 ) +
4728               (sid->id_auth[3] << 16) +
4729               (sid->id_auth[2] << 24);
4730
4731   slprintf(sidstr_out, sizeof(pstring) - 1, "S-%d-%d", sid->sid_rev_num, ia);
4732
4733   for (i = 0; i < sid->num_auths; i++)
4734   {
4735     slprintf(subauth, sizeof(subauth)-1, "-%d", sid->sub_auths[i]);
4736     pstrcat(sidstr_out, subauth);
4737   }
4738
4739   DEBUG(7,("sid_to_string returning %s\n", sidstr_out));
4740   return sidstr_out;
4741 }
4742
4743 /*****************************************************************
4744  Convert a string to a SID. Returns True on success, False on fail.
4745 *****************************************************************/  
4746    
4747 BOOL string_to_sid(DOM_SID *sidout, char *sidstr)
4748 {
4749   pstring tok;
4750   char *p = sidstr;
4751   /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
4752   uint32 ia;
4753
4754   memset((char *)sidout, '\0', sizeof(DOM_SID));
4755
4756   if(StrnCaseCmp( sidstr, "S-", 2)) {
4757     DEBUG(0,("string_to_sid: Sid %s does not start with 'S-'.\n", sidstr));
4758     return False;
4759   }
4760
4761   p += 2;
4762   if(!next_token(&p, tok, "-", sizeof(tok))) {
4763     DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr));
4764     return False;
4765   }
4766
4767   /* Get the revision number. */
4768   sidout->sid_rev_num = atoi(tok);
4769
4770   if(!next_token(&p, tok, "-", sizeof(tok))) {
4771     DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr));
4772     return False;
4773   }
4774
4775   /* identauth in decimal should be <  2^32 */
4776   ia = atoi(tok);
4777
4778   /* NOTE - the ia value is in big-endian format. */
4779   sidout->id_auth[0] = 0;
4780   sidout->id_auth[1] = 0;
4781   sidout->id_auth[2] = (ia & 0xff000000) >> 24;
4782   sidout->id_auth[3] = (ia & 0x00ff0000) >> 16;
4783   sidout->id_auth[4] = (ia & 0x0000ff00) >> 8;
4784   sidout->id_auth[5] = (ia & 0x000000ff);
4785
4786   sidout->num_auths = 0;
4787
4788   while(next_token(&p, tok, "-", sizeof(tok)) && 
4789         sidout->num_auths < MAXSUBAUTHS) {
4790     /* 
4791      * NOTE - the subauths are in native machine-endian format. They
4792      * are converted to little-endian when linearized onto the wire.
4793      */
4794     sidout->sub_auths[sidout->num_auths++] = atoi(tok);
4795   }
4796
4797   DEBUG(7,("string_to_sid: converted SID %s ok\n", sidstr));
4798
4799   return True;
4800 }
4801
4802 /*****************************************************************************
4803  * Provide a checksum on a string
4804  *
4805  *  Input:  s - the nul-terminated character string for which the checksum
4806  *              will be calculated.
4807  *
4808  *  Output: The checksum value calculated for s.
4809  *
4810  * ****************************************************************************
4811  */
4812 int str_checksum(const char *s)
4813 {
4814         int res = 0;
4815         int c;
4816         int i=0;
4817         
4818         while(*s) {
4819                 c = *s;
4820                 res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
4821                 s++;
4822                 i++;
4823         }
4824         return(res);
4825 } /* str_checksum */
4826
4827
4828
4829 /*****************************************************************
4830 zero a memory area then free it. Used to catch bugs faster
4831 *****************************************************************/  
4832 void zero_free(void *p, size_t size)
4833 {
4834         memset(p, 0, size);
4835         free(p);
4836 }
4837
4838
4839 /*****************************************************************
4840 set our open file limit to a requested max and return the limit
4841 *****************************************************************/