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