a huge pile of changes :-)
[samba.git] / source3 / lib / util.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Samba utility functions
5    Copyright (C) Andrew Tridgell 1992-1995
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23 #include "loadparm.h"
24
25 pstring scope = "";
26
27 int DEBUGLEVEL = 1;
28
29 BOOL passive = False;
30
31 int Protocol = PROTOCOL_COREPLUS;
32
33 /* 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     {
1825       DEBUG(2,("read socket failed. ERRNO=%d\n",errno));
1826       return(0);
1827     }
1828
1829   lastip = *(struct in_addr *) &sock.sa_data[2];
1830   lastport = ntohs(((struct sockaddr_in *)&sock)->sin_port);
1831
1832   return(ret);
1833 }
1834
1835 /****************************************************************************
1836 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
1837 else
1838 if SYSV use O_NDELAY
1839 if BSD use FNDELAY
1840 ****************************************************************************/
1841 int set_blocking(int fd, BOOL set)
1842 {
1843 int val;
1844 #ifdef O_NONBLOCK
1845 #define FLAG_TO_SET O_NONBLOCK
1846 #else
1847 #ifdef SYSV
1848 #define FLAG_TO_SET O_NDELAY
1849 #else /* BSD */
1850 #define FLAG_TO_SET FNDELAY
1851 #endif
1852 #endif
1853
1854   if((val = fcntl(fd, F_GETFL, 0))==-1)
1855         return -1;
1856   if(set) /* Turn blocking on - ie. clear nonblock flag */
1857         val &= ~FLAG_TO_SET;
1858   else
1859     val |= FLAG_TO_SET;
1860   return fcntl( fd, F_SETFL, val);
1861 #undef FLAG_TO_SET
1862 }
1863
1864
1865 /****************************************************************************
1866 Calculate the difference in timeout values. Return 1 if val1 > val2,
1867 0 if val1 == val2, -1 if val1 < val2. Stores result in retval. retval
1868 may be == val1 or val2
1869 ****************************************************************************/
1870 static int tval_sub( struct timeval *retval, struct timeval *val1, struct timeval *val2)
1871 {
1872   int usecdiff = val1->tv_usec - val2->tv_usec;
1873   int secdiff = val1->tv_sec - val2->tv_sec;
1874   if(usecdiff < 0) {
1875     usecdiff = 1000000 + usecdiff;
1876     secdiff--;
1877   }
1878   retval->tv_sec = secdiff;
1879   retval->tv_usec = usecdiff;
1880   if(secdiff < 0)
1881     return -1;
1882   if(secdiff > 0)
1883     return 1;
1884   return (usecdiff < 0 ) ? -1 : ((usecdiff > 0 ) ? 1 : 0);
1885 }
1886
1887 /****************************************************************************
1888 read data from a device with a timout in msec.
1889 mincount = if timeout, minimum to read before returning
1890 maxcount = number to be read.
1891 ****************************************************************************/
1892 int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out,BOOL exact)
1893 {
1894   fd_set fds;
1895   int selrtn;
1896   int readret;
1897   int nread = 0;
1898   struct timeval timeout, tval1, tval2, tvaldiff;
1899   int error_limit = 5;
1900
1901   /* just checking .... */
1902   if (maxcnt <= 0) return(0);
1903
1904   if(time_out == -2)
1905     time_out = DEFAULT_PIPE_TIMEOUT;
1906
1907   /* Blocking read */
1908   if(time_out < 0) {
1909     if (mincnt == 0) mincnt = maxcnt;
1910
1911     while (nread < mincnt)
1912       {
1913         readret = read(fd, buf + nread, maxcnt - nread);
1914         if (readret <= 0) return(nread);
1915         nread += readret;
1916       }
1917     return(nread);
1918   }
1919   
1920   /* Non blocking read */
1921   if(time_out == 0) {
1922     set_blocking(fd, False);
1923     nread = read_data(fd, buf, mincnt);
1924     if (nread < maxcnt)
1925       nread += read(fd,buf+nread,maxcnt-nread);
1926     if(nread == -1 && errno == EWOULDBLOCK)
1927       nread = 0;
1928     set_blocking(fd,True);
1929     return nread;
1930   }
1931
1932   /* Most difficult - timeout read */
1933   /* If this is ever called on a disk file and 
1934          mincnt is greater then the filesize then
1935          system performance will suffer severely as 
1936          select always return true on disk files */
1937
1938   /* Set initial timeout */
1939   timeout.tv_sec = time_out / 1000;
1940   timeout.tv_usec = 1000 * (time_out % 1000);
1941
1942   /* As most UNIXes don't modify the value of timeout
1943      when they return from select we need to get the timeofday (in usec)
1944      now, and also after the select returns so we know
1945      how much time has elapsed */
1946
1947   if (exact)
1948     GetTimeOfDay( &tval1);
1949   nread = 0; /* Number of bytes we have read */
1950
1951   for(;;) 
1952     {      
1953       FD_ZERO(&fds);
1954       FD_SET(fd,&fds);
1955       
1956       selrtn = sys_select(&fds,&timeout);
1957       
1958       /* Check if error */
1959       if(selrtn == -1) {
1960         errno = EBADF;
1961         return -1;
1962       }
1963       
1964       /* Did we timeout ? */
1965       if (selrtn == 0) {
1966         if (nread < mincnt) return -1;
1967         break; /* Yes */
1968       }
1969       
1970       readret = read(fd, buf+nread, maxcnt-nread);
1971       if (readret == 0 && nread < mincnt) {
1972         /* error_limit should not really be needed, but some systems
1973            do strange things ...  I don't want to just continue
1974            indefinately in case we get an infinite loop */
1975         if (error_limit--) continue;
1976         return(-1);
1977       }
1978
1979       if (readret < 0) {
1980         /* force a particular error number for
1981            portability */
1982         DEBUG(5,("read gave error %s\n",strerror(errno)));
1983         errno = EBADF;
1984         return -1;
1985       }
1986       
1987       nread += readret;
1988       
1989       /* If we have read more than mincnt then return */
1990       if (nread >= mincnt)
1991         break;
1992
1993       /* We need to do another select - but first reduce the
1994          time_out by the amount of time already elapsed - if
1995          this is less than zero then return */
1996       if (exact) {
1997         GetTimeOfDay(&tval2);
1998         (void)tval_sub( &tvaldiff, &tval2, &tval1);
1999       
2000         if (tval_sub(&timeout, &timeout, &tvaldiff) <= 0) 
2001           break; /* We timed out */
2002       }
2003       
2004       /* Save the time of day as we need to do the select 
2005          again (saves a system call) */
2006       tval1 = tval2;
2007     }
2008
2009   /* Return the number we got */
2010   return(nread);
2011 }
2012
2013 /****************************************************************************
2014 read data from the client. Maxtime is in milliseconds
2015 ****************************************************************************/
2016 int read_max_udp(int fd,char *buffer,int bufsize,int maxtime)
2017 {
2018   fd_set fds;
2019   int selrtn;
2020   int nread;
2021   struct timeval timeout;
2022  
2023   FD_ZERO(&fds);
2024   FD_SET(fd,&fds);
2025
2026   timeout.tv_sec = maxtime / 1000;
2027   timeout.tv_usec = (maxtime % 1000) * 1000;
2028
2029   selrtn = sys_select(&fds,maxtime>0?&timeout:NULL);
2030
2031   if (!FD_ISSET(fd,&fds))
2032     return 0;
2033
2034   nread = read_udp_socket(fd, buffer, bufsize);
2035
2036   /* return the number got */
2037   return(nread);
2038 }
2039
2040 /*******************************************************************
2041 find the difference in milliseconds between two struct timeval
2042 values
2043 ********************************************************************/
2044 int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew)
2045 {
2046   return((tvalnew->tv_sec - tvalold->tv_sec)*1000 + 
2047          ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000);  
2048 }
2049
2050 /****************************************************************************
2051 send a keepalive packet (rfc1002)
2052 ****************************************************************************/
2053 BOOL send_keepalive(int client)
2054 {
2055   unsigned char buf[4];
2056
2057   buf[0] = 0x85;
2058   buf[1] = buf[2] = buf[3] = 0;
2059
2060   return(write_data(client,(char *)buf,4) == 4);
2061 }
2062
2063
2064
2065 /****************************************************************************
2066   read data from the client, reading exactly N bytes. 
2067 ****************************************************************************/
2068 int read_data(int fd,char *buffer,int N)
2069 {
2070   int  ret;
2071   int total=0;  
2072  
2073   while (total < N)
2074     {
2075       ret = read(fd,buffer + total,N - total);
2076
2077       /* this is for portability */
2078       if (ret < 0)
2079         errno = EBADF;
2080
2081       if (ret <= 0)
2082         return total;
2083       total += ret;
2084     }
2085   return total;
2086 }
2087
2088
2089 /****************************************************************************
2090   write data to a fd 
2091 ****************************************************************************/
2092 int write_data(int fd,char *buffer,int N)
2093 {
2094   int total=0;
2095   int ret;
2096
2097   while (total < N)
2098     {
2099       ret = write(fd,buffer + total,N - total);
2100
2101       if (ret <= 0)
2102         return total;
2103
2104       total += ret;
2105     }
2106   return total;
2107 }
2108
2109
2110 /* variables used by the read prediction module */
2111 int rp_fd = -1;
2112 int rp_offset = 0;
2113 int rp_length = 0;
2114 int rp_alloced = 0;
2115 int rp_predict_fd = -1;
2116 int rp_predict_offset = 0;
2117 int rp_predict_length = 0;
2118 int rp_timeout = 5;
2119 time_t rp_time = 0;
2120 char *rp_buffer = NULL;
2121 BOOL predict_skip=False;
2122 time_t smb_last_time=(time_t)0;
2123
2124 /****************************************************************************
2125 handle read prediction on a file
2126 ****************************************************************************/
2127 int read_predict(int fd,int offset,char *buf,char **ptr,int num)
2128 {
2129   int ret = 0;
2130   int possible = rp_length - (offset - rp_offset);
2131
2132   possible = MIN(possible,num);
2133
2134   /* give data if possible */
2135   if (fd == rp_fd && 
2136       offset >= rp_offset && 
2137       possible>0 &&
2138       smb_last_time-rp_time < rp_timeout)
2139     {
2140       ret = possible;
2141       if (buf)
2142         memcpy(buf,rp_buffer + (offset-rp_offset),possible);
2143       else
2144         *ptr = rp_buffer + (offset-rp_offset);
2145       DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num));
2146     }
2147
2148   if (ret == num) {
2149     predict_skip = True;
2150   } else {
2151     predict_skip = False;
2152
2153     /* prepare the next prediction */
2154     rp_predict_fd = fd;
2155     rp_predict_offset = offset + num;
2156     rp_predict_length = num;
2157   }
2158
2159   if (ret < 0) ret = 0;
2160
2161   return(ret);
2162 }
2163
2164 /****************************************************************************
2165 pre-read some data
2166 ****************************************************************************/
2167 void do_read_prediction()
2168 {
2169   if (predict_skip) return;
2170
2171   if (rp_predict_fd == -1) 
2172     return;
2173
2174   rp_fd = rp_predict_fd;
2175   rp_offset = rp_predict_offset;
2176   rp_length = 0;
2177
2178   rp_predict_fd = -1;
2179
2180   rp_predict_length = MIN(rp_predict_length,2*ReadSize);
2181   rp_predict_length = MAX(rp_predict_length,1024);
2182   rp_offset = (rp_offset/1024)*1024;
2183   rp_predict_length = (rp_predict_length/1024)*1024;
2184
2185   if (rp_predict_length > rp_alloced)
2186     {
2187       rp_buffer = Realloc(rp_buffer,rp_predict_length);
2188       rp_alloced = rp_predict_length;
2189       if (!rp_buffer)
2190         {
2191           DEBUG(0,("can't allocate read-prediction buffer\n"));
2192           rp_predict_fd = -1;
2193           rp_fd = -1;
2194           rp_alloced = 0;
2195           return;
2196         }
2197     }
2198
2199   if (lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) {
2200     rp_fd = -1;
2201     rp_predict_fd = -1;
2202     return;
2203   }
2204
2205   rp_length = read(rp_fd,rp_buffer,rp_predict_length);
2206   rp_time = time(NULL);
2207   if (rp_length < 0)
2208     rp_length = 0;
2209 }
2210
2211 /****************************************************************************
2212 invalidate read-prediction on a fd
2213 ****************************************************************************/
2214 void invalidate_read_prediction(int fd)
2215 {
2216  if (rp_fd == fd) 
2217    rp_fd = -1;
2218  if (rp_predict_fd == fd)
2219    rp_predict_fd = -1;
2220 }
2221
2222
2223 /****************************************************************************
2224 transfer some data between two fd's
2225 ****************************************************************************/
2226 int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align)
2227 {
2228   static char *buf=NULL;  
2229   char *buf1,*abuf;
2230   static int size = 0;
2231   int total = 0;
2232
2233   DEBUG(4,("transfer_file %d  (head=%d) called\n",n,headlen));
2234
2235   if ((size < ReadSize) && buf) {
2236     free(buf);
2237     buf = NULL;
2238   }
2239
2240   size = MAX(ReadSize,1024);
2241
2242   while (!buf && size>0) {
2243     buf = (char *)Realloc(buf,size+8);
2244     if (!buf) size /= 2;
2245   }
2246   if (!buf) {
2247     DEBUG(0,("Can't allocate transfer buffer!\n"));
2248     exit(1);
2249   }
2250
2251   abuf = buf + (align%8);
2252
2253   if (header)
2254     n += headlen;
2255
2256   while (n > 0)
2257     {
2258       int s = MIN(n,size);
2259       int ret,ret2=0;
2260
2261       ret = 0;
2262
2263       if (header && (headlen >= MIN(s,1024))) {
2264         buf1 = header;
2265         s = headlen;
2266         ret = headlen;
2267         headlen = 0;
2268         header = NULL;
2269       } else {
2270         buf1 = abuf;
2271       }
2272
2273       if (header && headlen > 0)
2274         {
2275           ret = MIN(headlen,size);
2276           memcpy(buf1,header,ret);
2277           headlen -= ret;
2278           header += ret;
2279           if (headlen <= 0) header = NULL;
2280         }
2281
2282       if (s > ret)
2283         ret += read(infd,buf1+ret,s-ret);
2284
2285       if (ret > 0)
2286         {
2287           ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret);
2288           if (ret2 > 0) total += ret2;
2289           /* if we can't write then dump excess data */
2290           if (ret2 != ret)
2291             transfer_file(infd,-1,n-(ret+headlen),NULL,0,0);
2292         }
2293       if (ret <= 0 || ret2 != ret)
2294         return(total);
2295       n -= ret;
2296     }
2297   return(total);
2298 }
2299
2300
2301 /****************************************************************************
2302 read 4 bytes of a smb packet and return the smb length of the packet
2303 possibly store the result in the buffer
2304 ****************************************************************************/
2305 int read_smb_length(int fd,char *inbuf,int timeout)
2306 {
2307   char *buffer;
2308   char buf[4];
2309   int len=0, msg_type;
2310   BOOL ok=False;
2311
2312   if (inbuf)
2313     buffer = inbuf;
2314   else
2315     buffer = buf;
2316
2317   while (!ok)
2318     {
2319       if (timeout > 0)
2320         ok = (read_with_timeout(fd,buffer,4,4,timeout,False) == 4);
2321       else      
2322         ok = (read_data(fd,buffer,4) == 4);
2323
2324       if (!ok)
2325         {
2326           if (timeout>0)
2327             {
2328               DEBUG(10,("select timeout (%d)\n", timeout));
2329               return(-1);
2330             }
2331           else
2332             {
2333               DEBUG(6,("couldn't read from client\n"));
2334               exit(1);
2335             }
2336         }
2337
2338       len = smb_len(buffer);
2339       msg_type = CVAL(buffer,0);
2340
2341       if (msg_type == 0x85) 
2342         {
2343           DEBUG(5,( "Got keepalive packet\n"));
2344           ok = False;
2345         }
2346     }
2347
2348   DEBUG(10,("got smb length of %d\n",len));
2349
2350   return(len);
2351 }
2352
2353
2354
2355 /****************************************************************************
2356   read an smb from a fd and return it's length
2357 The timeout is in milli seconds
2358 ****************************************************************************/
2359 BOOL receive_smb(int fd,char *buffer,int timeout)
2360 {
2361   int len;
2362   BOOL ok;
2363
2364   bzero(buffer,smb_size + 100);
2365
2366   len = read_smb_length(fd,buffer,timeout);
2367   if (len == -1)
2368     return(False);
2369
2370   if (len > BUFFER_SIZE) {
2371     DEBUG(0,("Invalid packet length! (%d bytes)\n",len));
2372     if (len > BUFFER_SIZE + (SAFETY_MARGIN/2))
2373       exit(1);
2374   }
2375
2376   ok = (read_data(fd,buffer+4,len) == len);
2377
2378   if (!ok)
2379     {
2380       close_sockets();
2381       exit(1);
2382     }
2383
2384   return(True);
2385 }
2386
2387
2388 /****************************************************************************
2389   send an smb to a fd 
2390 ****************************************************************************/
2391 BOOL send_smb(int fd,char *buffer)
2392 {
2393   int len;
2394   int ret,nwritten=0;
2395   len = smb_len(buffer) + 4;
2396
2397   while (nwritten < len)
2398     {
2399       ret = write_socket(fd,buffer+nwritten,len - nwritten);
2400       if (ret <= 0)
2401         {
2402           DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret));
2403           close_sockets();
2404           exit(1);
2405         }
2406       nwritten += ret;
2407     }
2408
2409
2410   return True;
2411 }
2412
2413
2414 /****************************************************************************
2415 find a pointer to a netbios name
2416 ****************************************************************************/
2417 char *name_ptr(char *buf,int ofs)
2418 {
2419   unsigned char c = *(unsigned char *)(buf+ofs);
2420
2421   if ((c & 0xC0) == 0xC0)
2422     {
2423       uint16 l;
2424       char p[2];
2425       memcpy(p,buf+ofs,2);
2426       p[0] &= ~0xC0;
2427       l = RSVAL(p,0);
2428       DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
2429       return(buf + l);
2430     }
2431   else
2432     return(buf+ofs);
2433 }  
2434
2435 /****************************************************************************
2436 extract a netbios name from a buf
2437 ****************************************************************************/
2438 int name_extract(char *buf,int ofs,char *name)
2439 {
2440   char *p = name_ptr(buf,ofs);
2441   int d = PTR_DIFF(p,buf+ofs);
2442   strcpy(name,"");
2443   if (d < -50 || d > 50) return(0);
2444   return(name_interpret(p,name));
2445 }  
2446   
2447
2448 /****************************************************************************
2449 return the total storage length of a mangled name
2450 ****************************************************************************/
2451 int name_len(char *s)
2452 {
2453   char *s0=s;
2454   unsigned char c = *(unsigned char *)s;
2455   if ((c & 0xC0) == 0xC0)
2456     return(2);
2457   while (*s) s += (*s)+1;
2458   return(PTR_DIFF(s,s0)+1);
2459 }
2460
2461 /****************************************************************************
2462 send a single packet to a port on another machine
2463 ****************************************************************************/
2464 BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
2465 {
2466   BOOL ret;
2467   int out_fd;
2468   struct sockaddr_in sock_out;
2469
2470   if (passive)
2471     return(True);
2472
2473   /* create a socket to write to */
2474   out_fd = socket(AF_INET, type, 0);
2475   if (out_fd == -1) 
2476     {
2477       DEBUG(0,("socket failed"));
2478       return False;
2479     }
2480
2481   /* set the address and port */
2482   bzero((char *)&sock_out,sizeof(sock_out));
2483   putip((char *)&sock_out.sin_addr,(char *)&ip);
2484   sock_out.sin_port = htons( port );
2485   sock_out.sin_family = AF_INET;
2486   
2487   if (DEBUGLEVEL > 0)
2488     DEBUG(3,("sending a packet of len %d to (%s) on port %d of type %s\n",
2489              len,inet_ntoa(ip),port,type==SOCK_DGRAM?"DGRAM":"STREAM"));
2490         
2491   /* send it */
2492   ret = (sendto(out_fd,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
2493
2494   if (!ret)
2495     DEBUG(0,("Packet send to %s(%d) failed ERRNO=%d\n",
2496              inet_ntoa(ip),port,errno));
2497
2498   close(out_fd);
2499   return(ret);
2500 }
2501
2502 /*******************************************************************
2503 sleep for a specified number of milliseconds
2504 ********************************************************************/
2505 void msleep(int t)
2506 {
2507   int tdiff=0;
2508   struct timeval tval,t1,t2;  
2509   fd_set fds;
2510
2511   GetTimeOfDay(&t1);
2512   GetTimeOfDay(&t2);
2513   
2514   while (tdiff < t) {
2515     tval.tv_sec = (t-tdiff)/1000;
2516     tval.tv_usec = 1000*((t-tdiff)%1000);
2517  
2518     FD_ZERO(&fds);
2519     errno = 0;
2520     sys_select(&fds,&tval);
2521
2522     GetTimeOfDay(&t2);
2523     tdiff = TvalDiff(&t1,&t2);
2524   }
2525 }
2526
2527 /****************************************************************************
2528 check if a string is part of a list
2529 ****************************************************************************/
2530 BOOL in_list(char *s,char *list,BOOL casesensitive)
2531 {
2532   pstring tok;
2533   char *p=list;
2534
2535   if (!list) return(False);
2536
2537   while (next_token(&p,tok,LIST_SEP))
2538     {
2539       if (casesensitive) {
2540         if (strcmp(tok,s) == 0)
2541           return(True);
2542       } else {
2543         if (StrCaseCmp(tok,s) == 0)
2544           return(True);
2545       }
2546     }
2547   return(False);
2548 }
2549
2550 /* this is used to prevent lots of mallocs of size 1 */
2551 static char *null_string = NULL;
2552
2553 /****************************************************************************
2554 set a string value, allocing the space for the string
2555 ****************************************************************************/
2556 BOOL string_init(char **dest,char *src)
2557 {
2558   int l;
2559   if (!src)     
2560     src = "";
2561
2562   l = strlen(src);
2563
2564   if (l == 0)
2565     {
2566       if (!null_string)
2567         null_string = (char *)malloc(1);
2568
2569       *null_string = 0;
2570       *dest = null_string;
2571     }
2572   else
2573     {
2574       *dest = (char *)malloc(l+1);
2575       strcpy(*dest,src);
2576     }
2577   return(True);
2578 }
2579
2580 /****************************************************************************
2581 free a string value
2582 ****************************************************************************/
2583 void string_free(char **s)
2584 {
2585   if (!s || !(*s)) return;
2586   if (*s == null_string)
2587     *s = NULL;
2588   if (*s) free(*s);
2589   *s = NULL;
2590 }
2591
2592 /****************************************************************************
2593 set a string value, allocing the space for the string, and deallocating any 
2594 existing space
2595 ****************************************************************************/
2596 BOOL string_set(char **dest,char *src)
2597 {
2598   string_free(dest);
2599
2600   return(string_init(dest,src));
2601 }
2602
2603 /****************************************************************************
2604 substitute a string for a pattern in another string. Make sure there is 
2605 enough room!
2606
2607 This routine looks for pattern in s and replaces it with 
2608 insert. It may do multiple replacements.
2609
2610 return True if a substitution was done.
2611 ****************************************************************************/
2612 BOOL string_sub(char *s,char *pattern,char *insert)
2613 {
2614   BOOL ret = False;
2615   char *p;
2616   int ls,lp,li;
2617
2618   if (!insert || !pattern || !s) return(False);
2619
2620   ls = strlen(s);
2621   lp = strlen(pattern);
2622   li = strlen(insert);
2623
2624   if (!*pattern) return(False);
2625
2626   while (lp <= ls && (p = strstr(s,pattern)))
2627     {
2628       ret = True;
2629       memmove(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp));
2630       memcpy(p,insert,li);
2631       s = p + li;
2632       ls = strlen(s);
2633     }
2634   return(ret);
2635 }
2636
2637
2638
2639 /*********************************************************
2640 * Recursive routine that is called by mask_match.
2641 * Does the actual matching.
2642 *********************************************************/
2643 BOOL do_match(char *str, char *regexp, int case_sig)
2644 {
2645   char *p;
2646
2647   for( p = regexp; *p && *str; ) {
2648     switch(*p) {
2649     case '?':
2650       str++; p++;
2651       break;
2652
2653     case '*':
2654       /* Look for a character matching 
2655          the one after the '*' */
2656       p++;
2657       if(!*p)
2658         return True; /* Automatic match */
2659       while(*str) {
2660         while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
2661           str++;
2662         if(do_match(str,p,case_sig))
2663           return True;
2664         if(!*str)
2665           return False;
2666         else
2667           str++;
2668       }
2669       return False;
2670
2671     default:
2672       if(case_sig) {
2673         if(*str != *p)
2674           return False;
2675       } else {
2676         if(toupper(*str) != toupper(*p))
2677           return False;
2678       }
2679       str++, p++;
2680       break;
2681     }
2682   }
2683   if(!*p && !*str)
2684     return True;
2685
2686   if (!*p && str[0] == '.' && str[1] == 0)
2687     return(True);
2688   
2689   if (!*str && *p == '?')
2690     {
2691       while (*p == '?') p++;
2692       return(!*p);
2693     }
2694
2695   if(!*str && (*p == '*' && p[1] == '\0'))
2696     return True;
2697   return False;
2698 }
2699
2700
2701 /*********************************************************
2702 * Routine to match a given string with a regexp - uses
2703 * simplified regexp that takes * and ? only. Case can be
2704 * significant or not.
2705 *********************************************************/
2706 BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
2707 {
2708   char *p;
2709   pstring p1, p2;
2710   fstring ebase,eext,sbase,sext;
2711
2712   BOOL matched;
2713
2714   /* Make local copies of str and regexp */
2715   StrnCpy(p1,regexp,sizeof(pstring)-1);
2716   StrnCpy(p2,str,sizeof(pstring)-1);
2717
2718   if (!strchr(p2,'.')) {
2719     strcat(p2,".");
2720   }
2721
2722 /*
2723   if (!strchr(p1,'.')) {
2724     strcat(p1,".");
2725   }
2726 */
2727
2728 #if 0
2729   if (strchr(p1,'.'))
2730     {
2731       string_sub(p1,"*.*","*");
2732       string_sub(p1,".*","*");
2733     }
2734 #endif
2735
2736   /* Remove any *? and ** as they are meaningless */
2737   for(p = p1; *p; p++)
2738     while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
2739       (void)strcpy( &p[1], &p[2]);
2740
2741   if (strequal(p1,"*")) return(True);
2742
2743   DEBUG(5,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
2744
2745   if (trans2) {
2746     strcpy(ebase,p1);
2747     strcpy(sbase,p2);
2748   } else {
2749     if ((p=strrchr(p1,'.'))) {
2750       *p = 0;
2751       strcpy(ebase,p1);
2752       strcpy(eext,p+1);
2753     } else {
2754       strcpy(ebase,p1);
2755       eext[0] = 0;
2756     }
2757
2758   if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
2759     *p = 0;
2760     strcpy(sbase,p2);
2761     strcpy(sext,p+1);
2762   } else {
2763     strcpy(sbase,p2);
2764     strcpy(sext,"");
2765   }
2766   }
2767
2768   matched = do_match(sbase,ebase,case_sig) && 
2769     (trans2 || do_match(sext,eext,case_sig));
2770
2771   DEBUG(5,("mask_match returning %d\n", matched));
2772
2773   return matched;
2774 }
2775
2776
2777
2778 /****************************************************************************
2779 become a daemon, discarding the controlling terminal
2780 ****************************************************************************/
2781 void become_daemon(void)
2782 {
2783 #ifndef NO_FORK_DEBUG
2784   if (fork())
2785     exit(0);
2786
2787   /* detach from the terminal */
2788 #ifdef USE_SETSID
2789   setsid();
2790 #else
2791 #ifdef TIOCNOTTY
2792   {
2793     int i = open("/dev/tty", O_RDWR);
2794     if (i >= 0) 
2795       {
2796         ioctl(i, (int) TIOCNOTTY, (char *)0);      
2797         close(i);
2798       }
2799   }
2800 #endif
2801 #endif
2802 #endif
2803 }
2804
2805 /****************************************************************************
2806 calculate the default netmask for an address
2807 ****************************************************************************/
2808 static void default_netmask(struct in_addr *inm, struct in_addr *iad)
2809 {
2810   unsigned long ad = ntohl(iad->s_addr);
2811   unsigned long nm;
2812   /*
2813   ** Guess a netmask based on the class of the IP address given.
2814   */
2815   if ( (ad & 0x80000000) == 0 ) {
2816     /* class A address */
2817     nm = 0xFF000000;
2818   } else if ( (ad & 0xC0000000) == 0x80000000 ) {
2819     /* class B address */
2820     nm = 0xFFFF0000;
2821   } else if ( (ad & 0xE0000000) == 0xC0000000 ) {
2822     /* class C address */
2823     nm = 0xFFFFFF00;
2824   }  else {
2825     /* class D or E; netmask doesn't make much sense - guess 4 bits */
2826     nm =  0xFFFFFFF0;
2827   }
2828   inm->s_addr = htonl(nm);
2829 }
2830
2831 /****************************************************************************
2832   get the broadcast address for our address 
2833 (troyer@saifr00.ateng.az.honeywell.com)
2834 ****************************************************************************/
2835 void get_broadcast(struct in_addr *if_ipaddr,
2836                     struct in_addr *if_bcast,
2837                     struct in_addr *if_nmask)
2838 {  
2839   BOOL found = False;
2840 #ifndef NO_GET_BROADCAST
2841   int sock = -1;               /* AF_INET raw socket desc */
2842   char buff[1024];
2843   struct ifreq *ifr=NULL;
2844   int i;
2845
2846 #if defined(EVEREST)
2847   int n_interfaces;
2848   struct ifconf ifc;
2849   struct ifreq  *ifreqs;
2850 #elif defined(USE_IFREQ)
2851   struct ifreq ifreq;
2852   struct strioctl strioctl;
2853   struct ifconf *ifc;
2854 #else
2855   struct ifconf ifc;
2856 #endif
2857 #endif
2858
2859   /* get a default netmask and broadcast */
2860   default_netmask(if_nmask, if_ipaddr);
2861
2862 #ifndef NO_GET_BROADCAST  
2863   /* Create a socket to the INET kernel. */
2864 #if USE_SOCKRAW
2865   if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0)
2866 #else
2867     if ((sock = socket(AF_INET, SOCK_DGRAM, 0 )) < 0)
2868 #endif
2869       {
2870         DEBUG(0,( "Unable to open socket to get broadcast address\n"));
2871         return;
2872       }
2873   
2874   /* Get a list of the configured interfaces */
2875 #ifdef EVEREST
2876   /* This is part of SCO Openserver 5: The ioctls are no longer part
2877      if the lower level STREAMS interface glue. They are now real
2878      ioctl calls */
2879
2880   if (ioctl(sock, SIOCGIFANUM, &n_interfaces) < 0) {
2881     DEBUG(0,( "SIOCGIFANUM: %s\n", strerror(errno)));
2882   } else {
2883     DEBUG(0,( "number of interfaces returned is: %d\n", n_interfaces));
2884
2885     ifc.ifc_len = sizeof(struct ifreq) * n_interfaces;
2886     ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len);
2887
2888     if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
2889       DEBUG(0, ( "SIOCGIFCONF: %s\n", strerror(errno)));
2890     else {
2891       ifr = ifc.ifc_req;
2892
2893       for (i = 0; i < n_interfaces; ++i) {
2894         if (if_ipaddr->s_addr ==
2895             ((struct sockaddr_in *) &ifr[i].ifr_addr)->sin_addr.s_addr) {
2896           found = True;
2897           break;
2898         }
2899       }
2900     }
2901   }
2902 #elif defined(USE_IFREQ)
2903   ifc = (struct ifconf *)buff;
2904   ifc->ifc_len = BUFSIZ - sizeof(struct ifconf);
2905   strioctl.ic_cmd = SIOCGIFCONF;
2906   strioctl.ic_dp  = (char *)ifc;
2907   strioctl.ic_len = sizeof(buff);
2908   if (ioctl(sock, I_STR, &strioctl) < 0) {
2909     DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno)));
2910   } else {
2911     ifr = (struct ifreq *)ifc->ifc_req;  
2912
2913     /* Loop through interfaces, looking for given IP address */
2914     for (i = ifc->ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
2915       if (if_ipaddr->s_addr ==
2916           (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
2917         found = True;
2918         break;
2919       }
2920     }
2921   }
2922 #elif defined(__FreeBSD__) || defined(NETBSD)
2923   ifc.ifc_len = sizeof(buff);
2924   ifc.ifc_buf = buff;
2925   if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
2926     DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
2927   } else {
2928     ifr = ifc.ifc_req;
2929     /* Loop through interfaces, looking for given IP address */
2930     i = ifc.ifc_len;
2931     while (i > 0) {
2932       if (if_ipaddr->s_addr ==
2933           (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
2934         found = True;
2935         break;
2936       }
2937       i -= ifr->ifr_addr.sa_len + IFNAMSIZ;
2938       ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
2939     }
2940   }
2941 #else
2942   ifc.ifc_len = sizeof(buff);
2943   ifc.ifc_buf = buff;
2944   if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
2945     DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
2946   } else {
2947     ifr = ifc.ifc_req;
2948   
2949     /* Loop through interfaces, looking for given IP address */
2950     for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
2951 #ifdef BSDI
2952       if (ioctl(sock, SIOCGIFADDR, ifr) < 0) break;
2953 #endif
2954       if (if_ipaddr->s_addr ==
2955           (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
2956         found = True;
2957         break;
2958       }
2959     }
2960   }
2961 #endif
2962   
2963   if (!found) {
2964     DEBUG(0,("No interface found for address %s\n", inet_ntoa(*if_ipaddr)));
2965   } else {
2966     /* Get the netmask address from the kernel */
2967 #ifdef USE_IFREQ
2968     ifreq = *ifr;
2969   
2970     strioctl.ic_cmd = SIOCGIFNETMASK;
2971     strioctl.ic_dp  = (char *)&ifreq;
2972     strioctl.ic_len = sizeof(struct ifreq);
2973     if (ioctl(sock, I_STR, &strioctl) < 0)
2974       DEBUG(0,("Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno)));
2975     else
2976       *if_nmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
2977 #else
2978     if (ioctl(sock, SIOCGIFNETMASK, ifr) < 0)
2979       DEBUG(0,("SIOCGIFNETMASK failed\n"));
2980     else
2981       *if_nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
2982 #endif
2983
2984     DEBUG(2,("Netmask for %s = %s\n", ifr->ifr_name,
2985              inet_ntoa(*if_nmask)));
2986   }
2987
2988   /* Close up shop */
2989   (void) close(sock);
2990   
2991 #endif
2992
2993   /* sanity check on the netmask */
2994   {
2995     unsigned long nm = ntohl(if_nmask->s_addr);
2996     if ((nm >> 24) != 0xFF) {
2997       DEBUG(0,("Impossible netmask %s - using defaults\n",inet_ntoa(*if_nmask)));
2998       default_netmask(if_nmask, if_ipaddr);      
2999     }
3000   }
3001
3002   /* derive the broadcast assuming a 1's broadcast, as this is what
3003      all MS operating systems do, we have to comply even if the unix
3004      box is setup differently */
3005   {
3006     unsigned long ad = ntohl(if_ipaddr->s_addr);
3007     unsigned long nm = ntohl(if_nmask->s_addr);
3008     unsigned long bc = (ad & nm) | (0xffffffff & ~nm);
3009     if_bcast->s_addr = htonl(bc);
3010   }
3011   
3012   DEBUG(2,("Derived broadcast address %s\n", inet_ntoa(*if_bcast)));
3013 }  /* get_broadcast */
3014
3015
3016 /****************************************************************************
3017 put up a yes/no prompt
3018 ****************************************************************************/
3019 BOOL yesno(char *p)
3020 {
3021   pstring ans;
3022   printf("%s",p);
3023
3024   if (!fgets(ans,sizeof(ans)-1,stdin))
3025     return(False);
3026
3027   if (*ans == 'y' || *ans == 'Y')
3028     return(True);
3029
3030   return(False);
3031 }
3032
3033 /****************************************************************************
3034 read a line from a file with possible \ continuation chars. 
3035 Blanks at the start or end of a line are stripped.
3036 The string will be allocated if s2 is NULL
3037 ****************************************************************************/
3038 char *fgets_slash(char *s2,int maxlen,FILE *f)
3039 {
3040   char *s=s2;
3041   int len = 0;
3042   int c;
3043   BOOL start_of_line = True;
3044
3045   if (feof(f))
3046     return(NULL);
3047
3048   if (!s2)
3049     {
3050       maxlen = MIN(maxlen,8);
3051       s = (char *)Realloc(s,maxlen);
3052     }
3053
3054   if (!s || maxlen < 2) return(NULL);
3055
3056   *s = 0;
3057
3058   while (len < maxlen-1)
3059     {
3060       c = getc(f);
3061       switch (c)
3062         {
3063         case '\r':
3064           break;
3065         case '\n':
3066           while (len > 0 && s[len-1] == ' ')
3067             {
3068               s[--len] = 0;
3069             }
3070           if (len > 0 && s[len-1] == '\\')
3071             {
3072               s[--len] = 0;
3073               start_of_line = True;
3074               break;
3075             }
3076           return(s);
3077         case EOF:
3078           if (len <= 0 && !s2) 
3079             free(s);
3080           return(len>0?s:NULL);
3081         case ' ':
3082           if (start_of_line)
3083             break;
3084         default:
3085           start_of_line = False;
3086           s[len++] = c;
3087           s[len] = 0;
3088         }
3089       if (!s2 && len > maxlen-3)
3090         {
3091           maxlen *= 2;
3092           s = (char *)Realloc(s,maxlen);
3093           if (!s) return(NULL);
3094         }
3095     }
3096   return(s);
3097 }
3098
3099
3100
3101 /****************************************************************************
3102 set the length of a file from a filedescriptor.
3103 Returns 0 on success, -1 on failure.
3104 ****************************************************************************/
3105 int set_filelen(int fd, long len)
3106 {
3107 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
3108    extend a file with ftruncate. Provide alternate implementation
3109    for this */
3110
3111 #if FTRUNCATE_CAN_EXTEND
3112   return ftruncate(fd, len);
3113 #else
3114   struct stat st;
3115   char c = 0;
3116   long currpos = lseek(fd, 0L, SEEK_CUR);
3117
3118   if(currpos < 0)
3119     return -1;
3120   /* Do an fstat to see if the file is longer than
3121      the requested size (call ftruncate),
3122      or shorter, in which case seek to len - 1 and write 1
3123      byte of zero */
3124   if(fstat(fd, &st)<0)
3125     return -1;
3126
3127 #ifdef S_ISFIFO
3128   if (S_ISFIFO(st.st_mode)) return 0;
3129 #endif
3130
3131   if(st.st_size == len)
3132     return 0;
3133   if(st.st_size > len)
3134     return ftruncate(fd, len);
3135
3136   if(lseek(fd, len-1, SEEK_SET) != len -1)
3137     return -1;
3138   if(write(fd, &c, 1)!=1)
3139     return -1;
3140   /* Seek to where we were */
3141   lseek(fd, currpos, SEEK_SET);
3142   return 0;
3143 #endif
3144 }
3145
3146
3147 /****************************************************************************
3148 return the byte checksum of some data
3149 ****************************************************************************/
3150 int byte_checksum(char *buf,int len)
3151 {
3152   unsigned char *p = (unsigned char *)buf;
3153   int ret = 0;
3154   while (len--)
3155     ret += *p++;
3156   return(ret);
3157 }
3158
3159
3160
3161 #ifdef HPUX
3162 /****************************************************************************
3163 this is a version of setbuffer() for those machines that only have setvbuf
3164 ****************************************************************************/
3165 void setbuffer(FILE *f,char *buf,int bufsize)
3166 {
3167   setvbuf(f,buf,_IOFBF,bufsize);
3168 }
3169 #endif
3170
3171
3172 /****************************************************************************
3173 parse out a directory name from a path name. Assumes dos style filenames.
3174 ****************************************************************************/
3175 char *dirname_dos(char *path,char *buf)
3176 {
3177   char *p = strrchr(path,'\\');
3178
3179   if (!p)
3180     strcpy(buf,path);
3181   else
3182     {
3183       *p = 0;
3184       strcpy(buf,path);
3185       *p = '\\';
3186     }
3187
3188   return(buf);
3189 }
3190
3191
3192 /****************************************************************************
3193 parse out a filename from a path name. Assumes dos style filenames.
3194 ****************************************************************************/
3195 static char *filename_dos(char *path,char *buf)
3196 {
3197   char *p = strrchr(path,'\\');
3198
3199   if (!p)
3200     strcpy(buf,path);
3201   else
3202     strcpy(buf,p+1);
3203
3204   return(buf);
3205 }
3206
3207
3208
3209 /****************************************************************************
3210 expand a pointer to be a particular size
3211 ****************************************************************************/
3212 void *Realloc(void *p,int size)
3213 {
3214   void *ret=NULL;
3215
3216   if (size == 0) {
3217     if (p) free(p);
3218     DEBUG(5,("Realloc asked for 0 bytes\n"));
3219     return NULL;
3220   }
3221
3222   if (!p)
3223     ret = (void *)malloc(size);
3224   else
3225     ret = (void *)realloc(p,size);
3226
3227   if (!ret)
3228     DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",size));
3229
3230   return(ret);
3231 }
3232
3233 #ifdef NOSTRDUP
3234 /****************************************************************************
3235 duplicate a string
3236 ****************************************************************************/
3237  char *strdup(char *s)
3238 {
3239   char *ret = NULL;
3240   if (!s) return(NULL);
3241   ret = (char *)malloc(strlen(s)+1);
3242   if (!ret) return(NULL);
3243   strcpy(ret,s);
3244   return(ret);
3245 }
3246 #endif
3247
3248
3249 /****************************************************************************
3250   Signal handler for SIGPIPE (write on a disconnected socket) 
3251 ****************************************************************************/
3252 void Abort(void )
3253 {
3254   DEBUG(0,("Probably got SIGPIPE\nExiting\n"));
3255   exit(2);
3256 }
3257
3258
3259 #ifdef REPLACE_STRLEN
3260 /****************************************************************************
3261 a replacement strlen() that returns int for solaris
3262 ****************************************************************************/
3263  int Strlen(char *s)
3264 {
3265   int ret=0;
3266   if (!s) return(0);
3267   while (*s++) ret++;
3268   return(ret);
3269 }
3270 #endif
3271
3272
3273 #ifdef NO_FTRUNCATE
3274  /*******************************************************************
3275 ftruncate for operating systems that don't have it
3276 ********************************************************************/
3277  int ftruncate(int f,long l)
3278 {
3279       struct  flock   fl;
3280
3281       fl.l_whence = 0;
3282       fl.l_len = 0;
3283       fl.l_start = l;
3284       fl.l_type = F_WRLCK;
3285       return fcntl(f, F_FREESP, &fl);
3286 }
3287 #endif
3288
3289
3290
3291 /****************************************************************************
3292 get my own name and IP
3293 ****************************************************************************/
3294 BOOL get_myname(char *myname,struct in_addr *ip)
3295 {
3296   struct hostent *hp;
3297   pstring hostname;
3298
3299   *hostname = 0;
3300
3301   /* get my host name */
3302   if (gethostname(hostname, MAXHOSTNAMELEN) == -1) 
3303     {
3304       DEBUG(0,("gethostname failed\n"));
3305       return False;
3306     } 
3307
3308   /* get host info */
3309   if ((hp = Get_Hostbyname(hostname)) == 0) 
3310     {
3311       DEBUG(0,( "Get_Hostbyname: Unknown host %s.\n",hostname));
3312       return False;
3313     }
3314
3315   if (myname)
3316     {
3317       /* split off any parts after an initial . */
3318       char *p = strchr(hostname,'.');
3319       if (p) *p = 0;
3320
3321       strcpy(myname,hostname);
3322     }
3323
3324   if (ip)
3325     putip((char *)ip,(char *)hp->h_addr);
3326
3327   return(True);
3328 }
3329
3330
3331 /****************************************************************************
3332 true if two IP addresses are equal
3333 ****************************************************************************/
3334 BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
3335 {
3336   unsigned long a1,a2;
3337   a1 = ntohl(ip1.s_addr);
3338   a2 = ntohl(ip2.s_addr);
3339   return(a1 == a2);
3340 }
3341
3342
3343 /****************************************************************************
3344 open a socket of the specified type, port and address for incoming data
3345 ****************************************************************************/
3346 int open_socket_in(int type, int port, int dlevel)
3347 {
3348   struct hostent *hp;
3349   struct sockaddr_in sock;
3350   pstring host_name;
3351   int res;
3352
3353   /* get my host name */
3354   if (gethostname(host_name, MAXHOSTNAMELEN) == -1) 
3355     { DEBUG(0,("gethostname failed\n")); return -1; } 
3356
3357   /* get host info */
3358   if ((hp = Get_Hostbyname(host_name)) == 0) 
3359     {
3360       DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",host_name));
3361       return -1;
3362     }
3363   
3364   bzero((char *)&sock,sizeof(sock));
3365   memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
3366 #if defined(__FreeBSD__) || defined(NETBSD) /* XXX not the right ifdef */
3367   sock.sin_len = sizeof(sock);
3368 #endif
3369   sock.sin_port = htons( port );
3370   sock.sin_family = hp->h_addrtype;
3371   sock.sin_addr.s_addr = INADDR_ANY;
3372   res = socket(hp->h_addrtype, type, 0);
3373   if (res == -1) 
3374     { DEBUG(0,("socket failed\n")); return -1; }
3375
3376   {
3377     int one=1;
3378     setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
3379   }
3380
3381   /* now we've got a socket - we need to bind it */
3382   if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) 
3383     { 
3384       if (port) {
3385         if (port == SMB_PORT || port == NMB_PORT)
3386           DEBUG(dlevel,("bind failed on port %d (%s)\n",
3387                         port,strerror(errno))); 
3388         close(res); 
3389
3390         if (dlevel > 0 && port < 1000)
3391           port = 7999;
3392
3393         if (port >= 1000 && port < 9000)
3394           return(open_socket_in(type,port+1,dlevel));
3395       }
3396
3397       return(-1); 
3398     }
3399   DEBUG(3,("bind succeeded on port %d\n",port));
3400
3401   return res;
3402 }
3403
3404
3405 /****************************************************************************
3406   create an outgoing socket
3407   **************************************************************************/
3408 int open_socket_out(int type, struct in_addr *addr, int port )
3409 {
3410   struct sockaddr_in sock_out;
3411   int res;
3412
3413   /* create a socket to write to */
3414   res = socket(PF_INET, type, 0);
3415   if (res == -1) 
3416     { DEBUG(0,("socket error\n")); return -1; }
3417
3418   if (type != SOCK_STREAM) return(res);
3419   
3420   bzero((char *)&sock_out,sizeof(sock_out));
3421   putip((char *)&sock_out.sin_addr,(char *)addr);
3422   
3423   sock_out.sin_port = htons( port );
3424   sock_out.sin_family = PF_INET;
3425
3426   DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port));
3427   
3428   /* and connect it to the destination */
3429   if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))<0) {
3430     DEBUG(0,("connect error: %s\n",strerror(errno))); 
3431     close(res); 
3432     return(-1);
3433   }
3434
3435   return res;
3436 }
3437
3438
3439 /****************************************************************************
3440 interpret a protocol description string, with a default
3441 ****************************************************************************/
3442 int interpret_protocol(char *str,int def)
3443 {
3444   if (strequal(str,"NT1"))
3445     return(PROTOCOL_NT1);
3446   if (strequal(str,"LANMAN2"))
3447     return(PROTOCOL_LANMAN2);
3448   if (strequal(str,"LANMAN1"))
3449     return(PROTOCOL_LANMAN1);
3450   if (strequal(str,"CORE"))
3451     return(PROTOCOL_CORE);
3452   if (strequal(str,"COREPLUS"))
3453     return(PROTOCOL_COREPLUS);
3454   if (strequal(str,"CORE+"))
3455     return(PROTOCOL_COREPLUS);
3456   
3457   DEBUG(0,("Unrecognised protocol level %s\n",str));
3458   
3459   return(def);
3460 }
3461
3462 /****************************************************************************
3463 interpret a security level
3464 ****************************************************************************/
3465 int interpret_security(char *str,int def)
3466 {
3467   if (strequal(str,"SERVER"))
3468     return(SEC_SERVER);
3469   if (strequal(str,"USER"))
3470     return(SEC_USER);
3471   if (strequal(str,"SHARE"))
3472     return(SEC_SHARE);
3473   
3474   DEBUG(0,("Unrecognised security level %s\n",str));
3475   
3476   return(def);
3477 }
3478
3479
3480 /****************************************************************************
3481 interpret an internet address or name into an IP address in 4 byte form
3482 ****************************************************************************/
3483 unsigned long interpret_addr(char *str)
3484 {
3485   struct hostent *hp;
3486   unsigned long res;
3487
3488   if (strcmp(str,"0.0.0.0") == 0) return(0);
3489   if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
3490
3491   /* if it's in the form of an IP address then get the lib to interpret it */
3492   if (isdigit(str[0])) {
3493     res = inet_addr(str);
3494   } else {
3495     /* otherwise assume it's a network name of some sort and use Get_Hostbyname */
3496     if ((hp = Get_Hostbyname(str)) == 0) {
3497       DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
3498       return 0;
3499     }
3500     putip((char *)&res,(char *)hp->h_addr);
3501   }
3502
3503   if (res == (unsigned long)-1) return(0);
3504
3505   return(res);
3506 }
3507
3508 /*******************************************************************
3509   a convenient addition to interpret_addr()
3510   ******************************************************************/
3511 struct in_addr *interpret_addr2(char *str)
3512 {
3513   static struct in_addr ret;
3514   unsigned long a = interpret_addr(str);
3515   putip((char *)&ret,(char *)&a);
3516   return(&ret);
3517 }
3518
3519 /*******************************************************************
3520   check if an IP is the 0.0.0.0
3521   ******************************************************************/
3522 BOOL zero_ip(struct in_addr ip)
3523 {
3524   unsigned long a;
3525   putip((char *)&a,(char *)&ip);
3526   return(a == 0);
3527 }
3528
3529 /*******************************************************************
3530 sub strings with useful parameters
3531 ********************************************************************/
3532 void standard_sub_basic(char *s)
3533 {
3534   if (!strchr(s,'%')) return;
3535
3536   string_sub(s,"%R",remote_proto);
3537   string_sub(s,"%a",remote_arch);
3538   string_sub(s,"%m",remote_machine);
3539   string_sub(s,"%L",local_machine);
3540
3541   if (!strchr(s,'%')) return;
3542
3543   string_sub(s,"%v",VERSION);
3544   string_sub(s,"%h",myhostname);
3545   string_sub(s,"%U",sesssetup_user);
3546
3547   if (!strchr(s,'%')) return;
3548
3549   string_sub(s,"%I",Client_info.addr);
3550   string_sub(s,"%M",Client_info.name);
3551   string_sub(s,"%T",timestring());
3552
3553   if (!strchr(s,'%')) return;
3554
3555   {
3556     char pidstr[10];
3557     sprintf(pidstr,"%d",(int)getpid());
3558     string_sub(s,"%d",pidstr);
3559   }
3560
3561   if (!strchr(s,'%')) return;
3562
3563   {
3564     struct passwd *pass = Get_Pwnam(sesssetup_user,False);
3565     if (pass) {
3566       string_sub(s,"%G",gidtoname(pass->pw_gid));
3567     }
3568   }
3569 }
3570
3571
3572 /*******************************************************************
3573 are two IPs on the same subnet?
3574 ********************************************************************/
3575 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
3576 {
3577   unsigned long net1,net2,nmask;
3578
3579   nmask = ntohl(mask.s_addr);
3580   net1  = ntohl(ip1.s_addr);
3581   net2  = ntohl(ip2.s_addr);
3582             
3583   return((net1 & nmask) == (net2 & nmask));
3584 }
3585
3586
3587 /*******************************************************************
3588 write a string in unicoode format
3589 ********************************************************************/
3590 int PutUniCode(char *dst,char *src)
3591 {
3592   int ret = 0;
3593   while (*src) {
3594     dst[ret++] = src[0];
3595     dst[ret++] = 0;    
3596     src++;
3597   }
3598   dst[ret++]=0;
3599   dst[ret++]=0;
3600   return(ret);
3601 }
3602
3603 /****************************************************************************
3604 a wrapper for gethostbyname() that tries with all lower and all upper case 
3605 if the initial name fails
3606 ****************************************************************************/
3607 struct hostent *Get_Hostbyname(char *name)
3608 {
3609   char *name2 = strdup(name);
3610   struct hostent *ret;
3611
3612   if (!name2)
3613     {
3614       DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
3615       exit(0);
3616     }
3617
3618   if (!isalnum(*name2))
3619     {
3620       free(name2);
3621       return(NULL);
3622     }
3623
3624   ret = gethostbyname(name2);
3625   if (ret != NULL)
3626     {
3627       free(name2);
3628       return(ret);
3629     }
3630
3631   /* try with all lowercase */
3632   strlower(name2);
3633   ret = gethostbyname(name2);
3634   if (ret != NULL)
3635     {
3636       free(name2);
3637       return(ret);
3638     }
3639
3640   /* try with all uppercase */
3641   strupper(name2);
3642   ret = gethostbyname(name2);
3643   if (ret != NULL)
3644     {
3645       free(name2);
3646       return(ret);
3647     }
3648   
3649   /* nothing works :-( */
3650   free(name2);
3651   return(NULL);
3652 }
3653
3654
3655 /****************************************************************************
3656 check if a process exists. Does this work on all unixes?
3657 ****************************************************************************/
3658 BOOL process_exists(int pid)
3659 {
3660 #ifdef LINUX
3661   fstring s;
3662   sprintf(s,"/proc/%d",pid);
3663   return(directory_exist(s,NULL));
3664 #else
3665   {
3666     static BOOL tested=False;
3667     static BOOL ok=False;
3668     fstring s;
3669     if (!tested) {
3670       tested = True;
3671       sprintf(s,"/proc/%05d",getpid());
3672       ok = file_exist(s,NULL);
3673     }
3674     if (ok) {
3675       sprintf(s,"/proc/%05d",pid);
3676       return(file_exist(s,NULL));
3677     }
3678   }
3679
3680   /* a best guess for non root access */
3681   if (geteuid() != 0) return(True);
3682
3683   /* otherwise use kill */
3684   return(pid == getpid() || kill(pid,0) == 0);
3685 #endif
3686 }
3687
3688
3689 /*******************************************************************
3690 turn a uid into a user name
3691 ********************************************************************/
3692 char *uidtoname(int uid)
3693 {
3694   static char name[40];
3695   struct passwd *pass = getpwuid(uid);
3696   if (pass) return(pass->pw_name);
3697   sprintf(name,"%d",uid);
3698   return(name);
3699 }
3700
3701 /*******************************************************************
3702 turn a gid into a group name
3703 ********************************************************************/
3704 char *gidtoname(int gid)
3705 {
3706   static char name[40];
3707   struct group *grp = getgrgid(gid);
3708   if (grp) return(grp->gr_name);
3709   sprintf(name,"%d",gid);
3710   return(name);
3711 }
3712
3713 /*******************************************************************
3714 block sigs
3715 ********************************************************************/
3716 void BlockSignals(BOOL block)
3717 {
3718 #ifdef USE_SIGBLOCK
3719   int block_mask = (sigmask(SIGTERM)|sigmask(SIGQUIT)|sigmask(SIGSEGV)
3720                     |sigmask(SIGCHLD)|sigmask(SIGQUIT)|sigmask(SIGBUS)|
3721                     sigmask(SIGINT));
3722   if (block) 
3723     sigblock(block_mask);
3724   else
3725     sigunblock(block_mask);
3726 #endif
3727 }
3728
3729 #if AJT
3730 /*******************************************************************
3731 my own panic function - not suitable for general use
3732 ********************************************************************/
3733 void ajt_panic(void)
3734 {
3735   system("/usr/bin/X11/xedit -display :0 /tmp/ERROR_FAULT &");
3736 }
3737 #endif
3738
3739 #ifdef USE_DIRECT
3740 #define DIRECT direct
3741 #else
3742 #define DIRECT dirent
3743 #endif
3744
3745 /*******************************************************************
3746 a readdir wrapper which just returns the file name
3747 also return the inode number if requested
3748 ********************************************************************/
3749 char *readdirname(void *p)
3750 {
3751   struct DIRECT *ptr;
3752   char *dname;
3753
3754   if (!p) return(NULL);
3755   
3756   ptr = (struct DIRECT *)readdir(p);
3757   if (!ptr) return(NULL);
3758
3759   dname = ptr->d_name;
3760
3761 #ifdef KANJI
3762   {
3763     static pstring buf;
3764     strcpy(buf, dname);
3765     unix_to_dos(buf, True);
3766     dname = buf;
3767   }
3768 #endif
3769
3770 #ifdef NEXT2
3771   if (telldir(p) < 0) return(NULL);
3772 #endif
3773
3774 #ifdef SUNOS5
3775   /* this handles a broken compiler setup, causing a mixture
3776    of BSD and SYSV headers and libraries */
3777   {
3778     static BOOL broken_readdir = False;
3779     if (!broken_readdir && !(*(dname)) && strequal("..",dname-2))
3780       {
3781         DEBUG(0,("Your readdir() is broken. You have somehow mixed SYSV and BSD headers and libraries\n"));
3782         broken_readdir = True;
3783       }
3784     if (broken_readdir)
3785       return(dname-2);
3786   }
3787 #endif
3788
3789   return(dname);
3790 }
3791
3792
3793
3794 #if (defined(SecureWare) && defined(SCO))
3795 /* This is needed due to needing the nap() function but we don't want
3796    to include the Xenix libraries since that will break other things...
3797    BTW: system call # 0x0c28 is the same as calling nap() */
3798 long nap(long milliseconds) {
3799   return syscall(0x0c28, milliseconds);
3800 }
3801 #endif
3802
3803 #ifdef NO_INITGROUPS
3804 #include <sys/types.h>
3805 #include <limits.h>
3806 #include <grp.h>
3807
3808 #ifndef NULL
3809 #define NULL (void *)0
3810 #endif
3811
3812 /****************************************************************************
3813  some systems don't have an initgroups call 
3814 ****************************************************************************/
3815  int initgroups(char *name,gid_t id)
3816 {
3817 #ifdef NO_SETGROUPS
3818   /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
3819   return(0);
3820 #else
3821   gid_t  grouplst[NGROUPS_MAX];
3822   int    i,j;
3823   struct group *g;
3824   char   *gr;
3825
3826   grouplst[0] = id;
3827   i = 1;
3828   while (i < NGROUPS_MAX && 
3829          ((g = (struct group *)getgrent()) != (struct group *)NULL)) 
3830     {
3831       if (g->gr_gid == id)
3832         continue;
3833       j = 0;
3834       gr = g->gr_mem[0];
3835       while (gr && (*gr != (char)NULL)) {
3836         if (strcmp(name,gr) == 0) {
3837           grouplst[i] = g->gr_gid;
3838           i++;
3839           gr = (char *)NULL;
3840           break;
3841         }
3842         gr = g->gr_mem[++j];
3843       }
3844     }
3845   endgrent();
3846   return(setgroups(i,grouplst));
3847 #endif
3848 }
3849 #endif
3850
3851
3852 #if WRAP_MALLOC
3853
3854 /* undo the wrapping temporarily */
3855 #undef malloc
3856 #undef realloc
3857 #undef free
3858
3859 /****************************************************************************
3860 wrapper for malloc() to catch memory errors
3861 ****************************************************************************/
3862 void *malloc_wrapped(int size,char *file,int line)
3863 {
3864 #ifdef xx_old_malloc
3865   void *res = xx_old_malloc(size);
3866 #else
3867   void *res = malloc(size);
3868 #endif
3869   DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
3870         file,line,
3871         size,(unsigned int)res));
3872   return(res);
3873 }
3874
3875 /****************************************************************************
3876 wrapper for realloc() to catch memory errors
3877 ****************************************************************************/
3878 void *realloc_wrapped(void *ptr,int size,char *file,int line)
3879 {
3880 #ifdef xx_old_realloc
3881   void *res = xx_old_realloc(ptr,size);
3882 #else
3883   void *res = realloc(ptr,size);
3884 #endif
3885   DEBUG(3,("Realloc\n"));
3886   DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
3887         file,line,
3888         (unsigned int)ptr));
3889   DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
3890         file,line,
3891         size,(unsigned int)res));
3892   return(res);
3893 }
3894
3895 /****************************************************************************
3896 wrapper for free() to catch memory errors
3897 ****************************************************************************/
3898 void free_wrapped(void *ptr,char *file,int line)
3899 {
3900 #ifdef xx_old_free
3901   xx_old_free(ptr);
3902 #else
3903   free(ptr);
3904 #endif
3905   DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
3906         file,line,(unsigned int)ptr));
3907   return;
3908 }
3909
3910 /* and re-do the define for spots lower in this file */
3911 #define malloc(size) malloc_wrapped(size,__FILE__,__LINE__)
3912 #define realloc(ptr,size) realloc_wrapped(ptr,size,__FILE__,__LINE__)
3913 #define free(ptr) free_wrapped(ptr,__FILE__,__LINE__)
3914
3915 #endif
3916
3917 #ifdef REPLACE_STRSTR
3918 /****************************************************************************
3919 Mips version of strstr doesn't seem to work correctly.
3920 There is a #define in includes.h to redirect calls to this function.
3921 ****************************************************************************/
3922 char *Strstr(char *s, char *p)
3923 {
3924         int len = strlen(p);
3925
3926         while ( *s != '\0' ) {
3927                 if ( strncmp(s, p, len) == 0 )
3928                 return s;
3929                 s++;
3930         }
3931
3932         return NULL;
3933 }
3934 #endif /* REPLACE_STRSTR */
3935
3936
3937 #ifdef REPLACE_MKTIME
3938 /*******************************************************************
3939 a mktime() replacement for those who don't have it - contributed by 
3940 C.A. Lademann <cal@zls.com>
3941 ********************************************************************/
3942 #define  MINUTE  60
3943 #define  HOUR    60*MINUTE
3944 #define  DAY             24*HOUR
3945 #define  YEAR    365*DAY
3946 time_t Mktime(struct tm      *t)
3947 {
3948   struct tm       *u;
3949   time_t  epoch = 0;
3950   int             mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3951   y, m, i;
3952
3953   if(t->tm_year < 70)
3954     return((time_t)-1);
3955
3956   epoch = (t->tm_year - 70) * YEAR + 
3957     (t->tm_year / 4 - 70 / 4 - t->tm_year / 100) * DAY;
3958
3959   y = t->tm_year;
3960   m = 0;
3961
3962   for(i = 0; i < t->tm_mon; i++) {
3963     epoch += mon [m] * DAY;
3964     if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
3965       epoch += DAY;
3966     
3967     if(++m > 11) {
3968       m = 0;
3969       y++;
3970     }
3971   }
3972
3973   epoch += (t->tm_mday - 1) * DAY;
3974   epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
3975   
3976   if((u = localtime(&epoch)) != NULL) {
3977     t->tm_sec = u->tm_sec;
3978     t->tm_min = u->tm_min;
3979     t->tm_hour = u->tm_hour;
3980     t->tm_mday = u->tm_mday;
3981     t->tm_mon = u->tm_mon;
3982     t->tm_year = u->tm_year;
3983     t->tm_wday = u->tm_wday;
3984     t->tm_yday = u->tm_yday;
3985     t->tm_isdst = u->tm_isdst;
3986 #ifndef NO_TM_NAME
3987     memcpy(t->tm_name, u->tm_name, LTZNMAX);
3988 #endif
3989   }
3990
3991   return(epoch);
3992 }
3993 #endif /* REPLACE_MKTIME */
3994
3995
3996
3997 #ifdef REPLACE_RENAME
3998 /* Rename a file. (from libiberty in GNU binutils)  */
3999  int rename (zfrom, zto)
4000      const char *zfrom;
4001      const char *zto;
4002 {
4003   if (link (zfrom, zto) < 0)
4004     {
4005       if (errno != EEXIST)
4006         return -1;
4007       if (unlink (zto) < 0
4008           || link (zfrom, zto) < 0)
4009         return -1;
4010     }
4011   return unlink (zfrom);
4012 }
4013 #endif
4014
4015
4016 #ifdef REPLACE_INNETGR
4017 /*
4018  * Search for a match in a netgroup. This replaces it on broken systems.
4019  */
4020 int InNetGr(char *group,char *host,char *user,char *dom)
4021 {
4022   char *hst, *usr, *dm;
4023   
4024   setnetgrent(group);
4025   while (getnetgrent(&hst, &usr, &dm))
4026     if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
4027         ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
4028         ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
4029       endnetgrent();
4030       return (1);
4031     }
4032   endnetgrent();
4033   return (0);
4034 }
4035 #endif
4036
4037
4038 #if WRAP_MEMCPY
4039 #undef memcpy
4040 /*******************************************************************
4041 a wrapper around memcpy for diagnostic purposes
4042 ********************************************************************/
4043 void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line)
4044 {
4045   if (l>64 && (((int)d)%4) != (((int)s)%4))
4046     DEBUG(4,("Misaligned memcpy(0x%X,0x%X,%d) at %s(%d)\n",d,s,l,fname,line));
4047 #ifdef xx_old_memcpy  
4048   return(xx_old_memcpy(d,s,l));
4049 #else
4050   return(memcpy(d,s,l));
4051 #endif
4052 }
4053 #define memcpy(d,s,l) memcpy_wrapped(d,s,l,__FILE__,__LINE__)
4054 #endif
4055
4056
4057