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