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