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