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