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