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