added new smb.conf option "panic action". see my samba-technical
[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)
135 {
136   char *s;
137   BOOL quoted;
138
139   if (!ptr) ptr = &last_ptr;
140   if (!ptr) return(False);
141
142   s = *ptr;
143
144   /* default to simple separators */
145   if (!sep) sep = " \t\n\r";
146
147   /* find the first non sep char */
148   while(*s && strchr(sep,*s)) s++;
149
150   /* nothing left? */
151   if (! *s) return(False);
152
153   /* copy over the token */
154   for (quoted = False; *s && (quoted || !strchr(sep,*s)); s++)
155     {
156       if (*s == '\"') 
157         quoted = !quoted;
158       else
159         *buff++ = *s;
160     }
161
162   *ptr = (*s) ? s+1 : s;  
163   *buff = 0;
164   last_ptr = *ptr;
165
166   return(True);
167 }
168
169 /****************************************************************************
170 Convert list of tokens to array; dependent on above routine.
171 Uses last_ptr from above - bit of a hack.
172 ****************************************************************************/
173 char **toktocliplist(int *ctok, char *sep)
174 {
175   char *s=last_ptr;
176   int ictok=0;
177   char **ret, **iret;
178
179   if (!sep) sep = " \t\n\r";
180
181   while(*s && strchr(sep,*s)) s++;
182
183   /* nothing left? */
184   if (!*s) return(NULL);
185
186   do {
187     ictok++;
188     while(*s && (!strchr(sep,*s))) s++;
189     while(*s && strchr(sep,*s)) *s++=0;
190   } while(*s);
191
192   *ctok=ictok;
193   s=last_ptr;
194
195   if (!(ret=iret=malloc(ictok*sizeof(char *)))) return NULL;
196   
197   while(ictok--) {    
198     *iret++=s;
199     while(*s++);
200     while(!*s) s++;
201   }
202
203   return ret;
204 }
205
206
207 /* ************************************************************************* **
208  * Duplicate a block of memory.
209  * ************************************************************************* **
210  */
211 void *mem_dup( void *from, int size )
212   {
213   void *tmp;
214
215   tmp = malloc( size );
216   if( NULL != tmp )
217     (void)memcpy( tmp, from, size );
218   return( tmp );
219   } /* mem_dup */
220
221 /****************************************************************************
222 prompte a dptr (to make it recently used)
223 ****************************************************************************/
224 void array_promote(char *array,int elsize,int element)
225 {
226   char *p;
227   if (element == 0)
228     return;
229
230   p = (char *)malloc(elsize);
231
232   if (!p)
233     {
234       DEBUG(5,("Ahh! Can't malloc\n"));
235       return;
236     }
237   memcpy(p,array + element * elsize, elsize);
238   memmove(array + elsize,array,elsize*element);
239   memcpy(array,p,elsize);
240   free(p);
241 }
242
243 enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
244
245 struct
246 {
247   char *name;
248   int level;
249   int option;
250   int value;
251   int opttype;
252 } socket_options[] = {
253   {"SO_KEEPALIVE",      SOL_SOCKET,    SO_KEEPALIVE,    0,                 OPT_BOOL},
254   {"SO_REUSEADDR",      SOL_SOCKET,    SO_REUSEADDR,    0,                 OPT_BOOL},
255   {"SO_BROADCAST",      SOL_SOCKET,    SO_BROADCAST,    0,                 OPT_BOOL},
256 #ifdef TCP_NODELAY
257   {"TCP_NODELAY",       IPPROTO_TCP,   TCP_NODELAY,     0,                 OPT_BOOL},
258 #endif
259 #ifdef IPTOS_LOWDELAY
260   {"IPTOS_LOWDELAY",    IPPROTO_IP,    IP_TOS,          IPTOS_LOWDELAY,    OPT_ON},
261 #endif
262 #ifdef IPTOS_THROUGHPUT
263   {"IPTOS_THROUGHPUT",  IPPROTO_IP,    IP_TOS,          IPTOS_THROUGHPUT,  OPT_ON},
264 #endif
265 #ifdef SO_SNDBUF
266   {"SO_SNDBUF",         SOL_SOCKET,    SO_SNDBUF,       0,                 OPT_INT},
267 #endif
268 #ifdef SO_RCVBUF
269   {"SO_RCVBUF",         SOL_SOCKET,    SO_RCVBUF,       0,                 OPT_INT},
270 #endif
271 #ifdef SO_SNDLOWAT
272   {"SO_SNDLOWAT",       SOL_SOCKET,    SO_SNDLOWAT,     0,                 OPT_INT},
273 #endif
274 #ifdef SO_RCVLOWAT
275   {"SO_RCVLOWAT",       SOL_SOCKET,    SO_RCVLOWAT,     0,                 OPT_INT},
276 #endif
277 #ifdef SO_SNDTIMEO
278   {"SO_SNDTIMEO",       SOL_SOCKET,    SO_SNDTIMEO,     0,                 OPT_INT},
279 #endif
280 #ifdef SO_RCVTIMEO
281   {"SO_RCVTIMEO",       SOL_SOCKET,    SO_RCVTIMEO,     0,                 OPT_INT},
282 #endif
283   {NULL,0,0,0,0}};
284
285         
286
287 /****************************************************************************
288 set user socket options
289 ****************************************************************************/
290 void set_socket_options(int fd, char *options)
291 {
292   fstring tok;
293
294   while (next_token(&options,tok," \t,"))
295     {
296       int ret=0,i;
297       int value = 1;
298       char *p;
299       BOOL got_value = False;
300
301       if ((p = strchr(tok,'=')))
302         {
303           *p = 0;
304           value = atoi(p+1);
305           got_value = True;
306         }
307
308       for (i=0;socket_options[i].name;i++)
309         if (strequal(socket_options[i].name,tok))
310           break;
311
312       if (!socket_options[i].name)
313         {
314           DEBUG(0,("Unknown socket option %s\n",tok));
315           continue;
316         }
317
318       switch (socket_options[i].opttype)
319         {
320         case OPT_BOOL:
321         case OPT_INT:
322           ret = setsockopt(fd,socket_options[i].level,
323                            socket_options[i].option,(char *)&value,sizeof(int));
324           break;
325
326         case OPT_ON:
327           if (got_value)
328             DEBUG(0,("syntax error - %s does not take a value\n",tok));
329
330           {
331             int on = socket_options[i].value;
332             ret = setsockopt(fd,socket_options[i].level,
333                              socket_options[i].option,(char *)&on,sizeof(int));
334           }
335           break;          
336         }
337       
338       if (ret != 0)
339         DEBUG(0,("Failed to set socket option %s\n",tok));
340     }
341 }
342
343
344
345 /****************************************************************************
346   close the socket communication
347 ****************************************************************************/
348 void close_sockets(void )
349 {
350 #ifdef WITH_SSL
351   sslutil_disconnect(Client);
352 #endif /* WITH_SSL */
353
354   close(Client);
355   Client = 0;
356 }
357
358 /****************************************************************************
359 determine whether we are in the specified group
360 ****************************************************************************/
361 BOOL in_group(gid_t group, int current_gid, int ngroups, GID_T *groups)
362 {
363         int i;
364
365         if (group == current_gid) return(True);
366
367         for (i=0;i<ngroups;i++)
368                 if (group == groups[i])
369                         return(True);
370
371         return(False);
372 }
373
374 /****************************************************************************
375 this is a safer strcpy(), meant to prevent core dumps when nasty things happen
376 ****************************************************************************/
377 char *StrCpy(char *dest,char *src)
378 {
379   char *d = dest;
380
381   /* I don't want to get lazy with these ... */
382   if (!dest || !src) {
383           DEBUG(0,("ERROR: NULL StrCpy() called!\n"));
384           smb_panic("invalid StrCpy");
385   }
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(&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(&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(&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(&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(&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))
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