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