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