233e9872711cdb0a683cd04a4cf0ecde24822cf6
[kai/samba.git] / source3 / lib / util.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Samba utility functions
5    Copyright (C) Andrew Tridgell 1992-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     {
2688       DEBUG(0,("Invalid packet length! (%d bytes)\n",len));
2689       if (len > BUFFER_SIZE + (SAFETY_MARGIN/2))
2690         exit(1);
2691     }
2692
2693   ok = (read_data(fd,buffer+4,len) == len);
2694
2695   if (!ok)
2696     {
2697       close_sockets();
2698       exit(1);
2699     }
2700
2701   return(True);
2702 }
2703
2704
2705 /****************************************************************************
2706   send an smb to a fd 
2707 ****************************************************************************/
2708 BOOL send_smb(int fd,char *buffer)
2709 {
2710   int len;
2711   int ret,nwritten=0;
2712   len = smb_len(buffer) + 4;
2713
2714   while (nwritten < len)
2715     {
2716       ret = write_socket(fd,buffer+nwritten,len - nwritten);
2717       if (ret <= 0)
2718         {
2719           DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret));
2720           close_sockets();
2721           exit(1);
2722         }
2723       nwritten += ret;
2724     }
2725
2726
2727   return True;
2728 }
2729
2730
2731 /****************************************************************************
2732 find a pointer to a netbios name
2733 ****************************************************************************/
2734 char *name_ptr(char *buf,int ofs)
2735 {
2736   unsigned char c = *(unsigned char *)(buf+ofs);
2737
2738   if ((c & 0xC0) == 0xC0)
2739     {
2740       uint16 l;
2741       char p[2];
2742       memcpy(p,buf+ofs,2);
2743       p[0] &= ~0xC0;
2744       l = RSVAL(p,0);
2745       DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
2746       return(buf + l);
2747     }
2748   else
2749     return(buf+ofs);
2750 }  
2751
2752 /****************************************************************************
2753 extract a netbios name from a buf
2754 ****************************************************************************/
2755 int name_extract(char *buf,int ofs,char *name)
2756 {
2757   char *p = name_ptr(buf,ofs);
2758   int d = PTR_DIFF(p,buf+ofs);
2759   strcpy(name,"");
2760   if (d < -50 || d > 50) return(0);
2761   return(name_interpret(p,name));
2762 }  
2763   
2764
2765 /****************************************************************************
2766 return the total storage length of a mangled name
2767 ****************************************************************************/
2768 int name_len(char *s)
2769 {
2770   char *s0=s;
2771   unsigned char c = *(unsigned char *)s;
2772   if ((c & 0xC0) == 0xC0)
2773     return(2);
2774   while (*s) s += (*s)+1;
2775   return(PTR_DIFF(s,s0)+1);
2776 }
2777
2778 /****************************************************************************
2779 send a single packet to a port on another machine
2780 ****************************************************************************/
2781 BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
2782 {
2783   BOOL ret;
2784   int out_fd;
2785   struct sockaddr_in sock_out;
2786
2787   if (passive)
2788     return(True);
2789
2790   /* create a socket to write to */
2791   out_fd = socket(AF_INET, type, 0);
2792   if (out_fd == -1) 
2793     {
2794       DEBUG(0,("socket failed"));
2795       return False;
2796     }
2797
2798   /* set the address and port */
2799   bzero((char *)&sock_out,sizeof(sock_out));
2800   putip((char *)&sock_out.sin_addr,(char *)&ip);
2801   sock_out.sin_port = htons( port );
2802   sock_out.sin_family = AF_INET;
2803   
2804   if (DEBUGLEVEL > 0)
2805     DEBUG(3,("sending a packet of len %d to (%s) on port %d of type %s\n",
2806              len,inet_ntoa(ip),port,type==SOCK_DGRAM?"DGRAM":"STREAM"));
2807         
2808   /* send it */
2809   ret = (sendto(out_fd,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
2810
2811   if (!ret)
2812     DEBUG(0,("Packet send to %s(%d) failed ERRNO=%d\n",
2813              inet_ntoa(ip),port,errno));
2814
2815   close(out_fd);
2816   return(ret);
2817 }
2818
2819 /*******************************************************************
2820 sleep for a specified number of milliseconds
2821 ********************************************************************/
2822 void msleep(int t)
2823 {
2824   int tdiff=0;
2825   struct timeval tval,t1,t2;  
2826   fd_set fds;
2827
2828   GetTimeOfDay(&t1);
2829   GetTimeOfDay(&t2);
2830   
2831   while (tdiff < t) {
2832     tval.tv_sec = (t-tdiff)/1000;
2833     tval.tv_usec = 1000*((t-tdiff)%1000);
2834  
2835     FD_ZERO(&fds);
2836     errno = 0;
2837     sys_select(&fds,&tval);
2838
2839     GetTimeOfDay(&t2);
2840     tdiff = TvalDiff(&t1,&t2);
2841   }
2842 }
2843
2844 /****************************************************************************
2845 check if a string is part of a list
2846 ****************************************************************************/
2847 BOOL in_list(char *s,char *list,BOOL casesensitive)
2848 {
2849   pstring tok;
2850   char *p=list;
2851
2852   if (!list) return(False);
2853
2854   while (next_token(&p,tok,LIST_SEP))
2855     {
2856       if (casesensitive) {
2857         if (strcmp(tok,s) == 0)
2858           return(True);
2859       } else {
2860         if (StrCaseCmp(tok,s) == 0)
2861           return(True);
2862       }
2863     }
2864   return(False);
2865 }
2866
2867 /* this is used to prevent lots of mallocs of size 1 */
2868 static char *null_string = NULL;
2869
2870 /****************************************************************************
2871 set a string value, allocing the space for the string
2872 ****************************************************************************/
2873 BOOL string_init(char **dest,char *src)
2874 {
2875   int l;
2876   if (!src)     
2877     src = "";
2878
2879   l = strlen(src);
2880
2881   if (l == 0)
2882     {
2883       if (!null_string)
2884         null_string = (char *)malloc(1);
2885
2886       *null_string = 0;
2887       *dest = null_string;
2888     }
2889   else
2890     {
2891       *dest = (char *)malloc(l+1);
2892       strcpy(*dest,src);
2893     }
2894   return(True);
2895 }
2896
2897 /****************************************************************************
2898 free a string value
2899 ****************************************************************************/
2900 void string_free(char **s)
2901 {
2902   if (!s || !(*s)) return;
2903   if (*s == null_string)
2904     *s = NULL;
2905   if (*s) free(*s);
2906   *s = NULL;
2907 }
2908
2909 /****************************************************************************
2910 set a string value, allocing the space for the string, and deallocating any 
2911 existing space
2912 ****************************************************************************/
2913 BOOL string_set(char **dest,char *src)
2914 {
2915   string_free(dest);
2916
2917   return(string_init(dest,src));
2918 }
2919
2920 /****************************************************************************
2921 substitute a string for a pattern in another string. Make sure there is 
2922 enough room!
2923
2924 This routine looks for pattern in s and replaces it with 
2925 insert. It may do multiple replacements.
2926
2927 return True if a substitution was done.
2928 ****************************************************************************/
2929 BOOL string_sub(char *s,char *pattern,char *insert)
2930 {
2931   BOOL ret = False;
2932   char *p;
2933   int ls,lp,li;
2934
2935   if (!insert || !pattern || !s) return(False);
2936
2937   ls = strlen(s);
2938   lp = strlen(pattern);
2939   li = strlen(insert);
2940
2941   if (!*pattern) return(False);
2942
2943   while (lp <= ls && (p = strstr(s,pattern)))
2944     {
2945       ret = True;
2946       memmove(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp));
2947       memcpy(p,insert,li);
2948       s = p + li;
2949       ls = strlen(s);
2950     }
2951   return(ret);
2952 }
2953
2954
2955
2956 /*********************************************************
2957 * Recursive routine that is called by mask_match.
2958 * Does the actual matching.
2959 *********************************************************/
2960 BOOL do_match(char *str, char *regexp, int case_sig)
2961 {
2962   char *p;
2963
2964   for( p = regexp; *p && *str; ) {
2965     switch(*p) {
2966     case '?':
2967       str++; p++;
2968       break;
2969
2970     case '*':
2971       /* Look for a character matching 
2972          the one after the '*' */
2973       p++;
2974       if(!*p)
2975         return True; /* Automatic match */
2976       while(*str) {
2977         while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
2978           str++;
2979         if(do_match(str,p,case_sig))
2980           return True;
2981         if(!*str)
2982           return False;
2983         else
2984           str++;
2985       }
2986       return False;
2987
2988     default:
2989       if(case_sig) {
2990         if(*str != *p)
2991           return False;
2992       } else {
2993         if(toupper(*str) != toupper(*p))
2994           return False;
2995       }
2996       str++, p++;
2997       break;
2998     }
2999   }
3000   if(!*p && !*str)
3001     return True;
3002
3003   if (!*p && str[0] == '.' && str[1] == 0)
3004     return(True);
3005   
3006   if (!*str && *p == '?')
3007     {
3008       while (*p == '?') p++;
3009       return(!*p);
3010     }
3011
3012   if(!*str && (*p == '*' && p[1] == '\0'))
3013     return True;
3014   return False;
3015 }
3016
3017
3018 /*********************************************************
3019 * Routine to match a given string with a regexp - uses
3020 * simplified regexp that takes * and ? only. Case can be
3021 * significant or not.
3022 *********************************************************/
3023 BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
3024 {
3025   char *p;
3026   pstring p1, p2;
3027   fstring ebase,eext,sbase,sext;
3028
3029   BOOL matched;
3030
3031   /* Make local copies of str and regexp */
3032   StrnCpy(p1,regexp,sizeof(pstring)-1);
3033   StrnCpy(p2,str,sizeof(pstring)-1);
3034
3035   if (!strchr(p2,'.')) {
3036     strcat(p2,".");
3037   }
3038
3039 /*
3040   if (!strchr(p1,'.')) {
3041     strcat(p1,".");
3042   }
3043 */
3044
3045 #if 0
3046   if (strchr(p1,'.'))
3047     {
3048       string_sub(p1,"*.*","*");
3049       string_sub(p1,".*","*");
3050     }
3051 #endif
3052
3053   /* Remove any *? and ** as they are meaningless */
3054   for(p = p1; *p; p++)
3055     while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
3056       (void)strcpy( &p[1], &p[2]);
3057
3058   if (strequal(p1,"*")) return(True);
3059
3060   DEBUG(5,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
3061
3062   if (trans2) {
3063     strcpy(ebase,p1);
3064     strcpy(sbase,p2);
3065   } else {
3066     if ((p=strrchr(p1,'.'))) {
3067       *p = 0;
3068       strcpy(ebase,p1);
3069       strcpy(eext,p+1);
3070     } else {
3071       strcpy(ebase,p1);
3072       eext[0] = 0;
3073     }
3074
3075   if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
3076     *p = 0;
3077     strcpy(sbase,p2);
3078     strcpy(sext,p+1);
3079   } else {
3080     strcpy(sbase,p2);
3081     strcpy(sext,"");
3082   }
3083   }
3084
3085   matched = do_match(sbase,ebase,case_sig) && 
3086     (trans2 || do_match(sext,eext,case_sig));
3087
3088   DEBUG(5,("mask_match returning %d\n", matched));
3089
3090   return matched;
3091 }
3092
3093
3094
3095 /****************************************************************************
3096 become a daemon, discarding the controlling terminal
3097 ****************************************************************************/
3098 void become_daemon(void)
3099 {
3100 #ifndef NO_FORK_DEBUG
3101   if (fork())
3102     exit(0);
3103
3104   /* detach from the terminal */
3105 #ifdef USE_SETSID
3106   setsid();
3107 #else
3108 #ifdef TIOCNOTTY
3109   {
3110     int i = open("/dev/tty", O_RDWR);
3111     if (i >= 0) 
3112       {
3113         ioctl(i, (int) TIOCNOTTY, (char *)0);      
3114         close(i);
3115       }
3116   }
3117 #endif
3118 #endif
3119 #endif
3120 }
3121
3122 /****************************************************************************
3123 calculate the default netmask for an address
3124 ****************************************************************************/
3125 static void default_netmask(struct in_addr *inm, struct in_addr *iad)
3126 {
3127   unsigned long ad = ntohl(iad->s_addr);
3128   unsigned long nm;
3129   /*
3130   ** Guess a netmask based on the class of the IP address given.
3131   */
3132   if ( (ad & 0x80000000) == 0 ) {
3133     /* class A address */
3134     nm = 0xFF000000;
3135   } else if ( (ad & 0xC0000000) == 0x80000000 ) {
3136     /* class B address */
3137     nm = 0xFFFF0000;
3138   } else if ( (ad & 0xE0000000) == 0xC0000000 ) {
3139     /* class C address */
3140     nm = 0xFFFFFF00;
3141   }  else {
3142     /* class D or E; netmask doesn't make much sense - guess 4 bits */
3143     nm =  0xFFFFFFF0;
3144   }
3145   inm->s_addr = htonl(nm);
3146 }
3147
3148 /****************************************************************************
3149   get the broadcast address for our address 
3150 (troyer@saifr00.ateng.az.honeywell.com)
3151 ****************************************************************************/
3152 void get_broadcast(struct in_addr *if_ipaddr,
3153                     struct in_addr *if_bcast,
3154                     struct in_addr *if_nmask)
3155 {  
3156   BOOL found = False;
3157 #ifndef NO_GET_BROADCAST
3158   int sock = -1;               /* AF_INET raw socket desc */
3159   char buff[1024];
3160   struct ifreq *ifr=NULL;
3161   int i;
3162
3163 #if defined(EVEREST)
3164   int n_interfaces;
3165   struct ifconf ifc;
3166   struct ifreq  *ifreqs;
3167 #elif defined(USE_IFREQ)
3168   struct ifreq ifreq;
3169   struct strioctl strioctl;
3170   struct ifconf *ifc;
3171 #else
3172   struct ifconf ifc;
3173 #endif
3174 #endif
3175
3176   /* get a default netmask and broadcast */
3177   default_netmask(if_nmask, if_ipaddr);
3178
3179 #ifndef NO_GET_BROADCAST  
3180   /* Create a socket to the INET kernel. */
3181 #if USE_SOCKRAW
3182   if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0)
3183 #else
3184     if ((sock = socket(AF_INET, SOCK_DGRAM, 0 )) < 0)
3185 #endif
3186       {
3187         DEBUG(0,( "Unable to open socket to get broadcast address\n"));
3188         return;
3189       }
3190   
3191   /* Get a list of the configured interfaces */
3192 #ifdef EVEREST
3193   /* This is part of SCO Openserver 5: The ioctls are no longer part
3194      if the lower level STREAMS interface glue. They are now real
3195      ioctl calls */
3196
3197   if (ioctl(sock, SIOCGIFANUM, &n_interfaces) < 0) {
3198     DEBUG(0,( "SIOCGIFANUM: %s\n", strerror(errno)));
3199   } else {
3200     DEBUG(0,( "number of interfaces returned is: %d\n", n_interfaces));
3201
3202     ifc.ifc_len = sizeof(struct ifreq) * n_interfaces;
3203     ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len);
3204
3205     if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
3206       DEBUG(0, ( "SIOCGIFCONF: %s\n", strerror(errno)));
3207     else {
3208       ifr = ifc.ifc_req;
3209
3210       for (i = 0; i < n_interfaces; ++i) {
3211         if (if_ipaddr->s_addr ==
3212             ((struct sockaddr_in *) &ifr[i].ifr_addr)->sin_addr.s_addr) {
3213           found = True;
3214           break;
3215         }
3216       }
3217     }
3218   }
3219 #elif defined(USE_IFREQ)
3220   ifc = (struct ifconf *)buff;
3221   ifc->ifc_len = BUFSIZ - sizeof(struct ifconf);
3222   strioctl.ic_cmd = SIOCGIFCONF;
3223   strioctl.ic_dp  = (char *)ifc;
3224   strioctl.ic_len = sizeof(buff);
3225   if (ioctl(sock, I_STR, &strioctl) < 0) {
3226     DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno)));
3227   } else {
3228     ifr = (struct ifreq *)ifc->ifc_req;  
3229
3230     /* Loop through interfaces, looking for given IP address */
3231     for (i = ifc->ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
3232       if (if_ipaddr->s_addr ==
3233           (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
3234         found = True;
3235         break;
3236       }
3237     }
3238   }
3239 #elif defined(__FreeBSD__) || defined(NETBSD)
3240   ifc.ifc_len = sizeof(buff);
3241   ifc.ifc_buf = buff;
3242   if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
3243     DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
3244   } else {
3245     ifr = ifc.ifc_req;
3246     /* Loop through interfaces, looking for given IP address */
3247     i = ifc.ifc_len;
3248     while (i > 0) {
3249       if (if_ipaddr->s_addr ==
3250           (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
3251         found = True;
3252         break;
3253       }
3254       i -= ifr->ifr_addr.sa_len + IFNAMSIZ;
3255       ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
3256     }
3257   }
3258 #else
3259   ifc.ifc_len = sizeof(buff);
3260   ifc.ifc_buf = buff;
3261   if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
3262     DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
3263   } else {
3264     ifr = ifc.ifc_req;
3265   
3266     /* Loop through interfaces, looking for given IP address */
3267     for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
3268 #ifdef BSDI
3269       if (ioctl(sock, SIOCGIFADDR, ifr) < 0) break;
3270 #endif
3271       if (if_ipaddr->s_addr ==
3272           (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
3273         found = True;
3274         break;
3275       }
3276     }
3277   }
3278 #endif
3279   
3280   if (!found) {
3281     DEBUG(0,("No interface found for address %s\n", inet_ntoa(*if_ipaddr)));
3282   } else {
3283     /* Get the netmask address from the kernel */
3284 #ifdef USE_IFREQ
3285     ifreq = *ifr;
3286   
3287     strioctl.ic_cmd = SIOCGIFNETMASK;
3288     strioctl.ic_dp  = (char *)&ifreq;
3289     strioctl.ic_len = sizeof(struct ifreq);
3290     if (ioctl(sock, I_STR, &strioctl) < 0)
3291       DEBUG(0,("Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno)));
3292     else
3293       *if_nmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
3294 #else
3295     if (ioctl(sock, SIOCGIFNETMASK, ifr) < 0)
3296       DEBUG(0,("SIOCGIFNETMASK failed\n"));
3297     else
3298       *if_nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
3299 #endif
3300
3301     DEBUG(2,("Netmask for %s = %s\n", ifr->ifr_name,
3302              inet_ntoa(*if_nmask)));
3303   }
3304
3305   /* Close up shop */
3306   (void) close(sock);
3307   
3308 #endif
3309
3310   /* sanity check on the netmask */
3311   {
3312     unsigned long nm = ntohl(if_nmask->s_addr);
3313     if ((nm >> 24) != 0xFF) {
3314       DEBUG(0,("Impossible netmask %s - using defaults\n",inet_ntoa(*if_nmask)));
3315       default_netmask(if_nmask, if_ipaddr);      
3316     }
3317   }
3318
3319   /* derive the broadcast assuming a 1's broadcast, as this is what
3320      all MS operating systems do, we have to comply even if the unix
3321      box is setup differently */
3322   {
3323     unsigned long ad = ntohl(if_ipaddr->s_addr);
3324     unsigned long nm = ntohl(if_nmask->s_addr);
3325     unsigned long bc = (ad & nm) | (0xffffffff & ~nm);
3326     if_bcast->s_addr = htonl(bc);
3327   }
3328   
3329   DEBUG(2,("Derived broadcast address %s\n", inet_ntoa(*if_bcast)));
3330 }  /* get_broadcast */
3331
3332
3333 /****************************************************************************
3334 put up a yes/no prompt
3335 ****************************************************************************/
3336 BOOL yesno(char *p)
3337 {
3338   pstring ans;
3339   printf("%s",p);
3340
3341   if (!fgets(ans,sizeof(ans)-1,stdin))
3342     return(False);
3343
3344   if (*ans == 'y' || *ans == 'Y')
3345     return(True);
3346
3347   return(False);
3348 }
3349
3350 /****************************************************************************
3351 read a line from a file with possible \ continuation chars. 
3352 Blanks at the start or end of a line are stripped.
3353 The string will be allocated if s2 is NULL
3354 ****************************************************************************/
3355 char *fgets_slash(char *s2,int maxlen,FILE *f)
3356 {
3357   char *s=s2;
3358   int len = 0;
3359   int c;
3360   BOOL start_of_line = True;
3361
3362   if (feof(f))
3363     return(NULL);
3364
3365   if (!s2)
3366     {
3367       maxlen = MIN(maxlen,8);
3368       s = (char *)Realloc(s,maxlen);
3369     }
3370
3371   if (!s || maxlen < 2) return(NULL);
3372
3373   *s = 0;
3374
3375   while (len < maxlen-1)
3376     {
3377       c = getc(f);
3378       switch (c)
3379         {
3380         case '\r':
3381           break;
3382         case '\n':
3383           while (len > 0 && s[len-1] == ' ')
3384             {
3385               s[--len] = 0;
3386             }
3387           if (len > 0 && s[len-1] == '\\')
3388             {
3389               s[--len] = 0;
3390               start_of_line = True;
3391               break;
3392             }
3393           return(s);
3394         case EOF:
3395           if (len <= 0 && !s2) 
3396             free(s);
3397           return(len>0?s:NULL);
3398         case ' ':
3399           if (start_of_line)
3400             break;
3401         default:
3402           start_of_line = False;
3403           s[len++] = c;
3404           s[len] = 0;
3405         }
3406       if (!s2 && len > maxlen-3)
3407         {
3408           maxlen *= 2;
3409           s = (char *)Realloc(s,maxlen);
3410           if (!s) return(NULL);
3411         }
3412     }
3413   return(s);
3414 }
3415
3416
3417
3418 /****************************************************************************
3419 set the length of a file from a filedescriptor.
3420 Returns 0 on success, -1 on failure.
3421 ****************************************************************************/
3422 int set_filelen(int fd, long len)
3423 {
3424 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
3425    extend a file with ftruncate. Provide alternate implementation
3426    for this */
3427
3428 #if FTRUNCATE_CAN_EXTEND
3429   return ftruncate(fd, len);
3430 #else
3431   struct stat st;
3432   char c = 0;
3433   long currpos = lseek(fd, 0L, SEEK_CUR);
3434
3435   if(currpos < 0)
3436     return -1;
3437   /* Do an fstat to see if the file is longer than
3438      the requested size (call ftruncate),
3439      or shorter, in which case seek to len - 1 and write 1
3440      byte of zero */
3441   if(fstat(fd, &st)<0)
3442     return -1;
3443
3444 #ifdef S_ISFIFO
3445   if (S_ISFIFO(st.st_mode)) return 0;
3446 #endif
3447
3448   if(st.st_size == len)
3449     return 0;
3450   if(st.st_size > len)
3451     return ftruncate(fd, len);
3452
3453   if(lseek(fd, len-1, SEEK_SET) != len -1)
3454     return -1;
3455   if(write(fd, &c, 1)!=1)
3456     return -1;
3457   /* Seek to where we were */
3458   lseek(fd, currpos, SEEK_SET);
3459   return 0;
3460 #endif
3461 }
3462
3463
3464 /****************************************************************************
3465 return the byte checksum of some data
3466 ****************************************************************************/
3467 int byte_checksum(char *buf,int len)
3468 {
3469   unsigned char *p = (unsigned char *)buf;
3470   int ret = 0;
3471   while (len--)
3472     ret += *p++;
3473   return(ret);
3474 }
3475
3476
3477
3478 #ifdef HPUX
3479 /****************************************************************************
3480 this is a version of setbuffer() for those machines that only have setvbuf
3481 ****************************************************************************/
3482 void setbuffer(FILE *f,char *buf,int bufsize)
3483 {
3484   setvbuf(f,buf,_IOFBF,bufsize);
3485 }
3486 #endif
3487
3488
3489 /****************************************************************************
3490 parse out a directory name from a path name. Assumes dos style filenames.
3491 ****************************************************************************/
3492 char *dirname_dos(char *path,char *buf)
3493 {
3494   char *p = strrchr(path,'\\');
3495
3496   if (!p)
3497     strcpy(buf,path);
3498   else
3499     {
3500       *p = 0;
3501       strcpy(buf,path);
3502       *p = '\\';
3503     }
3504
3505   return(buf);
3506 }
3507
3508
3509 /****************************************************************************
3510 parse out a filename from a path name. Assumes dos style filenames.
3511 ****************************************************************************/
3512 static char *filename_dos(char *path,char *buf)
3513 {
3514   char *p = strrchr(path,'\\');
3515
3516   if (!p)
3517     strcpy(buf,path);
3518   else
3519     strcpy(buf,p+1);
3520
3521   return(buf);
3522 }
3523
3524
3525
3526 /****************************************************************************
3527 expand a pointer to be a particular size
3528 ****************************************************************************/
3529 void *Realloc(void *p,int size)
3530 {
3531   void *ret=NULL;
3532   if (!p)
3533     ret = (void *)malloc(size);
3534   else
3535     ret = (void *)realloc(p,size);
3536
3537   if (!ret)
3538     DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",size));
3539
3540   return(ret);
3541 }
3542
3543 /****************************************************************************
3544 set the time on a file
3545 ****************************************************************************/
3546 BOOL set_filetime(char *fname,time_t mtime)
3547 {  
3548   struct utimbuf times;
3549
3550   if (null_mtime(mtime)) return(True);
3551
3552   times.modtime = times.actime = mtime;
3553
3554   if (sys_utime(fname,&times)) {
3555     DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
3556   }
3557     
3558   return(True);
3559 }
3560
3561
3562 #ifdef NOSTRDUP
3563 /****************************************************************************
3564 duplicate a string
3565 ****************************************************************************/
3566 char *strdup(char *s)
3567 {
3568   char *ret = NULL;
3569   if (!s) return(NULL);
3570   ret = (char *)malloc(strlen(s)+1);
3571   if (!ret) return(NULL);
3572   strcpy(ret,s);
3573   return(ret);
3574 }
3575 #endif
3576
3577
3578 /****************************************************************************
3579   Signal handler for SIGPIPE (write on a disconnected socket) 
3580 ****************************************************************************/
3581 void Abort(void )
3582 {
3583   DEBUG(0,("Probably got SIGPIPE\nExiting\n"));
3584   exit(2);
3585 }
3586
3587
3588 #ifdef REPLACE_STRLEN
3589 /****************************************************************************
3590 a replacement strlen() that returns int for solaris
3591 ****************************************************************************/
3592 int Strlen(char *s)
3593 {
3594   int ret=0;
3595   if (!s) return(0);
3596   while (*s++) ret++;
3597   return(ret);
3598 }
3599 #endif
3600
3601
3602 /****************************************************************************
3603 return a time at the start of the current month
3604 ****************************************************************************/
3605 time_t start_of_month(void)
3606 {
3607   time_t t = time(NULL);
3608   struct tm *t2;
3609   
3610   t2 = gmtime(&t);
3611   
3612   t2->tm_mday = 1;
3613   t2->tm_hour = 0;
3614   t2->tm_min = 0;
3615   t2->tm_sec = 0;
3616   
3617   return(mktime(t2));
3618 }
3619
3620
3621 /*******************************************************************
3622   check for a sane unix date
3623 ********************************************************************/
3624 BOOL sane_unix_date(time_t unixdate)
3625 {
3626   struct tm t,today;
3627   time_t t_today = time(NULL);
3628   
3629   t = *(LocalTime(&unixdate,LOCAL_TO_GMT));
3630   today = *(LocalTime(&t_today,LOCAL_TO_GMT));
3631   
3632   if (t.tm_year < 80)
3633     return(False);
3634   
3635   if (t.tm_year >  today.tm_year)
3636     return(False);
3637   
3638   if (t.tm_year == today.tm_year &&
3639       t.tm_mon > today.tm_mon)
3640     return(False);
3641   
3642   
3643   if (t.tm_year == today.tm_year &&
3644       t.tm_mon == today.tm_mon &&
3645       t.tm_mday > (today.tm_mday+1))
3646     return(False);
3647   
3648   return(True);
3649 }
3650
3651
3652
3653 #ifdef NO_FTRUNCATE
3654  /*******************************************************************
3655 ftruncate for operating systems that don't have it
3656 ********************************************************************/
3657 int ftruncate(int f,long l)
3658 {
3659       struct  flock   fl;
3660
3661       fl.l_whence = 0;
3662       fl.l_len = 0;
3663       fl.l_start = l;
3664       fl.l_type = F_WRLCK;
3665       return fcntl(f, F_FREESP, &fl);
3666 }
3667 #endif
3668
3669
3670
3671 /****************************************************************************
3672 get my own name and IP
3673 ****************************************************************************/
3674 BOOL get_myname(char *myname,struct in_addr *ip)
3675 {
3676   struct hostent *hp;
3677   pstring hostname;
3678
3679   *hostname = 0;
3680
3681   /* get my host name */
3682   if (gethostname(hostname, MAXHOSTNAMELEN) == -1) 
3683     {
3684       DEBUG(0,("gethostname failed\n"));
3685       return False;
3686     } 
3687
3688   /* get host info */
3689   if ((hp = Get_Hostbyname(hostname)) == 0) 
3690     {
3691       DEBUG(0,( "Get_Hostbyname: Unknown host %s.\n",hostname));
3692       return False;
3693     }
3694
3695   if (myname)
3696     {
3697       /* split off any parts after an initial . */
3698       char *p = strchr(hostname,'.');
3699       if (p) *p = 0;
3700
3701       strcpy(myname,hostname);
3702     }
3703
3704   if (ip)
3705     putip((char *)ip,(char *)hp->h_addr);
3706
3707   return(True);
3708 }
3709
3710
3711 /****************************************************************************
3712 true if two IP addresses are equal
3713 ****************************************************************************/
3714 BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
3715 {
3716   unsigned long a1,a2;
3717   a1 = ntohl(ip1.s_addr);
3718   a2 = ntohl(ip2.s_addr);
3719   return(a1 == a2);
3720 }
3721
3722
3723 /****************************************************************************
3724 open a socket of the specified type, port and address for incoming data
3725 ****************************************************************************/
3726 int open_socket_in(int type, int port, int dlevel)
3727 {
3728   struct hostent *hp;
3729   struct sockaddr_in sock;
3730   pstring host_name;
3731   int res;
3732
3733   /* get my host name */
3734 #ifdef MAXHOSTNAMELEN
3735   if (gethostname(host_name, MAXHOSTNAMELEN) == -1) 
3736 #else
3737   if (gethostname(host_name, sizeof(host_name)) == -1) 
3738 #endif
3739     { DEBUG(0,("gethostname failed\n")); return -1; } 
3740
3741   /* get host info */
3742   if ((hp = Get_Hostbyname(host_name)) == 0) 
3743     {
3744       DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",host_name));
3745       return -1;
3746     }
3747   
3748   bzero((char *)&sock,sizeof(sock));
3749   memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
3750 #if defined(__FreeBSD__) || defined(NETBSD) /* XXX not the right ifdef */
3751   sock.sin_len = sizeof(sock);
3752 #endif
3753   sock.sin_port = htons( port );
3754   sock.sin_family = hp->h_addrtype;
3755   sock.sin_addr.s_addr = INADDR_ANY;
3756   res = socket(hp->h_addrtype, type, 0);
3757   if (res == -1) 
3758     { DEBUG(0,("socket failed\n")); return -1; }
3759
3760   {
3761     int one=1;
3762     setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
3763   }
3764
3765   /* now we've got a socket - we need to bind it */
3766   if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) 
3767     { 
3768       if (port) {
3769         if (port == 139 || port == 137)
3770           DEBUG(dlevel,("bind failed on port %d (%s)\n",
3771                         port,strerror(errno))); 
3772         close(res); 
3773
3774         if (dlevel > 0 && port < 1000)
3775           port = 7999;
3776
3777         if (port >= 1000 && port < 9000)
3778           return(open_socket_in(type,port+1,dlevel));
3779       }
3780
3781       return(-1); 
3782     }
3783   DEBUG(3,("bind succeeded on port %d\n",port));
3784
3785   return res;
3786 }
3787
3788
3789 /****************************************************************************
3790   create an outgoing socket
3791   **************************************************************************/
3792 int open_socket_out(int type, struct in_addr *addr, int port )
3793 {
3794   struct sockaddr_in sock_out;
3795   int res;
3796
3797   /* create a socket to write to */
3798   res = socket(PF_INET, type, 0);
3799   if (res == -1) 
3800     { DEBUG(0,("socket error\n")); return -1; }
3801
3802   if (type != SOCK_STREAM) return(res);
3803   
3804   bzero((char *)&sock_out,sizeof(sock_out));
3805   putip((char *)&sock_out.sin_addr,(char *)addr);
3806   
3807   sock_out.sin_port = htons( port );
3808   sock_out.sin_family = PF_INET;
3809
3810   DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port));
3811   
3812   /* and connect it to the destination */
3813   if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))<0) {
3814     DEBUG(0,("connect error: %s\n",strerror(errno))); 
3815     close(res); 
3816     return(-1);
3817   }
3818
3819   return res;
3820 }
3821
3822
3823 /****************************************************************************
3824 interpret a protocol description string, with a default
3825 ****************************************************************************/
3826 int interpret_protocol(char *str,int def)
3827 {
3828   if (strequal(str,"NT1"))
3829     return(PROTOCOL_NT1);
3830   if (strequal(str,"LANMAN2"))
3831     return(PROTOCOL_LANMAN2);
3832   if (strequal(str,"LANMAN1"))
3833     return(PROTOCOL_LANMAN1);
3834   if (strequal(str,"CORE"))
3835     return(PROTOCOL_CORE);
3836   if (strequal(str,"COREPLUS"))
3837     return(PROTOCOL_COREPLUS);
3838   if (strequal(str,"CORE+"))
3839     return(PROTOCOL_COREPLUS);
3840   
3841   DEBUG(0,("Unrecognised protocol level %s\n",str));
3842   
3843   return(def);
3844 }
3845
3846 /****************************************************************************
3847 interpret a security level
3848 ****************************************************************************/
3849 int interpret_security(char *str,int def)
3850 {
3851   if (strequal(str,"SERVER"))
3852     return(SEC_SERVER);
3853   if (strequal(str,"USER"))
3854     return(SEC_USER);
3855   if (strequal(str,"SHARE"))
3856     return(SEC_SHARE);
3857   
3858   DEBUG(0,("Unrecognised security level %s\n",str));
3859   
3860   return(def);
3861 }
3862
3863
3864 /****************************************************************************
3865 interpret an internet address or name into an IP address in 4 byte form
3866 ****************************************************************************/
3867 unsigned long interpret_addr(char *str)
3868 {
3869   struct hostent *hp;
3870   unsigned long res;
3871
3872   if (strcmp(str,"0.0.0.0") == 0) return(0);
3873   if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
3874
3875   /* if it's in the form of an IP address then get the lib to interpret it */
3876   if (isdigit(str[0])) {
3877     res = inet_addr(str);
3878   } else {
3879     /* otherwise assume it's a network name of some sort and use Get_Hostbyname */
3880     if ((hp = Get_Hostbyname(str)) == 0) {
3881       DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
3882       return 0;
3883     }
3884     putip((char *)&res,(char *)hp->h_addr);
3885   }
3886
3887   if (res == (unsigned long)-1) return(0);
3888
3889   return(res);
3890 }
3891
3892 /*******************************************************************
3893   a convenient addition to interpret_addr()
3894   ******************************************************************/
3895 struct in_addr *interpret_addr2(char *str)
3896 {
3897   static struct in_addr ret;
3898   unsigned long a = interpret_addr(str);
3899   putip((char *)&ret,(char *)&a);
3900   return(&ret);
3901 }
3902
3903 /*******************************************************************
3904   check if an IP is the 0.0.0.0
3905   ******************************************************************/
3906 BOOL zero_ip(struct in_addr ip)
3907 {
3908   unsigned long a;
3909   putip((char *)&a,(char *)&ip);
3910   return(a == 0);
3911 }
3912
3913 #define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
3914
3915 /****************************************************************************
3916 interpret an 8 byte "filetime" structure to a time_t
3917 It's originally in "100ns units since jan 1st 1601"
3918
3919 It appears to be kludge-GMT (at least for file listings). This means
3920 its the GMT you get by taking a localtime and adding the
3921 serverzone. This is NOT the same as GMT in some cases. This routine
3922 converts this to real GMT.
3923 ****************************************************************************/
3924 time_t interpret_long_date(char *p)
3925 {
3926   double d;
3927   time_t ret;
3928   uint32 tlow,thigh;
3929   tlow = IVAL(p,0);
3930   thigh = IVAL(p,4);
3931
3932   if (thigh == 0) return(0);
3933
3934   d = ((double)thigh)*4.0*(double)(1<<30);
3935   d += (tlow&0xFFF00000);
3936   d *= 1.0e-7;
3937  
3938   /* now adjust by 369 years to make the secs since 1970 */
3939   d -= TIME_FIXUP_CONSTANT;
3940
3941   if (d>=MAXINT)
3942     return(0);
3943
3944   ret = (time_t)(d+0.5);
3945
3946   /* this takes us from kludge-GMT to real GMT */
3947   ret += TimeDiff(ret) - serverzone;
3948
3949   return(ret);
3950 }
3951
3952
3953 /****************************************************************************
3954 put a 8 byte filetime from a time_t
3955 This takes real GMT as input and converts to kludge-GMT
3956 ****************************************************************************/
3957 void put_long_date(char *p,time_t t)
3958 {
3959   uint32 tlow,thigh;
3960   double d;
3961
3962   if (t==0) {
3963     SIVAL(p,0,0); SIVAL(p,4,0);
3964     return;
3965   }
3966
3967   /* this converts GMT to kludge-GMT */
3968   t -= TimeDiff(t) - serverzone; 
3969
3970   d = (double) (t);
3971
3972   d += TIME_FIXUP_CONSTANT;
3973
3974   d *= 1.0e7;
3975
3976   thigh = (uint32)(d * (1.0/(4.0*(double)(1<<30))));
3977   tlow = (uint32)(d - ((double)thigh)*4.0*(double)(1<<30));
3978
3979   SIVAL(p,0,tlow);
3980   SIVAL(p,4,thigh);
3981 }
3982
3983 /*******************************************************************
3984 sub strings with useful parameters
3985 ********************************************************************/
3986 void standard_sub_basic(char *s)
3987 {
3988   if (!strchr(s,'%')) return;
3989
3990   string_sub(s,"%R",remote_proto);
3991   string_sub(s,"%a",remote_arch);
3992   string_sub(s,"%m",remote_machine);
3993   string_sub(s,"%L",local_machine);
3994
3995   if (!strchr(s,'%')) return;
3996
3997   string_sub(s,"%v",VERSION);
3998   string_sub(s,"%h",myhostname);
3999   string_sub(s,"%U",sesssetup_user);
4000
4001   if (!strchr(s,'%')) return;
4002
4003   string_sub(s,"%I",Client_info.addr);
4004   string_sub(s,"%M",Client_info.name);
4005   string_sub(s,"%T",timestring());
4006
4007   if (!strchr(s,'%')) return;
4008
4009   {
4010     char pidstr[10];
4011     sprintf(pidstr,"%d",(int)getpid());
4012     string_sub(s,"%d",pidstr);
4013   }
4014
4015   if (!strchr(s,'%')) return;
4016
4017   {
4018     struct passwd *pass = Get_Pwnam(sesssetup_user,False);
4019     if (pass) {
4020       string_sub(s,"%G",gidtoname(pass->pw_gid));
4021     }
4022   }
4023 }
4024
4025
4026 /*******************************************************************
4027 write a string in unicoode format
4028 ********************************************************************/
4029 int PutUniCode(char *dst,char *src)
4030 {
4031   int ret = 0;
4032   while (*src) {
4033     dst[ret++] = src[0];
4034     dst[ret++] = 0;    
4035     src++;
4036   }
4037   dst[ret++]=0;
4038   dst[ret++]=0;
4039   return(ret);
4040 }
4041
4042
4043 pstring smbrun_path = SMBRUN;
4044
4045 /****************************************************************************
4046 run a command via system() using smbrun
4047 ****************************************************************************/
4048 int smbrun(char *cmd,char *outfile)
4049 {
4050   int ret;
4051   pstring syscmd;  
4052
4053   if (!file_exist(smbrun_path,NULL))
4054     {
4055       DEBUG(0,("SMBRUN ERROR: Can't find %s. Installation problem?\n",smbrun_path));
4056       return(1);
4057     }
4058
4059   sprintf(syscmd,"%s \"(%s 2>&1) > %s\"",
4060           smbrun_path,cmd,
4061           outfile?outfile:"/dev/null");
4062
4063   DEBUG(5,("smbrun - running %s ",syscmd));
4064   ret = system(syscmd);
4065   DEBUG(5,("gave %d\n",ret));
4066   return(ret);
4067 }
4068
4069
4070 /****************************************************************************
4071 a wrapper for gethostbyname() that tries with all lower and all upper case 
4072 if the initial name fails
4073 ****************************************************************************/
4074 struct hostent *Get_Hostbyname(char *name)
4075 {
4076   char *name2 = strdup(name);
4077   struct hostent *ret;
4078
4079   if (!name2)
4080     {
4081       DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
4082       exit(0);
4083     }
4084
4085   if (!isalnum(*name2))
4086     {
4087       free(name2);
4088       return(NULL);
4089     }
4090
4091   ret = gethostbyname(name2);
4092   if (ret != NULL)
4093     {
4094       free(name2);
4095       return(ret);
4096     }
4097
4098   /* try with all lowercase */
4099   strlower(name2);
4100   ret = gethostbyname(name2);
4101   if (ret != NULL)
4102     {
4103       free(name2);
4104       return(ret);
4105     }
4106
4107   /* try with all uppercase */
4108   strupper(name2);
4109   ret = gethostbyname(name2);
4110   if (ret != NULL)
4111     {
4112       free(name2);
4113       return(ret);
4114     }
4115   
4116   /* nothing works :-( */
4117   free(name2);
4118   return(NULL);
4119 }
4120
4121
4122 /****************************************************************************
4123 check if a process exists. Does this work on all unixes?
4124 ****************************************************************************/
4125 BOOL process_exists(int pid)
4126 {
4127 #ifdef LINUX
4128   fstring s;
4129   sprintf(s,"/proc/%d",pid);
4130   return(directory_exist(s,NULL));
4131 #else
4132   {
4133     static BOOL tested=False;
4134     static BOOL ok=False;
4135     fstring s;
4136     if (!tested) {
4137       tested = True;
4138       sprintf(s,"/proc/%05d",getpid());
4139       ok = file_exist(s,NULL);
4140     }
4141     if (ok) {
4142       sprintf(s,"/proc/%05d",pid);
4143       return(file_exist(s,NULL));
4144     }
4145   }
4146
4147   /* a best guess for non root access */
4148   if (geteuid() != 0) return(True);
4149
4150   /* otherwise use kill */
4151   return(pid == getpid() || kill(pid,0) == 0);
4152 #endif
4153 }
4154
4155
4156 /*******************************************************************
4157 turn a uid into a user name
4158 ********************************************************************/
4159 char *uidtoname(int uid)
4160 {
4161   static char name[40];
4162   struct passwd *pass = getpwuid(uid);
4163   if (pass) return(pass->pw_name);
4164   sprintf(name,"%d",uid);
4165   return(name);
4166 }
4167
4168 /*******************************************************************
4169 turn a gid into a group name
4170 ********************************************************************/
4171 char *gidtoname(int gid)
4172 {
4173   static char name[40];
4174   struct group *grp = getgrgid(gid);
4175   if (grp) return(grp->gr_name);
4176   sprintf(name,"%d",gid);
4177   return(name);
4178 }
4179
4180 /*******************************************************************
4181 block sigs
4182 ********************************************************************/
4183 void BlockSignals(BOOL block)
4184 {
4185 #ifdef USE_SIGBLOCK
4186   int block_mask = (sigmask(SIGTERM)|sigmask(SIGQUIT)|sigmask(SIGSEGV)
4187                     |sigmask(SIGCHLD)|sigmask(SIGQUIT)|sigmask(SIGBUS)|
4188                     sigmask(SIGINT));
4189   if (block) 
4190     sigblock(block_mask);
4191   else
4192     sigunblock(block_mask);
4193 #endif
4194 }
4195
4196 #if AJT
4197 /*******************************************************************
4198 my own panic function - not suitable for general use
4199 ********************************************************************/
4200 void ajt_panic(void)
4201 {
4202   pstring cmd = "/usr/bin/X11/xedit -display :0 /tmp/ERROR_FAULT &";
4203   smbrun(cmd,NULL);
4204 }
4205 #endif
4206
4207 #ifdef USE_DIRECT
4208 #define DIRECT direct
4209 #else
4210 #define DIRECT dirent
4211 #endif
4212
4213 /*******************************************************************
4214 a readdir wrapper which just returns the file name
4215 also return the inode number if requested
4216 ********************************************************************/
4217 char *readdirname(void *p)
4218 {
4219   struct DIRECT *ptr;
4220   char *dname;
4221
4222   if (!p) return(NULL);
4223   
4224   ptr = (struct DIRECT *)readdir(p);
4225   if (!ptr) return(NULL);
4226
4227   dname = ptr->d_name;
4228
4229 #ifdef KANJI
4230   {
4231     static pstring buf;
4232     strcpy(buf, dname);
4233     unix_to_dos(buf, True);
4234     dname = buf;
4235   }
4236 #endif
4237
4238 #ifdef NEXT2
4239   if (telldir(p) < 0) return(NULL);
4240 #endif
4241
4242 #ifdef SUNOS5
4243   /* this handles a broken compiler setup, causing a mixture
4244    of BSD and SYSV headers and libraries */
4245   {
4246     static BOOL broken_readdir = False;
4247     if (!broken_readdir && !(*(dname)) && strequal("..",dname-2))
4248       {
4249         DEBUG(0,("Your readdir() is broken. You have somehow mixed SYSV and BSD headers and libraries\n"));
4250         broken_readdir = True;
4251       }
4252     if (broken_readdir)
4253       return(dname-2);
4254   }
4255 #endif
4256
4257   return(dname);
4258 }
4259
4260
4261
4262 #if (defined(SecureWare) && defined(SCO))
4263 /* This is needed due to needing the nap() function but we don't want
4264    to include the Xenix libraries since that will break other things...
4265    BTW: system call # 0x0c28 is the same as calling nap() */
4266 long nap(long milliseconds) {
4267   return syscall(0x0c28, milliseconds);
4268 }
4269 #endif
4270
4271 #ifdef NO_INITGROUPS
4272 #include <sys/types.h>
4273 #include <limits.h>
4274 #include <grp.h>
4275
4276 #ifndef NULL
4277 #define NULL (void *)0
4278 #endif
4279
4280 /****************************************************************************
4281  some systems don't have an initgroups call 
4282 ****************************************************************************/
4283 int initgroups(char *name,gid_t id)
4284 {
4285 #ifdef NO_SETGROUPS
4286   /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
4287   return(0);
4288 #else
4289   gid_t  grouplst[NGROUPS_MAX];
4290   int    i,j;
4291   struct group *g;
4292   char   *gr;
4293
4294   grouplst[0] = id;
4295   i = 1;
4296   while (i < NGROUPS_MAX && 
4297          ((g = (struct group *)getgrent()) != (struct group *)NULL)) 
4298     {
4299       if (g->gr_gid == id)
4300         continue;
4301       j = 0;
4302       gr = g->gr_mem[0];
4303       while (gr && (*gr != (char)NULL)) {
4304         if (strcmp(name,gr) == 0) {
4305           grouplst[i] = g->gr_gid;
4306           i++;
4307           gr = (char *)NULL;
4308           break;
4309         }
4310         gr = g->gr_mem[++j];
4311       }
4312     }
4313   endgrent();
4314   return(setgroups(i,grouplst));
4315 #endif
4316 }
4317 #endif
4318
4319
4320 #if WRAP_MALLOC
4321
4322 /* undo the wrapping temporarily */
4323 #undef malloc
4324 #undef realloc
4325 #undef free
4326
4327 /****************************************************************************
4328 wrapper for malloc() to catch memory errors
4329 ****************************************************************************/
4330 void *malloc_wrapped(int size,char *file,int line)
4331 {
4332 #ifdef xx_old_malloc
4333   void *res = xx_old_malloc(size);
4334 #else
4335   void *res = malloc(size);
4336 #endif
4337   DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
4338         file,line,
4339         size,(unsigned int)res));
4340   return(res);
4341 }
4342
4343 /****************************************************************************
4344 wrapper for realloc() to catch memory errors
4345 ****************************************************************************/
4346 void *realloc_wrapped(void *ptr,int size,char *file,int line)
4347 {
4348 #ifdef xx_old_realloc
4349   void *res = xx_old_realloc(ptr,size);
4350 #else
4351   void *res = realloc(ptr,size);
4352 #endif
4353   DEBUG(3,("Realloc\n"));
4354   DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
4355         file,line,
4356         (unsigned int)ptr));
4357   DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
4358         file,line,
4359         size,(unsigned int)res));
4360   return(res);
4361 }
4362
4363 /****************************************************************************
4364 wrapper for free() to catch memory errors
4365 ****************************************************************************/
4366 void free_wrapped(void *ptr,char *file,int line)
4367 {
4368 #ifdef xx_old_free
4369   xx_old_free(ptr);
4370 #else
4371   free(ptr);
4372 #endif
4373   DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
4374         file,line,(unsigned int)ptr));
4375   return;
4376 }
4377
4378 /* and re-do the define for spots lower in this file */
4379 #define malloc(size) malloc_wrapped(size,__FILE__,__LINE__)
4380 #define realloc(ptr,size) realloc_wrapped(ptr,size,__FILE__,__LINE__)
4381 #define free(ptr) free_wrapped(ptr,__FILE__,__LINE__)
4382
4383 #endif
4384
4385 #ifdef REPLACE_STRSTR
4386 /****************************************************************************
4387 Mips version of strstr doesn't seem to work correctly.
4388 There is a #define in includes.h to redirect calls to this function.
4389 ****************************************************************************/
4390 char *Strstr(char *s, char *p)
4391 {
4392         int len = strlen(p);
4393
4394         while ( *s != '\0' ) {
4395                 if ( strncmp(s, p, len) == 0 )
4396                 return s;
4397                 s++;
4398         }
4399
4400         return NULL;
4401 }
4402 #endif /* REPLACE_STRSTR */
4403
4404
4405 #ifdef REPLACE_MKTIME
4406 /*******************************************************************
4407 a mktime() replacement for those who don't have it - contributed by 
4408 C.A. Lademann <cal@zls.com>
4409 ********************************************************************/
4410 #define  MINUTE  60
4411 #define  HOUR    60*MINUTE
4412 #define  DAY             24*HOUR
4413 #define  YEAR    365*DAY
4414 time_t Mktime(struct tm      *t)
4415 {
4416   struct tm       *u;
4417   time_t  epoch = 0;
4418   int             mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
4419   y, m, i;
4420
4421   if(t->tm_year < 70)
4422     return((time_t)-1);
4423
4424   epoch = (t->tm_year - 70) * YEAR + 
4425     (t->tm_year / 4 - 70 / 4 - t->tm_year / 100) * DAY;
4426
4427   y = t->tm_year;
4428   m = 0;
4429
4430   for(i = 0; i < t->tm_mon; i++) {
4431     epoch += mon [m] * DAY;
4432     if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
4433       epoch += DAY;
4434     
4435     if(++m > 11) {
4436       m = 0;
4437       y++;
4438     }
4439   }
4440
4441   epoch += (t->tm_mday - 1) * DAY;
4442   epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
4443   
4444   if((u = localtime(&epoch)) != NULL) {
4445     t->tm_sec = u->tm_sec;
4446     t->tm_min = u->tm_min;
4447     t->tm_hour = u->tm_hour;
4448     t->tm_mday = u->tm_mday;
4449     t->tm_mon = u->tm_mon;
4450     t->tm_year = u->tm_year;
4451     t->tm_wday = u->tm_wday;
4452     t->tm_yday = u->tm_yday;
4453     t->tm_isdst = u->tm_isdst;
4454 #ifndef NO_TM_NAME
4455     memcpy(t->tm_name, u->tm_name, LTZNMAX);
4456 #endif
4457   }
4458
4459   return(epoch);
4460 }
4461 #endif /* REPLACE_MKTIME */
4462
4463
4464
4465 #ifdef REPLACE_RENAME
4466 /* Rename a file. (from libiberty in GNU binutils)  */
4467 int
4468 rename (zfrom, zto)
4469      const char *zfrom;
4470      const char *zto;
4471 {
4472   if (link (zfrom, zto) < 0)
4473     {
4474       if (errno != EEXIST)
4475         return -1;
4476       if (unlink (zto) < 0
4477           || link (zfrom, zto) < 0)
4478         return -1;
4479     }
4480   return unlink (zfrom);
4481 }
4482 #endif
4483
4484
4485 #ifdef REPLACE_INNETGR
4486 /*
4487  * Search for a match in a netgroup. This replaces it on broken systems.
4488  */
4489 int InNetGr(group, host, user, dom)
4490         char *group, *host, *user, *dom;
4491 {
4492   char *hst, *usr, *dm;
4493   
4494   setnetgrent(group);
4495   while (getnetgrent(&hst, &usr, &dm))
4496     if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
4497         ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
4498         ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
4499       endnetgrent();
4500       return (1);
4501     }
4502   endnetgrent();
4503   return (0);
4504 }
4505 #endif
4506
4507
4508 #if WRAP_MEMCPY
4509 #undef memcpy
4510 /*******************************************************************
4511 a wrapper around memcpy for diagnostic purposes
4512 ********************************************************************/
4513 void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line)
4514 {
4515   if (l>64 && (((int)d)%4) != (((int)s)%4))
4516     DEBUG(4,("Misaligned memcpy(0x%X,0x%X,%d) at %s(%d)\n",d,s,l,fname,line));
4517 #ifdef xx_old_memcpy  
4518   return(xx_old_memcpy(d,s,l));
4519 #else
4520   return(memcpy(d,s,l));
4521 #endif
4522 }
4523 #define memcpy(d,s,l) memcpy_wrapped(d,s,l,__FILE__,__LINE__)
4524 #endif
4525
4526
4527