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