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