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