includes.h: SunOS doesn't have strcasecmp, solaris versions prior to 2.6 don't
[samba.git] / source / lib / util.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Samba utility functions
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 #if (defined(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       pstrcpy(fname,debugf);
182       if (lp_loaded() && (*lp_logfile()))
183         pstrcpy(fname,lp_logfile());
184
185       if (!strcsequal(fname,debugf) || !dbf || !file_exist(debugf,NULL))
186         {
187           int oldumask = umask(022);
188           pstrcpy(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   fstring 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)slprintf( buf, sizeof(buf) - 1, "%-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 fstring attrstr;
873
874   attrstr[0] = 0;
875
876   if (mode & aVOLID) fstrcat(attrstr,"V");
877   if (mode & aDIR) fstrcat(attrstr,"D");
878   if (mode & aARCH) fstrcat(attrstr,"A");
879   if (mode & aHIDDEN) fstrcat(attrstr,"H");
880   if (mode & aSYSTEM) fstrcat(attrstr,"S");
881   if (mode & aRONLY) fstrcat(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       pstrcpy(fname,".");
1248       pstrcat(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       pstrcat(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       pstrcpy(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       pstrcat(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                     pstrcpy (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   pstrcpy(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         pstrcpy(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       pstrcat(newname,"/");
1721       pstrcat(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     pstrcpy(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       pstrcpy(mext,"");
1806       if (strlen(mbeg) > 8)
1807         {
1808           pstrcpy(mext,mbeg + 8);
1809           mbeg[8] = 0;
1810         }
1811     }
1812
1813   if (*mbeg == 0)
1814     pstrcpy(mbeg,"????????");
1815   if ((*mext == 0) && doext && !hasdot)
1816     pstrcpy(mext,"???");
1817
1818   if (strequal(mbeg,"*") && *mext==0) 
1819     pstrcpy(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) pstrcat(Mask,"\\");
1828   pstrcat(Mask,mbeg);
1829   pstrcat(Mask,".");
1830   pstrcat(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   pstrcpy(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       pstrcpy(*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     pstrcat(p2,".");
3061   }
3062
3063 /*
3064   if (!strchr(p1,'.')) {
3065     pstrcat(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)pstrcpy( &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     pstrcpy(buf,path);
3314   else
3315     {
3316       *p = 0;
3317       pstrcpy(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     pstrcpy(buf,path);
3334   else
3335     pstrcpy(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   int len;
3374   if (!s) return(NULL);
3375   ret = (char *)malloc((len = strlen(s))+1);
3376   if (!ret) return(NULL);
3377   safe_strcpy(ret,s,len);
3378   return(ret);
3379 }
3380 #endif
3381
3382
3383 /****************************************************************************
3384   Signal handler for SIGPIPE (write on a disconnected socket) 
3385 ****************************************************************************/
3386 void Abort(void )
3387 {
3388   DEBUG(0,("Probably got SIGPIPE\nExiting\n"));
3389   exit(2);
3390 }
3391
3392 /****************************************************************************
3393 get my own name and IP
3394 ****************************************************************************/
3395 BOOL get_myname(char *my_name,struct in_addr *ip)
3396 {
3397   struct hostent *hp;
3398   pstring hostname;
3399
3400   *hostname = 0;
3401
3402   /* get my host name */
3403   if (gethostname(hostname, MAXHOSTNAMELEN) == -1) 
3404     {
3405       DEBUG(0,("gethostname failed\n"));
3406       return False;
3407     } 
3408
3409   /* get host info */
3410   if ((hp = Get_Hostbyname(hostname)) == 0) 
3411     {
3412       DEBUG(0,( "Get_Hostbyname: Unknown host %s\n",hostname));
3413       return False;
3414     }
3415
3416   if (my_name)
3417     {
3418       /* split off any parts after an initial . */
3419       char *p = strchr(hostname,'.');
3420       if (p) *p = 0;
3421
3422       fstrcpy(my_name,hostname);
3423     }
3424
3425   if (ip)
3426     putip((char *)ip,(char *)hp->h_addr);
3427
3428   return(True);
3429 }
3430
3431
3432 /****************************************************************************
3433 true if two IP addresses are equal
3434 ****************************************************************************/
3435 BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
3436 {
3437   uint32 a1,a2;
3438   a1 = ntohl(ip1.s_addr);
3439   a2 = ntohl(ip2.s_addr);
3440   return(a1 == a2);
3441 }
3442
3443
3444 /****************************************************************************
3445 open a socket of the specified type, port and address for incoming data
3446 ****************************************************************************/
3447 int open_socket_in(int type, int port, int dlevel,uint32 socket_addr)
3448 {
3449   struct hostent *hp;
3450   struct sockaddr_in sock;
3451   pstring host_name;
3452   int res;
3453
3454   /* get my host name */
3455   if (gethostname(host_name, MAXHOSTNAMELEN) == -1) 
3456     { DEBUG(0,("gethostname failed\n")); return -1; } 
3457
3458   /* get host info */
3459   if ((hp = Get_Hostbyname(host_name)) == 0) 
3460     {
3461       DEBUG(0,( "Get_Hostbyname: Unknown host %s\n",host_name));
3462       return -1;
3463     }
3464   
3465   bzero((char *)&sock,sizeof(sock));
3466   memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
3467 #if defined(__FreeBSD__) || defined(NETBSD) || defined(__OpenBSD__) /* XXX not the right ifdef */
3468   sock.sin_len = sizeof(sock);
3469 #endif
3470   sock.sin_port = htons( port );
3471   sock.sin_family = hp->h_addrtype;
3472   sock.sin_addr.s_addr = socket_addr;
3473   res = socket(hp->h_addrtype, type, 0);
3474   if (res == -1) 
3475     { DEBUG(0,("socket failed\n")); return -1; }
3476
3477   {
3478     int one=1;
3479     setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
3480   }
3481
3482   /* now we've got a socket - we need to bind it */
3483   if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) 
3484     { 
3485       if (port) {
3486         if (port == SMB_PORT || port == NMB_PORT)
3487           DEBUG(dlevel,("bind failed on port %d socket_addr=%s (%s)\n",
3488                         port,inet_ntoa(sock.sin_addr),strerror(errno))); 
3489         close(res); 
3490
3491         if (dlevel > 0 && port < 1000)
3492           port = 7999;
3493
3494         if (port >= 1000 && port < 9000)
3495           return(open_socket_in(type,port+1,dlevel,socket_addr));
3496       }
3497
3498       return(-1); 
3499     }
3500   DEBUG(3,("bind succeeded on port %d\n",port));
3501
3502   return res;
3503 }
3504
3505
3506 /****************************************************************************
3507   create an outgoing socket
3508   **************************************************************************/
3509 int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
3510 {
3511   struct sockaddr_in sock_out;
3512   int res,ret;
3513   int connect_loop = 250; /* 250 milliseconds */
3514   int loops = (timeout * 1000) / connect_loop;
3515
3516   /* create a socket to write to */
3517   res = socket(PF_INET, type, 0);
3518   if (res == -1) 
3519     { DEBUG(0,("socket error\n")); return -1; }
3520
3521   if (type != SOCK_STREAM) return(res);
3522   
3523   bzero((char *)&sock_out,sizeof(sock_out));
3524   putip((char *)&sock_out.sin_addr,(char *)addr);
3525   
3526   sock_out.sin_port = htons( port );
3527   sock_out.sin_family = PF_INET;
3528
3529   /* set it non-blocking */
3530   set_blocking(res,False);
3531
3532   DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port));
3533   
3534   /* and connect it to the destination */
3535 connect_again:
3536   ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out));
3537
3538   /* Some systems return EAGAIN when they mean EINPROGRESS */
3539   if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
3540         errno == EAGAIN) && loops--) {
3541     msleep(connect_loop);
3542     goto connect_again;
3543   }
3544
3545   if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
3546          errno == EAGAIN)) {
3547       DEBUG(1,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port));
3548       close(res);
3549       return -1;
3550   }
3551
3552 #ifdef EISCONN
3553   if (ret < 0 && errno == EISCONN) {
3554     errno = 0;
3555     ret = 0;
3556   }
3557 #endif
3558
3559   if (ret < 0) {
3560     DEBUG(1,("error connecting to %s:%d (%s)\n",
3561              inet_ntoa(*addr),port,strerror(errno)));
3562     return -1;
3563   }
3564
3565   /* set it blocking again */
3566   set_blocking(res,True);
3567
3568   return res;
3569 }
3570
3571
3572 /****************************************************************************
3573 interpret a protocol description string, with a default
3574 ****************************************************************************/
3575 int interpret_protocol(char *str,int def)
3576 {
3577   if (strequal(str,"NT1"))
3578     return(PROTOCOL_NT1);
3579   if (strequal(str,"LANMAN2"))
3580     return(PROTOCOL_LANMAN2);
3581   if (strequal(str,"LANMAN1"))
3582     return(PROTOCOL_LANMAN1);
3583   if (strequal(str,"CORE"))
3584     return(PROTOCOL_CORE);
3585   if (strequal(str,"COREPLUS"))
3586     return(PROTOCOL_COREPLUS);
3587   if (strequal(str,"CORE+"))
3588     return(PROTOCOL_COREPLUS);
3589   
3590   DEBUG(0,("Unrecognised protocol level %s\n",str));
3591   
3592   return(def);
3593 }
3594
3595 /****************************************************************************
3596 interpret a security level
3597 ****************************************************************************/
3598 int interpret_security(char *str,int def)
3599 {
3600   if (strequal(str,"SERVER"))
3601     return(SEC_SERVER);
3602   if (strequal(str,"USER"))
3603     return(SEC_USER);
3604   if (strequal(str,"SHARE"))
3605     return(SEC_SHARE);
3606   
3607   DEBUG(0,("Unrecognised security level %s\n",str));
3608   
3609   return(def);
3610 }
3611
3612
3613 /****************************************************************************
3614 interpret an internet address or name into an IP address in 4 byte form
3615 ****************************************************************************/
3616 uint32 interpret_addr(char *str)
3617 {
3618   struct hostent *hp;
3619   uint32 res;
3620   int i;
3621   BOOL pure_address = True;
3622
3623   if (strcmp(str,"0.0.0.0") == 0) return(0);
3624   if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
3625
3626   for (i=0; pure_address && str[i]; i++)
3627     if (!(isdigit(str[i]) || str[i] == '.')) 
3628       pure_address = False;
3629
3630   /* if it's in the form of an IP address then get the lib to interpret it */
3631   if (pure_address) {
3632     res = inet_addr(str);
3633   } else {
3634     /* otherwise assume it's a network name of some sort and use 
3635        Get_Hostbyname */
3636     if ((hp = Get_Hostbyname(str)) == 0) {
3637       DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
3638       return 0;
3639     }
3640     if(hp->h_addr == NULL) {
3641       DEBUG(3,("Get_Hostbyname: host address is invalid for host %s\n",str));
3642       return 0;
3643     }
3644     putip((char *)&res,(char *)hp->h_addr);
3645   }
3646
3647   if (res == (uint32)-1) return(0);
3648
3649   return(res);
3650 }
3651
3652 /*******************************************************************
3653   a convenient addition to interpret_addr()
3654   ******************************************************************/
3655 struct in_addr *interpret_addr2(char *str)
3656 {
3657   static struct in_addr ret;
3658   uint32 a = interpret_addr(str);
3659   ret.s_addr = a;
3660   return(&ret);
3661 }
3662
3663 /*******************************************************************
3664   check if an IP is the 0.0.0.0
3665   ******************************************************************/
3666 BOOL zero_ip(struct in_addr ip)
3667 {
3668   uint32 a;
3669   putip((char *)&a,(char *)&ip);
3670   return(a == 0);
3671 }
3672
3673
3674 /*******************************************************************
3675  matchname - determine if host name matches IP address 
3676  ******************************************************************/
3677 static BOOL matchname(char *remotehost,struct in_addr  addr)
3678 {
3679   struct hostent *hp;
3680   int     i;
3681   
3682   if ((hp = Get_Hostbyname(remotehost)) == 0) {
3683     DEBUG(0,("Get_Hostbyname(%s): lookup failure", remotehost));
3684     return False;
3685   } 
3686
3687   /*
3688    * Make sure that gethostbyname() returns the "correct" host name.
3689    * Unfortunately, gethostbyname("localhost") sometimes yields
3690    * "localhost.domain". Since the latter host name comes from the
3691    * local DNS, we just have to trust it (all bets are off if the local
3692    * DNS is perverted). We always check the address list, though.
3693    */
3694   
3695   if (strcasecmp(remotehost, hp->h_name)
3696       && strcasecmp(remotehost, "localhost")) {
3697     DEBUG(0,("host name/name mismatch: %s != %s",
3698              remotehost, hp->h_name));
3699     return False;
3700   }
3701         
3702   /* Look up the host address in the address list we just got. */
3703   for (i = 0; hp->h_addr_list[i]; i++) {
3704     if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
3705       return True;
3706   }
3707
3708   /*
3709    * The host name does not map to the original host address. Perhaps
3710    * someone has compromised a name server. More likely someone botched
3711    * it, but that could be dangerous, too.
3712    */
3713   
3714   DEBUG(0,("host name/address mismatch: %s != %s",
3715            inet_ntoa(addr), hp->h_name));
3716   return False;
3717 }
3718
3719 /*******************************************************************
3720  Reset the 'done' variables so after a client process is created
3721  from a fork call these calls will be re-done. This should be
3722  expanded if more variables need reseting.
3723  ******************************************************************/
3724
3725 static BOOL global_client_name_done = False;
3726 static BOOL global_client_addr_done = False;
3727
3728 void reset_globals_after_fork(void)
3729 {
3730   global_client_name_done = False;
3731   global_client_addr_done = False;
3732 }
3733  
3734 /*******************************************************************
3735  return the DNS name of the client 
3736  ******************************************************************/
3737 char *client_name(int fd)
3738 {
3739         struct sockaddr sa;
3740         struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
3741         int     length = sizeof(sa);
3742         static pstring name_buf;
3743         struct hostent *hp;
3744         static int last_fd=-1;
3745         
3746         if (global_client_name_done && last_fd == fd) 
3747                 return name_buf;
3748         
3749         last_fd = fd;
3750         global_client_name_done = False;
3751         
3752         pstrcpy(name_buf,"UNKNOWN");
3753         
3754         if (fd == -1) {
3755                 return name_buf;
3756         }
3757         
3758         if (getpeername(fd, &sa, &length) < 0) {
3759                 DEBUG(0,("getpeername failed\n"));
3760                 return name_buf;
3761         }
3762         
3763         /* Look up the remote host name. */
3764         if ((hp = gethostbyaddr((char *) &sockin->sin_addr,
3765                                 sizeof(sockin->sin_addr),
3766                                 AF_INET)) == 0) {
3767                 DEBUG(1,("Gethostbyaddr failed for %s\n",client_addr(fd)));
3768                 StrnCpy(name_buf,client_addr(fd),sizeof(name_buf) - 1);
3769         } else {
3770                 StrnCpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1);
3771                 if (!matchname(name_buf, sockin->sin_addr)) {
3772                         DEBUG(0,("Matchname failed on %s %s\n",name_buf,client_addr(fd)));
3773                         pstrcpy(name_buf,"UNKNOWN");
3774                 }
3775         }
3776         global_client_name_done = True;
3777         return name_buf;
3778 }
3779
3780 /*******************************************************************
3781  return the IP addr of the client as a string 
3782  ******************************************************************/
3783 char *client_addr(int fd)
3784 {
3785         struct sockaddr sa;
3786         struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
3787         int     length = sizeof(sa);
3788         static fstring addr_buf;
3789         static int last_fd = -1;
3790
3791         if (global_client_addr_done && fd == last_fd) 
3792                 return addr_buf;
3793
3794         last_fd = fd;
3795         global_client_addr_done = False;
3796
3797         fstrcpy(addr_buf,"0.0.0.0");
3798
3799         if (fd == -1) {
3800                 return addr_buf;
3801         }
3802         
3803         if (getpeername(fd, &sa, &length) < 0) {
3804                 DEBUG(0,("getpeername failed\n"));
3805                 return addr_buf;
3806         }
3807         
3808         fstrcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr));
3809         
3810         global_client_addr_done = True;
3811         return addr_buf;
3812 }
3813
3814 /*******************************************************************
3815  Patch from jkf@soton.ac.uk
3816  Split Luke's automount_server into YP lookup and string splitter
3817  so can easily implement automount_path(). 
3818  As we may end up doing both, cache the last YP result. 
3819 *******************************************************************/
3820
3821 #if (defined(NETGROUP) && defined(AUTOMOUNT))
3822 #ifdef NISPLUS
3823 static char *automount_lookup(char *user_name)
3824 {
3825   static fstring last_key = "";
3826   static pstring last_value = "";
3827  
3828   char *nis_map = (char *)lp_nis_home_map_name();
3829  
3830   char nis_domain[NIS_MAXNAMELEN + 1];
3831   char buffer[NIS_MAXATTRVAL + 1];
3832   nis_result *result;
3833   nis_object *object;
3834   entry_obj  *entry;
3835  
3836   strncpy(nis_domain, (char *)nis_local_directory(), NIS_MAXNAMELEN);
3837   nis_domain[NIS_MAXNAMELEN] = '\0';
3838  
3839   DEBUG(5, ("NIS+ Domain: %s\n", nis_domain));
3840  
3841   if (strcmp(user_name, last_key))
3842   {
3843     slprintf(buffer, sizeof(buffer)-1, "[%s=%s]%s.%s", "key", user_name, nis_map, nis_domain);
3844     DEBUG(5, ("NIS+ querystring: %s\n", buffer));
3845  
3846     if (result = nis_list(buffer, RETURN_RESULT, NULL, NULL))
3847     {
3848        if (result->status != NIS_SUCCESS)
3849       {
3850         DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
3851         fstrcpy(last_key, ""); pstrcpy(last_value, "");
3852       }
3853       else
3854       {
3855         object = result->objects.objects_val;
3856         if (object->zo_data.zo_type == ENTRY_OBJ)
3857         {
3858            entry = &object->zo_data.objdata_u.en_data;
3859            DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
3860            DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
3861  
3862            pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
3863            string_sub(last_value, "&", user_name);
3864            fstrcpy(last_key, user_name);
3865         }
3866       }
3867     }
3868     nis_freeresult(result);
3869   }
3870   DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
3871   return last_value;
3872 }
3873 #else /* NISPLUS */
3874 static char *automount_lookup(char *user_name)
3875 {
3876   static fstring last_key = "";
3877   static pstring last_value = "";
3878
3879   int nis_error;        /* returned by yp all functions */
3880   char *nis_result;     /* yp_match inits this */
3881   int nis_result_len;  /* and set this */
3882   char *nis_domain;     /* yp_get_default_domain inits this */
3883   char *nis_map = (char *)lp_nis_home_map_name();
3884
3885   if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
3886   {
3887     DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
3888     return last_value;
3889   }
3890
3891   DEBUG(5, ("NIS Domain: %s\n", nis_domain));
3892
3893   if (!strcmp(user_name, last_key))
3894   {
3895     nis_result = last_value;
3896     nis_result_len = strlen(last_value);
3897     nis_error = 0;
3898   }
3899   else
3900   {
3901     if ((nis_error = yp_match(nis_domain, nis_map,
3902                               user_name, strlen(user_name),
3903                               &nis_result, &nis_result_len)) != 0)
3904     {
3905       DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n", 
3906                yperr_string(nis_error), user_name, nis_map));
3907     }
3908     if (!nis_error && nis_result_len >= sizeof(pstring))
3909     {
3910       nis_result_len = sizeof(pstring)-1;
3911     }
3912     fstrcpy(last_key, user_name);
3913     strncpy(last_value, nis_result, nis_result_len);
3914     last_value[nis_result_len] = '\0';
3915   }
3916
3917   DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
3918   return last_value;
3919 }
3920 #endif /* NISPLUS */
3921 #endif
3922
3923 /*******************************************************************
3924  Patch from jkf@soton.ac.uk
3925  This is Luke's original function with the NIS lookup code
3926  moved out to a separate function.
3927 *******************************************************************/
3928
3929 char *automount_server(char *user_name)
3930 {
3931         static pstring server_name;
3932
3933         /* use the local machine name as the default */
3934         /* this will be the default if AUTOMOUNT is not used or fails */
3935         pstrcpy(server_name, local_machine);
3936
3937 #if (defined(NETGROUP) && defined (AUTOMOUNT))
3938
3939         if (lp_nis_home_map())
3940         {
3941                 int home_server_len;
3942                 char *automount_value = automount_lookup(user_name);
3943                 home_server_len = strcspn(automount_value,":");
3944                 DEBUG(5, ("NIS lookup succeeded.  Home server length: %d\n",home_server_len));
3945                 if (home_server_len > sizeof(pstring))
3946                 {
3947                         home_server_len = sizeof(pstring);
3948                 }
3949                 strncpy(server_name, automount_value, home_server_len);
3950                 server_name[home_server_len] = '\0';
3951         }
3952 #endif
3953
3954         DEBUG(4,("Home server: %s\n", server_name));
3955
3956         return server_name;
3957 }
3958
3959 /*******************************************************************
3960  Patch from jkf@soton.ac.uk
3961  Added this to implement %p (NIS auto-map version of %H)
3962 *******************************************************************/
3963
3964 char *automount_path(char *user_name)
3965 {
3966         static pstring server_path;
3967
3968         /* use the passwd entry as the default */
3969         /* this will be the default if AUTOMOUNT is not used or fails */
3970         /* pstrcpy() copes with get_home_dir() returning NULL */
3971         pstrcpy(server_path, get_home_dir(user_name));
3972
3973 #if (defined(NETGROUP) && defined (AUTOMOUNT))
3974
3975         if (lp_nis_home_map())
3976         {
3977                 char *home_path_start;
3978                 char *automount_value = automount_lookup(user_name);
3979                 home_path_start = strchr(automount_value,':');
3980                 if (home_path_start != NULL)
3981                 {
3982                   DEBUG(5, ("NIS lookup succeeded.  Home path is: %s\n",
3983                         home_path_start?(home_path_start+1):""));
3984                   pstrcpy(server_path, home_path_start+1);
3985                 }
3986         }
3987 #endif
3988
3989         DEBUG(4,("Home server path: %s\n", server_path));
3990
3991         return server_path;
3992 }
3993
3994
3995 /*******************************************************************
3996 sub strings with useful parameters
3997 Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
3998 Paul Rippin <pr3245@nopc.eurostat.cec.be>
3999 ********************************************************************/
4000 void standard_sub_basic(char *str)
4001 {
4002         char *s, *p;
4003         char pidstr[10];
4004         struct passwd *pass;
4005         char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user;
4006
4007         for (s = str ; s && *s && (p = strchr(s,'%')); s = p )
4008         {
4009                 switch (*(p+1))
4010                 {
4011                         case 'G' :
4012                         {
4013                                 if ((pass = Get_Pwnam(username,False))!=NULL)
4014                                 {
4015                                         string_sub(p,"%G",gidtoname(pass->pw_gid));
4016                                 }
4017                                 else
4018                                 {
4019                                         p += 2;
4020                                 }
4021                                 break;
4022                         }
4023                         case 'N' : string_sub(p,"%N", automount_server(username)); break;
4024                         case 'I' : string_sub(p,"%I", client_addr(Client)); break;
4025                         case 'L' : string_sub(p,"%L", local_machine); break;
4026                         case 'M' : string_sub(p,"%M", client_name(Client)); break;
4027                         case 'R' : string_sub(p,"%R", remote_proto); break;
4028                         case 'T' : string_sub(p,"%T", timestring()); break;
4029                         case 'U' : string_sub(p,"%U", username); break;
4030                         case 'a' : string_sub(p,"%a", remote_arch); break;
4031                         case 'd' :
4032                         {
4033                                 slprintf(pidstr,sizeof(pidstr) - 1, "%d",(int)getpid());
4034                                 string_sub(p,"%d", pidstr);
4035                                 break;
4036                         }
4037                         case 'h' : string_sub(p,"%h", myhostname); break;
4038                         case 'm' : string_sub(p,"%m", remote_machine); break;
4039                         case 'v' : string_sub(p,"%v", VERSION); break;
4040                         case '$' : /* Expand environment variables */
4041                         {
4042                           /* Contributed by Branko Cibej <branko.cibej@hermes.si> */
4043                           fstring envname;
4044                           char *envval;
4045                           char *q, *r;
4046                           int copylen;
4047  
4048                           if (*(p+2) != '(') { p+=2; break; }
4049                           if ((q = strchr(p,')')) == NULL)
4050                           {
4051                             DEBUG(0,("standard_sub_basic: Unterminated environment \
4052 variable [%s]\n", p));
4053                             p+=2; break;
4054                           }
4055  
4056                           r = p+3;
4057                           copylen = MIN((q-r),(sizeof(envname)-1));
4058                           strncpy(envname,r,copylen);
4059                           envname[copylen] = '\0';
4060                           if ((envval = getenv(envname)) == NULL)
4061                           {
4062                             DEBUG(0,("standard_sub_basic: Environment variable [%s] not set\n",
4063                                      envname));
4064                             p+=2; break;
4065                           }
4066                           copylen = MIN((q+1-p),(sizeof(envname)-1));
4067                           strncpy(envname,p,copylen);
4068                           envname[copylen] = '\0';
4069                           string_sub(p,envname,envval);
4070                           break;
4071                         }
4072                         case '\0': p++; break; /* don't run off end if last character is % */
4073                         default  : p+=2; break;
4074                 }
4075         }
4076         return;
4077 }
4078
4079 /*******************************************************************
4080 are two IPs on the same subnet?
4081 ********************************************************************/
4082 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
4083 {
4084   uint32 net1,net2,nmask;
4085
4086   nmask = ntohl(mask.s_addr);
4087   net1  = ntohl(ip1.s_addr);
4088   net2  = ntohl(ip2.s_addr);
4089             
4090   return((net1 & nmask) == (net2 & nmask));
4091 }
4092
4093
4094 /*******************************************************************
4095 write a string in unicoode format
4096 ********************************************************************/
4097 int PutUniCode(char *dst,char *src)
4098 {
4099   int ret = 0;
4100   while (*src) {
4101     dst[ret++] = src[0];
4102     dst[ret++] = 0;    
4103     src++;
4104   }
4105   dst[ret++]=0;
4106   dst[ret++]=0;
4107   return(ret);
4108 }
4109
4110 /****************************************************************************
4111 a wrapper for gethostbyname() that tries with all lower and all upper case 
4112 if the initial name fails
4113 ****************************************************************************/
4114 struct hostent *Get_Hostbyname(char *name)
4115 {
4116   char *name2 = strdup(name);
4117   struct hostent *ret;
4118
4119   if (!name2)
4120     {
4121       DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
4122       exit(0);
4123     }
4124
4125    
4126   /* 
4127    * This next test is redundent and causes some systems (with
4128    * broken isalnum() calls) problems.
4129    * JRA.
4130    */
4131
4132 #if 0
4133   if (!isalnum(*name2))
4134     {
4135       free(name2);
4136       return(NULL);
4137     }
4138 #endif /* 0 */
4139
4140   ret = sys_gethostbyname(name2);
4141   if (ret != NULL)
4142     {
4143       free(name2);
4144       return(ret);
4145     }
4146
4147   /* try with all lowercase */
4148   strlower(name2);
4149   ret = sys_gethostbyname(name2);
4150   if (ret != NULL)
4151     {
4152       free(name2);
4153       return(ret);
4154     }
4155
4156   /* try with all uppercase */
4157   strupper(name2);
4158   ret = sys_gethostbyname(name2);
4159   if (ret != NULL)
4160     {
4161       free(name2);
4162       return(ret);
4163     }
4164   
4165   /* nothing works :-( */
4166   free(name2);
4167   return(NULL);
4168 }
4169
4170
4171 /****************************************************************************
4172 check if a process exists. Does this work on all unixes?
4173 ****************************************************************************/
4174 BOOL process_exists(int pid)
4175 {
4176         return(kill(pid,0) == 0 || errno != ESRCH);
4177 }
4178
4179
4180 /*******************************************************************
4181 turn a uid into a user name
4182 ********************************************************************/
4183 char *uidtoname(int uid)
4184 {
4185   static char name[40];
4186   struct passwd *pass = getpwuid(uid);
4187   if (pass) return(pass->pw_name);
4188   slprintf(name, sizeof(name) - 1, "%d",uid);
4189   return(name);
4190 }
4191
4192 /*******************************************************************
4193 turn a gid into a group name
4194 ********************************************************************/
4195 char *gidtoname(int gid)
4196 {
4197   static char name[40];
4198   struct group *grp = getgrgid(gid);
4199   if (grp) return(grp->gr_name);
4200   slprintf(name,sizeof(name) - 1, "%d",gid);
4201   return(name);
4202 }
4203
4204 /*******************************************************************
4205 block sigs
4206 ********************************************************************/
4207 void BlockSignals(BOOL block,int signum)
4208 {
4209 #ifdef USE_SIGBLOCK
4210   int block_mask = sigmask(signum);
4211   static int oldmask = 0;
4212   if (block) 
4213     oldmask = sigblock(block_mask);
4214   else
4215     sigsetmask(oldmask);
4216 #elif defined(USE_SIGPROCMASK)
4217   sigset_t set;
4218   sigemptyset(&set);
4219   sigaddset(&set,signum);
4220   sigprocmask(block?SIG_BLOCK:SIG_UNBLOCK,&set,NULL);
4221 #endif
4222 }
4223
4224 #if AJT
4225 /*******************************************************************
4226 my own panic function - not suitable for general use
4227 ********************************************************************/
4228 void ajt_panic(void)
4229 {
4230   system("/usr/bin/X11/xedit -display solen:0 /tmp/ERROR_FAULT");
4231 }
4232 #endif
4233
4234 #ifdef USE_DIRECT
4235 #define DIRECT direct
4236 #else
4237 #define DIRECT dirent
4238 #endif
4239
4240 /*******************************************************************
4241 a readdir wrapper which just returns the file name
4242 also return the inode number if requested
4243 ********************************************************************/
4244 char *readdirname(void *p)
4245 {
4246   struct DIRECT *ptr;
4247   char *dname;
4248
4249   if (!p) return(NULL);
4250   
4251   ptr = (struct DIRECT *)readdir(p);
4252   if (!ptr) return(NULL);
4253
4254   dname = ptr->d_name;
4255
4256 #ifdef NEXT2
4257   if (telldir(p) < 0) return(NULL);
4258 #endif
4259
4260 #ifdef SUNOS5
4261   /* this handles a broken compiler setup, causing a mixture
4262    of BSD and SYSV headers and libraries */
4263   {
4264     static BOOL broken_readdir = False;
4265     if (!broken_readdir && !(*(dname)) && strequal("..",dname-2))
4266       {
4267         DEBUG(0,("Your readdir() is broken. You have somehow mixed SYSV and BSD headers and libraries\n"));
4268         broken_readdir = True;
4269       }
4270     if (broken_readdir)
4271       dname = dname - 2;
4272   }
4273 #endif
4274
4275   {
4276     static pstring buf;
4277     pstrcpy(buf, dname);
4278     unix_to_dos(buf, True);
4279     dname = buf;
4280   }
4281
4282   return(dname);
4283 }
4284
4285 /*******************************************************************
4286  Utility function used to decide if the last component 
4287  of a path matches a (possibly wildcarded) entry in a namelist.
4288 ********************************************************************/
4289
4290 BOOL is_in_path(char *name, name_compare_entry *namelist)
4291 {
4292   pstring last_component;
4293   char *p;
4294
4295   DEBUG(8, ("is_in_path: %s\n", name));
4296
4297   /* if we have no list it's obviously not in the path */
4298   if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) 
4299   {
4300     DEBUG(8,("is_in_path: no name list.\n"));
4301     return False;
4302   }
4303
4304   /* Get the last component of the unix name. */
4305   p = strrchr(name, '/');
4306   strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
4307   last_component[sizeof(last_component)-1] = '\0'; 
4308
4309   for(; namelist->name != NULL; namelist++)
4310   {
4311     if(namelist->is_wild)
4312     {
4313       /* look for a wildcard match. */
4314       if (mask_match(last_component, namelist->name, case_sensitive, False))
4315       {
4316          DEBUG(8,("is_in_path: mask match succeeded\n"));
4317          return True;
4318       }
4319     }
4320     else
4321     {
4322       if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
4323        (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0)))
4324         {
4325          DEBUG(8,("is_in_path: match succeeded\n"));
4326          return True;
4327         }
4328     }
4329   }
4330   DEBUG(8,("is_in_path: match not found\n"));
4331  
4332   return False;
4333 }
4334
4335 /*******************************************************************
4336  Strip a '/' separated list into an array of 
4337  name_compare_enties structures suitable for 
4338  passing to is_in_path(). We do this for
4339  speed so we can pre-parse all the names in the list 
4340  and don't do it for each call to is_in_path().
4341  namelist is modified here and is assumed to be 
4342  a copy owned by the caller.
4343  We also check if the entry contains a wildcard to
4344  remove a potentially expensive call to mask_match
4345  if possible.
4346 ********************************************************************/
4347  
4348 void set_namearray(name_compare_entry **ppname_array, char *namelist)
4349 {
4350   char *name_end;
4351   char *nameptr = namelist;
4352   int num_entries = 0;
4353   int i;
4354
4355   (*ppname_array) = NULL;
4356
4357   if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0'))) 
4358     return;
4359
4360   /* We need to make two passes over the string. The
4361      first to count the number of elements, the second
4362      to split it.
4363    */
4364   while(*nameptr) 
4365     {
4366       if ( *nameptr == '/' ) 
4367         {
4368           /* cope with multiple (useless) /s) */
4369           nameptr++;
4370           continue;
4371         }
4372       /* find the next / */
4373       name_end = strchr(nameptr, '/');
4374
4375       /* oops - the last check for a / didn't find one. */
4376       if (name_end == NULL)
4377         break;
4378
4379       /* next segment please */
4380       nameptr = name_end + 1;
4381       num_entries++;
4382     }
4383
4384   if(num_entries == 0)
4385     return;
4386
4387   if(( (*ppname_array) = (name_compare_entry *)malloc( 
4388            (num_entries + 1) * sizeof(name_compare_entry))) == NULL)
4389         {
4390     DEBUG(0,("set_namearray: malloc fail\n"));
4391     return;
4392         }
4393
4394   /* Now copy out the names */
4395   nameptr = namelist;
4396   i = 0;
4397   while(*nameptr)
4398              {
4399       if ( *nameptr == '/' ) 
4400       {
4401           /* cope with multiple (useless) /s) */
4402           nameptr++;
4403           continue;
4404       }
4405       /* find the next / */
4406       if ((name_end = strchr(nameptr, '/')) != NULL) 
4407       {
4408           *name_end = 0;
4409          }
4410
4411       /* oops - the last check for a / didn't find one. */
4412       if(name_end == NULL) 
4413         break;
4414
4415       (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
4416                                 (strchr( nameptr, '*')!=NULL));
4417       if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
4418       {
4419         DEBUG(0,("set_namearray: malloc fail (1)\n"));
4420         return;
4421       }
4422
4423       /* next segment please */
4424       nameptr = name_end + 1;
4425       i++;
4426     }
4427   
4428   (*ppname_array)[i].name = NULL;
4429
4430   return;
4431 }
4432
4433 /****************************************************************************
4434 routine to free a namearray.
4435 ****************************************************************************/
4436
4437 void free_namearray(name_compare_entry *name_array)
4438 {
4439   if(name_array == 0)
4440     return;
4441
4442   if(name_array->name != NULL)
4443     free(name_array->name);
4444
4445   free((char *)name_array);
4446 }
4447
4448 /****************************************************************************
4449 routine to do file locking
4450 ****************************************************************************/
4451 BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type)
4452 {
4453 #if HAVE_FCNTL_LOCK
4454   struct flock lock;
4455   int ret;
4456
4457 #if 1
4458   uint32 mask = 0xC0000000;
4459
4460   /* make sure the count is reasonable, we might kill the lockd otherwise */
4461   count &= ~mask;
4462
4463   /* the offset is often strange - remove 2 of its bits if either of
4464      the top two bits are set. Shift the top ones by two bits. This
4465      still allows OLE2 apps to operate, but should stop lockd from
4466      dieing */
4467   if ((offset & mask) != 0)
4468     offset = (offset & ~mask) | ((offset & mask) >> 2);
4469 #else
4470   uint32 mask = ((unsigned)1<<31);
4471
4472   /* interpret negative counts as large numbers */
4473   if (count < 0)
4474     count &= ~mask;
4475
4476   /* no negative offsets */
4477   offset &= ~mask;
4478
4479   /* count + offset must be in range */
4480   while ((offset < 0 || (offset + count < 0)) && mask)
4481     {
4482       offset &= ~mask;
4483       mask = mask >> 1;
4484     }
4485 #endif
4486
4487
4488   DEBUG(8,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type));
4489
4490   lock.l_type = type;
4491   lock.l_whence = SEEK_SET;
4492   lock.l_start = (int)offset;
4493   lock.l_len = (int)count;
4494   lock.l_pid = 0;
4495
4496   errno = 0;
4497
4498   ret = fcntl(fd,op,&lock);
4499
4500   if (errno != 0)
4501     DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
4502
4503   /* a lock query */
4504   if (op == F_GETLK)
4505     {
4506       if ((ret != -1) &&
4507           (lock.l_type != F_UNLCK) && 
4508           (lock.l_pid != 0) && 
4509           (lock.l_pid != getpid()))
4510         {
4511           DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid));
4512           return(True);
4513         }
4514
4515       /* it must be not locked or locked by me */
4516       return(False);
4517     }
4518
4519   /* a lock set or unset */
4520   if (ret == -1)
4521     {
4522       DEBUG(3,("lock failed at offset %d count %d op %d type %d (%s)\n",
4523                offset,count,op,type,strerror(errno)));
4524
4525       /* perhaps it doesn't support this sort of locking?? */
4526       if (errno == EINVAL)
4527         {
4528           DEBUG(3,("locking not supported? returning True\n"));
4529           return(True);
4530         }
4531
4532       return(False);
4533     }
4534
4535   /* everything went OK */
4536   DEBUG(8,("Lock call successful\n"));
4537
4538   return(True);
4539 #else
4540   return(False);
4541 #endif
4542 }
4543
4544 /*******************************************************************
4545 lock a file - returning a open file descriptor or -1 on failure
4546 The timeout is in seconds. 0 means no timeout
4547 ********************************************************************/
4548 int file_lock(char *name,int timeout)
4549 {  
4550   int fd = open(name,O_RDWR|O_CREAT,0666);
4551   time_t t=0;
4552   if (fd < 0) return(-1);
4553
4554 #if HAVE_FCNTL_LOCK
4555   if (timeout) t = time(NULL);
4556   while (!timeout || (time(NULL)-t < timeout)) {
4557     if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)) return(fd);    
4558     msleep(LOCK_RETRY_TIMEOUT);
4559   }
4560   return(-1);
4561 #else
4562   return(fd);
4563 #endif
4564 }
4565
4566 /*******************************************************************
4567 unlock a file locked by file_lock
4568 ********************************************************************/
4569 void file_unlock(int fd)
4570 {
4571   if (fd<0) return;
4572 #if HAVE_FCNTL_LOCK
4573   fcntl_lock(fd,F_SETLK,0,1,F_UNLCK);
4574 #endif
4575   close(fd);
4576 }
4577
4578 /*******************************************************************
4579 is the name specified one of my netbios names
4580 returns true is it is equal, false otherwise
4581 ********************************************************************/
4582 BOOL is_myname(char *s)
4583 {
4584   int n;
4585   BOOL ret = False;
4586
4587   for (n=0; my_netbios_names[n]; n++) {
4588     if (strequal(my_netbios_names[n], s))
4589       ret=True;
4590   }
4591   DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
4592   return(ret);
4593 }
4594
4595 /*******************************************************************
4596 set the horrid remote_arch string based on an enum.
4597 ********************************************************************/
4598 void set_remote_arch(enum remote_arch_types type)
4599 {
4600   ra_type = type;
4601   switch( type )
4602   {
4603   case RA_WFWG:
4604     fstrcpy(remote_arch, "WfWg");
4605     return;
4606   case RA_OS2:
4607     fstrcpy(remote_arch, "OS2");
4608     return;
4609   case RA_WIN95:
4610     fstrcpy(remote_arch, "Win95");
4611     return;
4612   case RA_WINNT:
4613     fstrcpy(remote_arch, "WinNT");
4614     return;
4615   case RA_SAMBA:
4616     fstrcpy(remote_arch,"Samba");
4617     return;
4618   default:
4619     ra_type = RA_UNKNOWN;
4620     fstrcpy(remote_arch, "UNKNOWN");
4621     break;
4622   }
4623 }
4624
4625 /*******************************************************************
4626  Get the remote_arch type.
4627 ********************************************************************/
4628 enum remote_arch_types get_remote_arch(void)
4629 {
4630   return ra_type;
4631 }
4632
4633
4634 /*******************************************************************
4635 skip past some unicode strings in a buffer
4636 ********************************************************************/
4637 char *skip_unicode_string(char *buf,int n)
4638 {
4639   while (n--)
4640   {
4641     while (*buf)
4642       buf += 2;
4643     buf += 2;
4644   }
4645   return(buf);
4646 }
4647
4648 /*******************************************************************
4649 Return a ascii version of a unicode string
4650 Hack alert: uses fixed buffer(s) and only handles ascii strings
4651 ********************************************************************/
4652 #define MAXUNI 1024
4653 char *unistrn2(uint16 *buf, int len)
4654 {
4655         static char lbufs[8][MAXUNI];
4656         static int nexti;
4657         char *lbuf = lbufs[nexti];
4658         char *p;
4659
4660         nexti = (nexti+1)%8;
4661
4662         DEBUG(10, ("unistrn2: "));
4663
4664         for (p = lbuf; *buf && p-lbuf < MAXUNI-2 && len > 0; len--, p++, buf++)
4665         {
4666                 DEBUG(10, ("%4x ", *buf));
4667                 *p = *buf;
4668         }
4669
4670         DEBUG(10,("\n"));
4671
4672         *p = 0;
4673         return lbuf;
4674 }
4675
4676 /*******************************************************************
4677 Return a ascii version of a unicode string
4678 Hack alert: uses fixed buffer(s) and only handles ascii strings
4679 ********************************************************************/
4680 #define MAXUNI 1024
4681 char *unistr2(uint16 *buf)
4682 {
4683         static char lbufs[8][MAXUNI];
4684         static int nexti;
4685         char *lbuf = lbufs[nexti];
4686         char *p;
4687
4688         nexti = (nexti+1)%8;
4689
4690         DEBUG(10, ("unistr2: "));
4691
4692         for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf++)
4693         {
4694                 DEBUG(10, ("%4x ", *buf));
4695                 *p = *buf;
4696         }
4697
4698         DEBUG(10,("\n"));
4699
4700         *p = 0;
4701         return lbuf;
4702 }
4703
4704 /*******************************************************************
4705 create a null-terminated unicode string from a null-terminated ascii string.
4706 return number of unicode chars copied, excluding the null character.
4707
4708 only handles ascii strings
4709 ********************************************************************/
4710 #define MAXUNI 1024
4711 int struni2(uint16 *p, char *buf)
4712 {
4713         int len = 0;
4714
4715         if (p == NULL) return 0;
4716
4717         DEBUG(10, ("struni2: "));
4718
4719         if (buf != NULL)
4720         {
4721                 for (; *buf && len < MAXUNI-2; len++, p++, buf++)
4722                 {
4723                         DEBUG(10, ("%2x ", *buf));
4724                         *p = *buf;
4725                 }
4726
4727                 DEBUG(10,("\n"));
4728         }
4729
4730         *p = 0;
4731
4732         return len;
4733 }
4734
4735 /*******************************************************************
4736 Return a ascii version of a unicode string
4737 Hack alert: uses fixed buffer(s) and only handles ascii strings
4738 ********************************************************************/
4739 #define MAXUNI 1024
4740 char *unistr(char *buf)
4741 {
4742         static char lbufs[8][MAXUNI];
4743         static int nexti;
4744         char *lbuf = lbufs[nexti];
4745         char *p;
4746
4747         nexti = (nexti+1)%8;
4748
4749         for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf += 2)
4750         {
4751                 *p = *buf;
4752         }
4753         *p = 0;
4754         return lbuf;
4755 }
4756
4757 /*******************************************************************
4758 strncpy for unicode strings
4759 ********************************************************************/
4760 int unistrncpy(char *dst, char *src, int len)
4761 {
4762         int num_wchars = 0;
4763
4764         while (*src && len > 0)
4765         {
4766                 *dst++ = *src++;
4767                 *dst++ = *src++;
4768                 len--;
4769                 num_wchars++;
4770         }
4771         *dst++ = 0;
4772         *dst++ = 0;
4773
4774         return num_wchars;
4775 }
4776
4777
4778 /*******************************************************************
4779 strcpy for unicode strings.  returns length (in num of wide chars)
4780 ********************************************************************/
4781 int unistrcpy(char *dst, char *src)
4782 {
4783         int num_wchars = 0;
4784
4785         while (*src)
4786         {
4787                 *dst++ = *src++;
4788                 *dst++ = *src++;
4789                 num_wchars++;
4790         }
4791         *dst++ = 0;
4792         *dst++ = 0;
4793
4794         return num_wchars;
4795 }
4796
4797 /*******************************************************************
4798 safe string copy into a known length string. maxlength does not
4799 include the terminating zero.
4800 ********************************************************************/
4801 char *safe_strcpy(char *dest, char *src, int maxlength)
4802 {
4803     int len;
4804
4805     if (!dest) {
4806         DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
4807         return NULL;
4808     }
4809
4810     if (!src) {
4811         *dest = 0;
4812         return dest;
4813     }  
4814
4815     len = strlen(src);
4816
4817     if (len > maxlength) {
4818             DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
4819                      len-maxlength, src));
4820             len = maxlength;
4821     }
4822       
4823     memcpy(dest, src, len);
4824     dest[len] = 0;
4825     return dest;
4826 }  
4827
4828 /*******************************************************************
4829 safe string cat into a string. maxlength does not
4830 include the terminating zero.
4831 ********************************************************************/
4832 char *safe_strcat(char *dest, char *src, int maxlength)
4833 {
4834     int src_len, dest_len;
4835
4836     if (!dest) {
4837         DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
4838         return NULL;
4839     }
4840
4841     if (!src) {
4842         return dest;
4843     }  
4844
4845     src_len = strlen(src);
4846     dest_len = strlen(dest);
4847
4848     if (src_len + dest_len > maxlength) {
4849             DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
4850                      src_len + dest_len - maxlength, src));
4851             src_len = maxlength - dest_len;
4852     }
4853       
4854     memcpy(&dest[dest_len], src, src_len);
4855     dest[dest_len + src_len] = 0;
4856     return dest;
4857 }
4858
4859 /*******************************************************************
4860 align a pointer to a multiple of 4 bytes
4861 ********************************************************************/
4862 char *align4(char *q, char *base)
4863 {
4864         if ((q - base) & 3)
4865         {
4866                 q += 4 - ((q - base) & 3);
4867         }
4868         return q;
4869 }
4870
4871 /*******************************************************************
4872 align a pointer to a multiple of 2 bytes
4873 ********************************************************************/
4874 char *align2(char *q, char *base)
4875 {
4876         if ((q - base) & 1)
4877         {
4878                 q++;
4879         }
4880         return q;
4881 }
4882
4883 /*******************************************************************
4884 align a pointer to a multiple of align_offset bytes.  looks like it
4885 will work for offsets of 0, 2 and 4...
4886 ********************************************************************/
4887 char *align_offset(char *q, char *base, int align_offset_len)
4888 {
4889         int mod = ((q - base) & (align_offset_len-1));
4890         if (align_offset_len != 0 && mod != 0)
4891         {
4892                 q += align_offset_len - mod;
4893         }
4894         return q;
4895 }
4896
4897 void print_asc(int level, unsigned char *buf,int len)
4898 {
4899         int i;
4900         for (i=0;i<len;i++)
4901                 DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
4902 }
4903
4904 void dump_data(int level,char *buf1,int len)
4905 {
4906   unsigned char *buf = (unsigned char *)buf1;
4907   int i=0;
4908   if (len<=0) return;
4909
4910   DEBUG(level,("[%03X] ",i));
4911   for (i=0;i<len;) {
4912     DEBUG(level,("%02X ",(int)buf[i]));
4913     i++;
4914     if (i%8 == 0) DEBUG(level,(" "));
4915     if (i%16 == 0) {      
4916       print_asc(level,&buf[i-16],8); DEBUG(level,(" "));
4917       print_asc(level,&buf[i-8],8); DEBUG(level,("\n"));
4918       if (i<len) DEBUG(level,("[%03X] ",i));
4919     }
4920   }
4921   if (i%16) {
4922     int n;
4923
4924     n = 16 - (i%16);
4925     DEBUG(level,(" "));
4926     if (n>8) DEBUG(level,(" "));
4927     while (n--) DEBUG(level,("   "));
4928
4929     n = MIN(8,i%16);
4930     print_asc(level,&buf[i-(i%16)],n); DEBUG(level,(" "));
4931     n = (i%16) - n;
4932     if (n>0) print_asc(level,&buf[i-n],n); 
4933     DEBUG(level,("\n"));    
4934   }
4935 }
4936
4937 char *tab_depth(int depth)
4938 {
4939         static pstring spaces;
4940         memset(spaces, ' ', depth * 4);
4941         spaces[depth * 4] = 0;
4942         return spaces;
4943 }
4944
4945 /*****************************************************************
4946  Convert a domain SID to an ascii string. (non-reentrant).
4947 *****************************************************************/
4948
4949 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
4950 char *dom_sid_to_string(DOM_SID *sid)
4951 {
4952   static pstring sidstr;
4953   char subauth[16];
4954   int i;
4955   uint32 ia = (sid->id_auth[5]) +
4956               (sid->id_auth[4] << 8 ) +
4957               (sid->id_auth[3] << 16) +
4958               (sid->id_auth[2] << 24);
4959
4960   slprintf(sidstr, sizeof(sidstr) - 1, "S-%d-%d", sid->sid_rev_num, ia);
4961
4962   for (i = 0; i < sid->num_auths; i++)
4963   {
4964     slprintf(subauth, sizeof(subauth)-1, "-%d", sid->sub_auths[i]);
4965     pstrcat(sidstr, subauth);
4966   }
4967
4968   DEBUG(7,("dom_sid_to_string returning %s\n", sidstr));
4969   return sidstr;
4970 }
4971