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