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