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