0d7c32be89287a8995ab1357a14285be3f455dbe
[kai/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 j;
999   int bcc=0;
1000   if (DEBUGLEVEL < 5)
1001     return;
1002
1003   DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
1004           smb_len(buf),
1005           (int)CVAL(buf,smb_com),
1006           (int)CVAL(buf,smb_rcls),
1007           (int)CVAL(buf,smb_reh),
1008           (int)SVAL(buf,smb_err),
1009           (int)CVAL(buf,smb_flg),
1010           (int)SVAL(buf,smb_flg2)));
1011   DEBUG(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n",
1012           (int)SVAL(buf,smb_tid),
1013           (int)SVAL(buf,smb_pid),
1014           (int)SVAL(buf,smb_uid),
1015           (int)SVAL(buf,smb_mid),
1016           (int)CVAL(buf,smb_wct)));
1017   for (i=0;i<(int)CVAL(buf,smb_wct);i++)
1018     DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i,
1019           SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
1020   bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
1021   DEBUG(5,("smb_bcc=%d\n",bcc));
1022   if (DEBUGLEVEL < 10)
1023     return;
1024   for (i = 0; i < MIN(bcc, 256); i += 16)
1025   {
1026     for (j = 0; j < 16 && i+j < MIN(bcc,256); j++)
1027     {
1028
1029       DEBUG(10,("%2X ",CVAL(smb_buf(buf),i+j)));
1030       if (j == 7) DEBUG(10, ("  "));
1031
1032     }
1033     DEBUG(10,("  "));  
1034
1035     for (j = 0; j < 16 && i+j < MIN(bcc,256); j++)
1036     {
1037       unsigned char c = CVAL(smb_buf(buf),i+j);
1038       if (c < 32 || c > 128) c = '.';
1039       DEBUG(10,("%c",c));
1040
1041       if (j == 7) DEBUG(10, ("  "));
1042     }
1043
1044     DEBUG(10,("\n"));  
1045   }
1046 }
1047
1048 /*******************************************************************
1049   return the length of an smb packet
1050 ********************************************************************/
1051 int smb_len(char *buf)
1052 {
1053   return( PVAL(buf,3) | (PVAL(buf,2)<<8) | ((PVAL(buf,1)&1)<<16) );
1054 }
1055
1056 /*******************************************************************
1057   set the length of an smb packet
1058 ********************************************************************/
1059 void _smb_setlen(char *buf,int len)
1060 {
1061   buf[0] = 0;
1062   buf[1] = (len&0x10000)>>16;
1063   buf[2] = (len&0xFF00)>>8;
1064   buf[3] = len&0xFF;
1065 }
1066
1067 /*******************************************************************
1068   set the length and marker of an smb packet
1069 ********************************************************************/
1070 void smb_setlen(char *buf,int len)
1071 {
1072   _smb_setlen(buf,len);
1073
1074   CVAL(buf,4) = 0xFF;
1075   CVAL(buf,5) = 'S';
1076   CVAL(buf,6) = 'M';
1077   CVAL(buf,7) = 'B';
1078 }
1079
1080 /*******************************************************************
1081   setup the word count and byte count for a smb message
1082 ********************************************************************/
1083 int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
1084 {
1085   if (zero)
1086     bzero(buf + smb_size,num_words*2 + num_bytes);
1087   CVAL(buf,smb_wct) = num_words;
1088   SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);  
1089   smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
1090   return (smb_size + num_words*2 + num_bytes);
1091 }
1092
1093 /*******************************************************************
1094 return the number of smb words
1095 ********************************************************************/
1096 int smb_numwords(char *buf)
1097 {
1098   return (CVAL(buf,smb_wct));
1099 }
1100
1101 /*******************************************************************
1102 return the size of the smb_buf region of a message
1103 ********************************************************************/
1104 int smb_buflen(char *buf)
1105 {
1106   return(SVAL(buf,smb_vwv0 + smb_numwords(buf)*2));
1107 }
1108
1109 /*******************************************************************
1110   return a pointer to the smb_buf data area
1111 ********************************************************************/
1112 int smb_buf_ofs(char *buf)
1113 {
1114   return (smb_size + CVAL(buf,smb_wct)*2);
1115 }
1116
1117 /*******************************************************************
1118   return a pointer to the smb_buf data area
1119 ********************************************************************/
1120 char *smb_buf(char *buf)
1121 {
1122   return (buf + smb_buf_ofs(buf));
1123 }
1124
1125 /*******************************************************************
1126 return the SMB offset into an SMB buffer
1127 ********************************************************************/
1128 int smb_offset(char *p,char *buf)
1129 {
1130   return(PTR_DIFF(p,buf+4) + chain_size);
1131 }
1132
1133
1134 /*******************************************************************
1135 skip past some strings in a buffer
1136 ********************************************************************/
1137 char *skip_string(char *buf,int n)
1138 {
1139   while (n--)
1140     buf += strlen(buf) + 1;
1141   return(buf);
1142 }
1143
1144 /*******************************************************************
1145 trim the specified elements off the front and back of a string
1146 ********************************************************************/
1147 BOOL trim_string(char *s,char *front,char *back)
1148 {
1149   BOOL ret = False;
1150   while (front && *front && strncmp(s,front,strlen(front)) == 0)
1151     {
1152       char *p = s;
1153       ret = True;
1154       while (1)
1155         {
1156           if (!(*p = p[strlen(front)]))
1157             break;
1158           p++;
1159         }
1160     }
1161   while (back && *back && strlen(s) >= strlen(back) && 
1162          (strncmp(s+strlen(s)-strlen(back),back,strlen(back))==0))  
1163     {
1164       ret = True;
1165       s[strlen(s)-strlen(back)] = 0;
1166     }
1167   return(ret);
1168 }
1169
1170
1171 /*******************************************************************
1172 reduce a file name, removing .. elements.
1173 ********************************************************************/
1174 void dos_clean_name(char *s)
1175 {
1176   char *p=NULL;
1177
1178   DEBUG(3,("dos_clean_name [%s]\n",s));
1179
1180   /* remove any double slashes */
1181   string_sub(s, "\\\\", "\\");
1182
1183   while ((p = strstr(s,"\\..\\")) != NULL)
1184     {
1185       pstring s1;
1186
1187       *p = 0;
1188       strcpy(s1,p+3);
1189
1190       if ((p=strrchr(s,'\\')) != NULL)
1191         *p = 0;
1192       else
1193         *s = 0;
1194       strcat(s,s1);
1195     }  
1196
1197   trim_string(s,NULL,"\\..");
1198
1199   string_sub(s, "\\.\\", "\\");
1200 }
1201
1202 /*******************************************************************
1203 reduce a file name, removing .. elements. 
1204 ********************************************************************/
1205 void unix_clean_name(char *s)
1206 {
1207   char *p=NULL;
1208
1209   DEBUG(3,("unix_clean_name [%s]\n",s));
1210
1211   /* remove any double slashes */
1212   string_sub(s, "//","/");
1213
1214   /* Remove leading ./ characters */
1215   if(strncmp(s, "./", 2) == 0) {
1216     trim_string(s, "./", NULL);
1217     if(*s == 0)
1218       strcpy(s,"./");
1219   }
1220
1221   while ((p = strstr(s,"/../")) != NULL)
1222     {
1223       pstring s1;
1224
1225       *p = 0;
1226       strcpy(s1,p+3);
1227
1228       if ((p=strrchr(s,'/')) != NULL)
1229         *p = 0;
1230       else
1231         *s = 0;
1232       strcat(s,s1);
1233     }  
1234
1235   trim_string(s,NULL,"/..");
1236 }
1237
1238
1239 /*******************************************************************
1240 a wrapper for the normal chdir() function
1241 ********************************************************************/
1242 int ChDir(char *path)
1243 {
1244   int res;
1245   static pstring LastDir="";
1246
1247   if (strcsequal(path,".")) return(0);
1248
1249   if (*path == '/' && strcsequal(LastDir,path)) return(0);
1250   DEBUG(3,("chdir to %s\n",path));
1251   res = sys_chdir(path);
1252   if (!res)
1253     strcpy(LastDir,path);
1254   return(res);
1255 }
1256
1257
1258 /*******************************************************************
1259   return the absolute current directory path. A dumb version.
1260 ********************************************************************/
1261 static char *Dumb_GetWd(char *s)
1262 {
1263 #ifdef USE_GETCWD
1264     return ((char *)getcwd(s,sizeof(pstring)));
1265 #else
1266     return ((char *)getwd(s));
1267 #endif
1268 }
1269
1270
1271 /* number of list structures for a caching GetWd function. */
1272 #define MAX_GETWDCACHE (50)
1273
1274 struct
1275 {
1276   ino_t inode;
1277   dev_t dev;
1278   char *text;
1279   BOOL valid;
1280 } ino_list[MAX_GETWDCACHE];
1281
1282 BOOL use_getwd_cache=True;
1283
1284 /*******************************************************************
1285   return the absolute current directory path
1286 ********************************************************************/
1287 char *GetWd(char *str)
1288 {
1289   pstring s;
1290   static BOOL getwd_cache_init = False;
1291   struct stat st, st2;
1292   int i;
1293
1294   *s = 0;
1295
1296   if (!use_getwd_cache)
1297     return(Dumb_GetWd(str));
1298
1299   /* init the cache */
1300   if (!getwd_cache_init)
1301     {
1302       getwd_cache_init = True;
1303       for (i=0;i<MAX_GETWDCACHE;i++)
1304         {
1305           string_init(&ino_list[i].text,"");
1306           ino_list[i].valid = False;
1307         }
1308     }
1309
1310   /*  Get the inode of the current directory, if this doesn't work we're
1311       in trouble :-) */
1312
1313   if (stat(".",&st) == -1) 
1314     {
1315       DEBUG(0,("Very strange, couldn't stat \".\"\n"));
1316       return(Dumb_GetWd(str));
1317     }
1318
1319
1320   for (i=0; i<MAX_GETWDCACHE; i++)
1321     if (ino_list[i].valid)
1322       {
1323
1324         /*  If we have found an entry with a matching inode and dev number
1325             then find the inode number for the directory in the cached string.
1326             If this agrees with that returned by the stat for the current
1327             directory then all is o.k. (but make sure it is a directory all
1328             the same...) */
1329       
1330         if (st.st_ino == ino_list[i].inode &&
1331             st.st_dev == ino_list[i].dev)
1332           {
1333             if (stat(ino_list[i].text,&st2) == 0)
1334               {
1335                 if (st.st_ino == st2.st_ino &&
1336                     st.st_dev == st2.st_dev &&
1337                     (st2.st_mode & S_IFMT) == S_IFDIR)
1338                   {
1339                     strcpy (str, ino_list[i].text);
1340
1341                     /* promote it for future use */
1342                     array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
1343                     return (str);
1344                   }
1345                 else
1346                   {
1347                     /*  If the inode is different then something's changed, 
1348                         scrub the entry and start from scratch. */
1349                     ino_list[i].valid = False;
1350                   }
1351               }
1352           }
1353       }
1354
1355
1356   /*  We don't have the information to hand so rely on traditional methods.
1357       The very slow getcwd, which spawns a process on some systems, or the
1358       not quite so bad getwd. */
1359
1360   if (!Dumb_GetWd(s))
1361     {
1362       DEBUG(0,("Getwd failed, errno %d\n",errno));
1363       return (NULL);
1364     }
1365
1366   strcpy(str,s);
1367
1368   DEBUG(5,("GetWd %s, inode %d, dev %x\n",s,(int)st.st_ino,(int)st.st_dev));
1369
1370   /* add it to the cache */
1371   i = MAX_GETWDCACHE - 1;
1372   string_set(&ino_list[i].text,s);
1373   ino_list[i].dev = st.st_dev;
1374   ino_list[i].inode = st.st_ino;
1375   ino_list[i].valid = True;
1376
1377   /* put it at the top of the list */
1378   array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
1379
1380   return (str);
1381 }
1382
1383
1384
1385 /*******************************************************************
1386 reduce a file name, removing .. elements and checking that 
1387 it is below dir in the heirachy. This uses GetWd() and so must be run
1388 on the system that has the referenced file system.
1389
1390 widelinks are allowed if widelinks is true
1391 ********************************************************************/
1392 BOOL reduce_name(char *s,char *dir,BOOL widelinks)
1393 {
1394 #ifndef REDUCE_PATHS
1395   return True;
1396 #else
1397   pstring dir2;
1398   pstring wd;
1399   pstring basename;
1400   pstring newname;
1401   char *p=NULL;
1402   BOOL relative = (*s != '/');
1403
1404   *dir2 = *wd = *basename = *newname = 0;
1405
1406   if (widelinks)
1407     {
1408       unix_clean_name(s);
1409       /* can't have a leading .. */
1410       if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
1411         {
1412           DEBUG(3,("Illegal file name? (%s)\n",s));
1413           return(False);
1414         }
1415
1416       if (strlen(s) == 0)
1417         strcpy(s,"./");
1418
1419       return(True);
1420     }
1421   
1422   DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
1423
1424   /* remove any double slashes */
1425   string_sub(s,"//","/");
1426
1427   strcpy(basename,s);
1428   p = strrchr(basename,'/');
1429
1430   if (!p)
1431     return(True);
1432
1433   if (!GetWd(wd))
1434     {
1435       DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
1436       return(False);
1437     }
1438
1439   if (ChDir(dir) != 0)
1440     {
1441       DEBUG(0,("couldn't chdir to %s\n",dir));
1442       return(False);
1443     }
1444
1445   if (!GetWd(dir2))
1446     {
1447       DEBUG(0,("couldn't getwd for %s\n",dir));
1448       ChDir(wd);
1449       return(False);
1450     }
1451
1452
1453     if (p && (p != basename))
1454       {
1455         *p = 0;
1456         if (strcmp(p+1,".")==0)
1457           p[1]=0;
1458         if (strcmp(p+1,"..")==0)
1459           *p = '/';
1460       }
1461
1462   if (ChDir(basename) != 0)
1463     {
1464       ChDir(wd);
1465       DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,basename));
1466       return(False);
1467     }
1468
1469   if (!GetWd(newname))
1470     {
1471       ChDir(wd);
1472       DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
1473       return(False);
1474     }
1475
1476   if (p && (p != basename))
1477     {
1478       strcat(newname,"/");
1479       strcat(newname,p+1);
1480     }
1481
1482   {
1483     int l = strlen(dir2);    
1484     if (dir2[l-1] == '/')
1485       l--;
1486
1487     if (strncmp(newname,dir2,l) != 0)
1488       {
1489         ChDir(wd);
1490         DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,l));
1491         return(False);
1492       }
1493
1494     if (relative)
1495       {
1496         if (newname[l] == '/')
1497           strcpy(s,newname + l + 1);
1498         else
1499           strcpy(s,newname+l);
1500       }
1501     else
1502       strcpy(s,newname);
1503   }
1504
1505   ChDir(wd);
1506
1507   if (strlen(s) == 0)
1508     strcpy(s,"./");
1509
1510   DEBUG(3,("reduced to %s\n",s));
1511   return(True);
1512 #endif
1513 }
1514
1515 /****************************************************************************
1516 expand some *s 
1517 ****************************************************************************/
1518 static void expand_one(char *Mask,int len)
1519 {
1520   char *p1;
1521   while ((p1 = strchr(Mask,'*')) != NULL)
1522     {
1523       int lfill = (len+1) - strlen(Mask);
1524       int l1= (p1 - Mask);
1525       pstring tmp;
1526       strcpy(tmp,Mask);  
1527       memset(tmp+l1,'?',lfill);
1528       strcpy(tmp + l1 + lfill,Mask + l1 + 1);   
1529       strcpy(Mask,tmp);      
1530     }
1531 }
1532
1533 /****************************************************************************
1534 expand a wildcard expression, replacing *s with ?s
1535 ****************************************************************************/
1536 void expand_mask(char *Mask,BOOL doext)
1537 {
1538   pstring mbeg,mext;
1539   pstring dirpart;
1540   pstring filepart;
1541   BOOL hasdot = False;
1542   char *p1;
1543   BOOL absolute = (*Mask == '\\');
1544
1545   *mbeg = *mext = *dirpart = *filepart = 0;
1546
1547   /* parse the directory and filename */
1548   if (strchr(Mask,'\\'))
1549     dirname_dos(Mask,dirpart);
1550
1551   filename_dos(Mask,filepart);
1552
1553   strcpy(mbeg,filepart);
1554   if ((p1 = strchr(mbeg,'.')) != NULL)
1555     {
1556       hasdot = True;
1557       *p1 = 0;
1558       p1++;
1559       strcpy(mext,p1);
1560     }
1561   else
1562     {
1563       strcpy(mext,"");
1564       if (strlen(mbeg) > 8)
1565         {
1566           strcpy(mext,mbeg + 8);
1567           mbeg[8] = 0;
1568         }
1569     }
1570
1571   if (*mbeg == 0)
1572     strcpy(mbeg,"????????");
1573   if ((*mext == 0) && doext && !hasdot)
1574     strcpy(mext,"???");
1575
1576   if (strequal(mbeg,"*") && *mext==0) 
1577     strcpy(mext,"*");
1578
1579   /* expand *'s */
1580   expand_one(mbeg,8);
1581   if (*mext)
1582     expand_one(mext,3);
1583
1584   strcpy(Mask,dirpart);
1585   if (*dirpart || absolute) strcat(Mask,"\\");
1586   strcat(Mask,mbeg);
1587   strcat(Mask,".");
1588   strcat(Mask,mext);
1589
1590   DEBUG(6,("Mask expanded to [%s]\n",Mask));
1591 }  
1592
1593
1594 /****************************************************************************
1595 does a string have any uppercase chars in it?
1596 ****************************************************************************/
1597 BOOL strhasupper(char *s)
1598 {
1599   while (*s) 
1600     {
1601 #ifdef KANJI
1602         if (is_shift_jis (*s)) {
1603             s += 2;
1604         } else if (is_kana (*s)) {
1605             s++;
1606         } else {
1607             if (isupper(*s)) return(True);
1608             s++;
1609         }
1610 #else 
1611       if (isupper(*s)) return(True);
1612       s++;
1613 #endif /* KANJI */
1614     }
1615   return(False);
1616 }
1617
1618 /****************************************************************************
1619 does a string have any lowercase chars in it?
1620 ****************************************************************************/
1621 BOOL strhaslower(char *s)
1622 {
1623   while (*s) 
1624     {
1625 #ifdef KANJI
1626         if (is_shift_jis (*s)) {
1627             s += 2;
1628         } else if (is_kana (*s)) {
1629             s++;
1630         } else {
1631             if (islower(*s)) return(True);
1632             s++;
1633         }
1634 #else 
1635       if (islower(*s)) return(True);
1636       s++;
1637 #endif /* KANJI */
1638     }
1639   return(False);
1640 }
1641
1642 /****************************************************************************
1643 find the number of chars in a string
1644 ****************************************************************************/
1645 int count_chars(char *s,char c)
1646 {
1647   int count=0;
1648   while (*s) 
1649     {
1650       if (*s == c)
1651         count++;
1652       s++;
1653     }
1654   return(count);
1655 }
1656
1657
1658 /****************************************************************************
1659   make a dir struct
1660 ****************************************************************************/
1661 void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode,time_t date)
1662 {  
1663   char *p;
1664   pstring mask2;
1665
1666   strcpy(mask2,mask);
1667
1668   if ((mode & aDIR) != 0)
1669     size = 0;
1670
1671   memset(buf+1,' ',11);
1672   if ((p = strchr(mask2,'.')) != NULL)
1673     {
1674       *p = 0;
1675       memcpy(buf+1,mask2,MIN(strlen(mask2),8));
1676       memcpy(buf+9,p+1,MIN(strlen(p+1),3));
1677       *p = '.';
1678     }
1679   else
1680     memcpy(buf+1,mask2,MIN(strlen(mask2),11));
1681
1682   bzero(buf+21,DIR_STRUCT_SIZE-21);
1683   CVAL(buf,21) = mode;
1684   put_dos_date(buf,22,date);
1685   SSVAL(buf,26,size & 0xFFFF);
1686   SSVAL(buf,28,size >> 16);
1687   StrnCpy(buf+30,fname,12);
1688   if (!case_sensitive)
1689     strupper(buf+30);
1690   DEBUG(8,("put name [%s] into dir struct\n",buf+30));
1691 }
1692
1693
1694 /*******************************************************************
1695 close the low 3 fd's and open dev/null in their place
1696 ********************************************************************/
1697 void close_low_fds(void)
1698 {
1699   int fd;
1700   int i;
1701   close(0); close(1); close(2);
1702   /* try and use up these file descriptors, so silly
1703      library routines writing to stdout etc won't cause havoc */
1704   for (i=0;i<3;i++) {
1705     fd = open("/dev/null",O_RDWR,0);
1706     if (fd < 0) fd = open("/dev/null",O_WRONLY,0);
1707     if (fd < 0) {
1708       DEBUG(0,("Can't open /dev/null\n"));
1709       return;
1710     }
1711     if (fd != i) {
1712       DEBUG(0,("Didn't get file descriptor %d\n",i));
1713       return;
1714     }
1715   }
1716 }
1717
1718 /****************************************************************************
1719 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
1720 else
1721 if SYSV use O_NDELAY
1722 if BSD use FNDELAY
1723 ****************************************************************************/
1724 int set_blocking(int fd, int set)
1725 {
1726   int val;
1727 #ifdef O_NONBLOCK
1728 #define FLAG_TO_SET O_NONBLOCK
1729 #else
1730 #ifdef SYSV
1731 #define FLAG_TO_SET O_NDELAY
1732 #else /* BSD */
1733 #define FLAG_TO_SET FNDELAY
1734 #endif
1735 #endif
1736
1737   if((val = fcntl(fd, F_GETFL, 0)) == -1)
1738         return -1;
1739   if(set) /* Turn blocking on - ie. clear nonblock flag */
1740         val &= ~FLAG_TO_SET;
1741   else
1742     val |= FLAG_TO_SET;
1743   return fcntl( fd, F_SETFL, val);
1744 #undef FLAG_TO_SET
1745 }
1746
1747
1748 /****************************************************************************
1749 write to a socket
1750 ****************************************************************************/
1751 int write_socket(int fd,char *buf,int len)
1752 {
1753   int ret=0;
1754
1755   if (passive)
1756     return(len);
1757   DEBUG(6,("write_socket(%d,%d)\n",fd,len));
1758   ret = write_data(fd,buf,len);
1759       
1760   DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,len,ret));
1761   return(ret);
1762 }
1763
1764 /****************************************************************************
1765 read from a socket
1766 ****************************************************************************/
1767 int read_udp_socket(int fd,char *buf,int len)
1768 {
1769   int ret;
1770   struct sockaddr sock;
1771   int socklen;
1772   
1773   socklen = sizeof(sock);
1774   bzero((char *)&sock,socklen);
1775   bzero((char *)&lastip,sizeof(lastip));
1776   ret = recvfrom(fd,buf,len,0,&sock,&socklen);
1777   if (ret <= 0) {
1778     DEBUG(2,("read socket failed. ERRNO=%d\n",errno));
1779     return(0);
1780   }
1781
1782   lastip = *(struct in_addr *) &sock.sa_data[2];
1783   lastport = ntohs(((struct sockaddr_in *)&sock)->sin_port);
1784
1785   return(ret);
1786 }
1787
1788 /****************************************************************************
1789 read data from a device with a timout in msec.
1790 mincount = if timeout, minimum to read before returning
1791 maxcount = number to be read.
1792 ****************************************************************************/
1793 int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out)
1794 {
1795   fd_set fds;
1796   int selrtn;
1797   int readret;
1798   int nread = 0;
1799   struct timeval timeout;
1800
1801   /* just checking .... */
1802   if (maxcnt <= 0) return(0);
1803
1804   smb_read_error = 0;
1805
1806   /* Blocking read */
1807   if (time_out <= 0) {
1808     if (mincnt == 0) mincnt = maxcnt;
1809
1810     while (nread < mincnt) {
1811       readret = read(fd, buf + nread, maxcnt - nread);
1812       if (readret == 0) {
1813         smb_read_error = READ_EOF;
1814         return -1;
1815       }
1816
1817       if (readret == -1) {
1818         smb_read_error = READ_ERROR;
1819         return -1;
1820       }
1821       nread += readret;
1822     }
1823     return(nread);
1824   }
1825   
1826   /* Most difficult - timeout read */
1827   /* If this is ever called on a disk file and 
1828          mincnt is greater then the filesize then
1829          system performance will suffer severely as 
1830          select always return true on disk files */
1831
1832   /* Set initial timeout */
1833   timeout.tv_sec = time_out / 1000;
1834   timeout.tv_usec = 1000 * (time_out % 1000);
1835
1836   for (nread=0; nread<mincnt; ) 
1837     {      
1838       FD_ZERO(&fds);
1839       FD_SET(fd,&fds);
1840       
1841       selrtn = sys_select(&fds,&timeout);
1842
1843       /* Check if error */
1844       if(selrtn == -1) {
1845         /* something is wrong. Maybe the socket is dead? */
1846         smb_read_error = READ_ERROR;
1847         return -1;
1848       }
1849       
1850       /* Did we timeout ? */
1851       if (selrtn == 0) {
1852         smb_read_error = READ_TIMEOUT;
1853         return -1;
1854       }
1855       
1856       readret = read(fd, buf+nread, maxcnt-nread);
1857       if (readret == 0) {
1858         /* we got EOF on the file descriptor */
1859         smb_read_error = READ_EOF;
1860         return -1;
1861       }
1862
1863       if (readret == -1) {
1864         /* the descriptor is probably dead */
1865         smb_read_error = READ_ERROR;
1866         return -1;
1867       }
1868       
1869       nread += readret;
1870     }
1871
1872   /* Return the number we got */
1873   return(nread);
1874 }
1875
1876 /****************************************************************************
1877 read data from the client. Maxtime is in milliseconds
1878 ****************************************************************************/
1879 int read_max_udp(int fd,char *buffer,int bufsize,int maxtime)
1880 {
1881   fd_set fds;
1882   int selrtn;
1883   int nread;
1884   struct timeval timeout;
1885  
1886   FD_ZERO(&fds);
1887   FD_SET(fd,&fds);
1888
1889   timeout.tv_sec = maxtime / 1000;
1890   timeout.tv_usec = (maxtime % 1000) * 1000;
1891
1892   selrtn = sys_select(&fds,maxtime>0?&timeout:NULL);
1893
1894   if (!FD_ISSET(fd,&fds))
1895     return 0;
1896
1897   nread = read_udp_socket(fd, buffer, bufsize);
1898
1899   /* return the number got */
1900   return(nread);
1901 }
1902
1903 /*******************************************************************
1904 find the difference in milliseconds between two struct timeval
1905 values
1906 ********************************************************************/
1907 int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew)
1908 {
1909   return((tvalnew->tv_sec - tvalold->tv_sec)*1000 + 
1910          ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000);  
1911 }
1912
1913 /****************************************************************************
1914 send a keepalive packet (rfc1002)
1915 ****************************************************************************/
1916 BOOL send_keepalive(int client)
1917 {
1918   unsigned char buf[4];
1919
1920   buf[0] = 0x85;
1921   buf[1] = buf[2] = buf[3] = 0;
1922
1923   return(write_data(client,(char *)buf,4) == 4);
1924 }
1925
1926
1927
1928 /****************************************************************************
1929   read data from the client, reading exactly N bytes. 
1930 ****************************************************************************/
1931 int read_data(int fd,char *buffer,int N)
1932 {
1933   int  ret;
1934   int total=0;  
1935  
1936   smb_read_error = 0;
1937
1938   while (total < N)
1939     {
1940       ret = read(fd,buffer + total,N - total);
1941       if (ret == 0) {
1942         smb_read_error = READ_EOF;
1943         return 0;
1944       }
1945       if (ret == -1) {
1946         smb_read_error = READ_ERROR;
1947         return -1;
1948       }
1949       total += ret;
1950     }
1951   return total;
1952 }
1953
1954
1955 /****************************************************************************
1956   write data to a fd 
1957 ****************************************************************************/
1958 int write_data(int fd,char *buffer,int N)
1959 {
1960   int total=0;
1961   int ret;
1962
1963   while (total < N)
1964     {
1965       ret = write(fd,buffer + total,N - total);
1966
1967       if (ret == -1) return -1;
1968       if (ret == 0) return total;
1969
1970       total += ret;
1971     }
1972   return total;
1973 }
1974
1975
1976 /****************************************************************************
1977 transfer some data between two fd's
1978 ****************************************************************************/
1979 int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align)
1980 {
1981   static char *buf=NULL;  
1982   static int size=0;
1983   char *buf1,*abuf;
1984   int total = 0;
1985
1986   DEBUG(4,("transfer_file %d  (head=%d) called\n",n,headlen));
1987
1988   if (size == 0) {
1989     size = lp_readsize();
1990     size = MAX(size,1024);
1991   }
1992
1993   while (!buf && size>0) {
1994     buf = (char *)Realloc(buf,size+8);
1995     if (!buf) size /= 2;
1996   }
1997
1998   if (!buf) {
1999     DEBUG(0,("Can't allocate transfer buffer!\n"));
2000     exit(1);
2001   }
2002
2003   abuf = buf + (align%8);
2004
2005   if (header)
2006     n += headlen;
2007
2008   while (n > 0)
2009     {
2010       int s = MIN(n,size);
2011       int ret,ret2=0;
2012
2013       ret = 0;
2014
2015       if (header && (headlen >= MIN(s,1024))) {
2016         buf1 = header;
2017         s = headlen;
2018         ret = headlen;
2019         headlen = 0;
2020         header = NULL;
2021       } else {
2022         buf1 = abuf;
2023       }
2024
2025       if (header && headlen > 0)
2026         {
2027           ret = MIN(headlen,size);
2028           memcpy(buf1,header,ret);
2029           headlen -= ret;
2030           header += ret;
2031           if (headlen <= 0) header = NULL;
2032         }
2033
2034       if (s > ret)
2035         ret += read(infd,buf1+ret,s-ret);
2036
2037       if (ret > 0)
2038         {
2039           ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret);
2040           if (ret2 > 0) total += ret2;
2041           /* if we can't write then dump excess data */
2042           if (ret2 != ret)
2043             transfer_file(infd,-1,n-(ret+headlen),NULL,0,0);
2044         }
2045       if (ret <= 0 || ret2 != ret)
2046         return(total);
2047       n -= ret;
2048     }
2049   return(total);
2050 }
2051
2052
2053 /****************************************************************************
2054 read 4 bytes of a smb packet and return the smb length of the packet
2055 possibly store the result in the buffer
2056 ****************************************************************************/
2057 int read_smb_length(int fd,char *inbuf,int timeout)
2058 {
2059   char *buffer;
2060   char buf[4];
2061   int len=0, msg_type;
2062   BOOL ok=False;
2063
2064   if (inbuf)
2065     buffer = inbuf;
2066   else
2067     buffer = buf;
2068
2069   while (!ok)
2070     {
2071       if (timeout > 0)
2072         ok = (read_with_timeout(fd,buffer,4,4,timeout) == 4);
2073       else 
2074         ok = (read_data(fd,buffer,4) == 4);
2075
2076       if (!ok)
2077         return(-1);
2078
2079       len = smb_len(buffer);
2080       msg_type = CVAL(buffer,0);
2081
2082       if (msg_type == 0x85) 
2083         {
2084           DEBUG(5,("Got keepalive packet\n"));
2085           ok = False;
2086         }
2087     }
2088
2089   DEBUG(10,("got smb length of %d\n",len));
2090
2091   return(len);
2092 }
2093
2094
2095
2096 /****************************************************************************
2097   read an smb from a fd and return it's length
2098 The timeout is in milli seconds
2099 ****************************************************************************/
2100 BOOL receive_smb(int fd,char *buffer,int timeout)
2101 {
2102   int len,ret;
2103
2104   smb_read_error = 0;
2105
2106   bzero(buffer,smb_size + 100);
2107
2108   len = read_smb_length(fd,buffer,timeout);
2109   if (len == -1)
2110     return(False);
2111
2112   if (len > BUFFER_SIZE) {
2113     DEBUG(0,("Invalid packet length! (%d bytes).\n",len));
2114     if (len > BUFFER_SIZE + (SAFETY_MARGIN/2))
2115       exit(1);
2116   }
2117
2118   ret = read_data(fd,buffer+4,len);
2119   if (ret != len) {
2120     smb_read_error = READ_ERROR;
2121     return False;
2122   }
2123
2124   return(True);
2125 }
2126
2127
2128 /****************************************************************************
2129   send an smb to a fd 
2130 ****************************************************************************/
2131 BOOL send_smb(int fd,char *buffer)
2132 {
2133   int len;
2134   int ret,nwritten=0;
2135   len = smb_len(buffer) + 4;
2136
2137   while (nwritten < len)
2138     {
2139       ret = write_socket(fd,buffer+nwritten,len - nwritten);
2140       if (ret <= 0)
2141         {
2142           DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret));
2143           close_sockets();
2144           exit(1);
2145         }
2146       nwritten += ret;
2147     }
2148
2149
2150   return True;
2151 }
2152
2153
2154 /****************************************************************************
2155 find a pointer to a netbios name
2156 ****************************************************************************/
2157 char *name_ptr(char *buf,int ofs)
2158 {
2159   unsigned char c = *(unsigned char *)(buf+ofs);
2160
2161   if ((c & 0xC0) == 0xC0)
2162     {
2163       uint16 l;
2164       char p[2];
2165       memcpy(p,buf+ofs,2);
2166       p[0] &= ~0xC0;
2167       l = RSVAL(p,0);
2168       DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
2169       return(buf + l);
2170     }
2171   else
2172     return(buf+ofs);
2173 }  
2174
2175 /****************************************************************************
2176 extract a netbios name from a buf
2177 ****************************************************************************/
2178 int name_extract(char *buf,int ofs,char *name)
2179 {
2180   char *p = name_ptr(buf,ofs);
2181   int d = PTR_DIFF(p,buf+ofs);
2182   strcpy(name,"");
2183   if (d < -50 || d > 50) return(0);
2184   return(name_interpret(p,name));
2185 }  
2186   
2187
2188 /****************************************************************************
2189 return the total storage length of a mangled name
2190 ****************************************************************************/
2191 int name_len(char *s)
2192 {
2193   char *s0=s;
2194   unsigned char c = *(unsigned char *)s;
2195   if ((c & 0xC0) == 0xC0)
2196     return(2);
2197   while (*s) s += (*s)+1;
2198   return(PTR_DIFF(s,s0)+1);
2199 }
2200
2201 /****************************************************************************
2202 send a single packet to a port on another machine
2203 ****************************************************************************/
2204 BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
2205 {
2206   BOOL ret;
2207   int out_fd;
2208   struct sockaddr_in sock_out;
2209
2210   if (passive)
2211     return(True);
2212
2213   /* create a socket to write to */
2214   out_fd = socket(AF_INET, type, 0);
2215   if (out_fd == -1) 
2216     {
2217       DEBUG(0,("socket failed"));
2218       return False;
2219     }
2220
2221   /* set the address and port */
2222   bzero((char *)&sock_out,sizeof(sock_out));
2223   putip((char *)&sock_out.sin_addr,(char *)&ip);
2224   sock_out.sin_port = htons( port );
2225   sock_out.sin_family = AF_INET;
2226   
2227   if (DEBUGLEVEL > 0)
2228     DEBUG(3,("sending a packet of len %d to (%s) on port %d of type %s\n",
2229              len,inet_ntoa(ip),port,type==SOCK_DGRAM?"DGRAM":"STREAM"));
2230         
2231   /* send it */
2232   ret = (sendto(out_fd,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
2233
2234   if (!ret)
2235     DEBUG(0,("Packet send to %s(%d) failed ERRNO=%d\n",
2236              inet_ntoa(ip),port,errno));
2237
2238   close(out_fd);
2239   return(ret);
2240 }
2241
2242 /*******************************************************************
2243 sleep for a specified number of milliseconds
2244 ********************************************************************/
2245 void msleep(int t)
2246 {
2247   int tdiff=0;
2248   struct timeval tval,t1,t2;  
2249   fd_set fds;
2250
2251   GetTimeOfDay(&t1);
2252   GetTimeOfDay(&t2);
2253   
2254   while (tdiff < t) {
2255     tval.tv_sec = (t-tdiff)/1000;
2256     tval.tv_usec = 1000*((t-tdiff)%1000);
2257  
2258     FD_ZERO(&fds);
2259     errno = 0;
2260     sys_select(&fds,&tval);
2261
2262     GetTimeOfDay(&t2);
2263     tdiff = TvalDiff(&t1,&t2);
2264   }
2265 }
2266
2267 /****************************************************************************
2268 check if a string is part of a list
2269 ****************************************************************************/
2270 BOOL in_list(char *s,char *list,BOOL casesensitive)
2271 {
2272   pstring tok;
2273   char *p=list;
2274
2275   if (!list) return(False);
2276
2277   while (next_token(&p,tok,LIST_SEP))
2278     {
2279       if (casesensitive) {
2280         if (strcmp(tok,s) == 0)
2281           return(True);
2282       } else {
2283         if (StrCaseCmp(tok,s) == 0)
2284           return(True);
2285       }
2286     }
2287   return(False);
2288 }
2289
2290 /* this is used to prevent lots of mallocs of size 1 */
2291 static char *null_string = NULL;
2292
2293 /****************************************************************************
2294 set a string value, allocing the space for the string
2295 ****************************************************************************/
2296 BOOL string_init(char **dest,char *src)
2297 {
2298   int l;
2299   if (!src)     
2300     src = "";
2301
2302   l = strlen(src);
2303
2304   if (l == 0)
2305     {
2306       if (!null_string)
2307         null_string = (char *)malloc(1);
2308
2309       *null_string = 0;
2310       *dest = null_string;
2311     }
2312   else
2313     {
2314       *dest = (char *)malloc(l+1);
2315       strcpy(*dest,src);
2316     }
2317   return(True);
2318 }
2319
2320 /****************************************************************************
2321 free a string value
2322 ****************************************************************************/
2323 void string_free(char **s)
2324 {
2325   if (!s || !(*s)) return;
2326   if (*s == null_string)
2327     *s = NULL;
2328   if (*s) free(*s);
2329   *s = NULL;
2330 }
2331
2332 /****************************************************************************
2333 set a string value, allocing the space for the string, and deallocating any 
2334 existing space
2335 ****************************************************************************/
2336 BOOL string_set(char **dest,char *src)
2337 {
2338   string_free(dest);
2339
2340   return(string_init(dest,src));
2341 }
2342
2343 /****************************************************************************
2344 substitute a string for a pattern in another string. Make sure there is 
2345 enough room!
2346
2347 This routine looks for pattern in s and replaces it with 
2348 insert. It may do multiple replacements.
2349
2350 return True if a substitution was done.
2351 ****************************************************************************/
2352 BOOL string_sub(char *s,char *pattern,char *insert)
2353 {
2354   BOOL ret = False;
2355   char *p;
2356   int ls,lp,li;
2357
2358   if (!insert || !pattern || !s) return(False);
2359
2360   ls = strlen(s);
2361   lp = strlen(pattern);
2362   li = strlen(insert);
2363
2364   if (!*pattern) return(False);
2365
2366   while (lp <= ls && (p = strstr(s,pattern)))
2367     {
2368       ret = True;
2369       memmove(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp));
2370       memcpy(p,insert,li);
2371       s = p + li;
2372       ls = strlen(s);
2373     }
2374   return(ret);
2375 }
2376
2377
2378
2379 /*********************************************************
2380 * Recursive routine that is called by mask_match.
2381 * Does the actual matching.
2382 *********************************************************/
2383 BOOL do_match(char *str, char *regexp, int case_sig)
2384 {
2385   char *p;
2386
2387   for( p = regexp; *p && *str; ) {
2388     switch(*p) {
2389     case '?':
2390       str++; p++;
2391       break;
2392
2393     case '*':
2394       /* Look for a character matching 
2395          the one after the '*' */
2396       p++;
2397       if(!*p)
2398         return True; /* Automatic match */
2399       while(*str) {
2400         while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
2401           str++;
2402         if(do_match(str,p,case_sig))
2403           return True;
2404         if(!*str)
2405           return False;
2406         else
2407           str++;
2408       }
2409       return False;
2410
2411     default:
2412       if(case_sig) {
2413         if(*str != *p)
2414           return False;
2415       } else {
2416         if(toupper(*str) != toupper(*p))
2417           return False;
2418       }
2419       str++, p++;
2420       break;
2421     }
2422   }
2423   if(!*p && !*str)
2424     return True;
2425
2426   if (!*p && str[0] == '.' && str[1] == 0)
2427     return(True);
2428   
2429   if (!*str && *p == '?')
2430     {
2431       while (*p == '?') p++;
2432       return(!*p);
2433     }
2434
2435   if(!*str && (*p == '*' && p[1] == '\0'))
2436     return True;
2437   return False;
2438 }
2439
2440
2441 /*********************************************************
2442 * Routine to match a given string with a regexp - uses
2443 * simplified regexp that takes * and ? only. Case can be
2444 * significant or not.
2445 *********************************************************/
2446 BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
2447 {
2448   char *p;
2449   pstring p1, p2;
2450   fstring ebase,eext,sbase,sext;
2451
2452   BOOL matched;
2453
2454   /* Make local copies of str and regexp */
2455   StrnCpy(p1,regexp,sizeof(pstring)-1);
2456   StrnCpy(p2,str,sizeof(pstring)-1);
2457
2458   if (!strchr(p2,'.')) {
2459     strcat(p2,".");
2460   }
2461
2462 /*
2463   if (!strchr(p1,'.')) {
2464     strcat(p1,".");
2465   }
2466 */
2467
2468 #if 0
2469   if (strchr(p1,'.'))
2470     {
2471       string_sub(p1,"*.*","*");
2472       string_sub(p1,".*","*");
2473     }
2474 #endif
2475
2476   /* Remove any *? and ** as they are meaningless */
2477   for(p = p1; *p; p++)
2478     while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
2479       (void)strcpy( &p[1], &p[2]);
2480
2481   if (strequal(p1,"*")) return(True);
2482
2483   DEBUG(5,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
2484
2485   if (trans2) {
2486     strcpy(ebase,p1);
2487     strcpy(sbase,p2);
2488   } else {
2489     if ((p=strrchr(p1,'.'))) {
2490       *p = 0;
2491       strcpy(ebase,p1);
2492       strcpy(eext,p+1);
2493     } else {
2494       strcpy(ebase,p1);
2495       eext[0] = 0;
2496     }
2497
2498   if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
2499     *p = 0;
2500     strcpy(sbase,p2);
2501     strcpy(sext,p+1);
2502   } else {
2503     strcpy(sbase,p2);
2504     strcpy(sext,"");
2505   }
2506   }
2507
2508   matched = do_match(sbase,ebase,case_sig) && 
2509     (trans2 || do_match(sext,eext,case_sig));
2510
2511   DEBUG(5,("mask_match returning %d\n", matched));
2512
2513   return matched;
2514 }
2515
2516
2517
2518 /****************************************************************************
2519 become a daemon, discarding the controlling terminal
2520 ****************************************************************************/
2521 void become_daemon(void)
2522 {
2523 #ifndef NO_FORK_DEBUG
2524   if (fork())
2525     exit(0);
2526
2527   /* detach from the terminal */
2528 #ifdef USE_SETSID
2529   setsid();
2530 #else /* USE_SETSID */
2531 #ifdef TIOCNOTTY
2532   {
2533     int i = open("/dev/tty", O_RDWR);
2534     if (i >= 0) 
2535       {
2536         ioctl(i, (int) TIOCNOTTY, (char *)0);      
2537         close(i);
2538       }
2539   }
2540 #endif /* TIOCNOTTY */
2541 #endif /* USE_SETSID */
2542   /* Close fd's 0,1,2. Needed if started by rsh */
2543   close_low_fds();
2544 #endif /* NO_FORK_DEBUG */
2545 }
2546
2547
2548 /****************************************************************************
2549 put up a yes/no prompt
2550 ****************************************************************************/
2551 BOOL yesno(char *p)
2552 {
2553   pstring ans;
2554   printf("%s",p);
2555
2556   if (!fgets(ans,sizeof(ans)-1,stdin))
2557     return(False);
2558
2559   if (*ans == 'y' || *ans == 'Y')
2560     return(True);
2561
2562   return(False);
2563 }
2564
2565 /****************************************************************************
2566 read a line from a file with possible \ continuation chars. 
2567 Blanks at the start or end of a line are stripped.
2568 The string will be allocated if s2 is NULL
2569 ****************************************************************************/
2570 char *fgets_slash(char *s2,int maxlen,FILE *f)
2571 {
2572   char *s=s2;
2573   int len = 0;
2574   int c;
2575   BOOL start_of_line = True;
2576
2577   if (feof(f))
2578     return(NULL);
2579
2580   if (!s2)
2581     {
2582       maxlen = MIN(maxlen,8);
2583       s = (char *)Realloc(s,maxlen);
2584     }
2585
2586   if (!s || maxlen < 2) return(NULL);
2587
2588   *s = 0;
2589
2590   while (len < maxlen-1)
2591     {
2592       c = getc(f);
2593       switch (c)
2594         {
2595         case '\r':
2596           break;
2597         case '\n':
2598           while (len > 0 && s[len-1] == ' ')
2599             {
2600               s[--len] = 0;
2601             }
2602           if (len > 0 && s[len-1] == '\\')
2603             {
2604               s[--len] = 0;
2605               start_of_line = True;
2606               break;
2607             }
2608           return(s);
2609         case EOF:
2610           if (len <= 0 && !s2) 
2611             free(s);
2612           return(len>0?s:NULL);
2613         case ' ':
2614           if (start_of_line)
2615             break;
2616         default:
2617           start_of_line = False;
2618           s[len++] = c;
2619           s[len] = 0;
2620         }
2621       if (!s2 && len > maxlen-3)
2622         {
2623           maxlen *= 2;
2624           s = (char *)Realloc(s,maxlen);
2625           if (!s) return(NULL);
2626         }
2627     }
2628   return(s);
2629 }
2630
2631
2632
2633 /****************************************************************************
2634 set the length of a file from a filedescriptor.
2635 Returns 0 on success, -1 on failure.
2636 ****************************************************************************/
2637 int set_filelen(int fd, long len)
2638 {
2639 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2640    extend a file with ftruncate. Provide alternate implementation
2641    for this */
2642
2643 #if FTRUNCATE_CAN_EXTEND
2644   return ftruncate(fd, len);
2645 #else
2646   struct stat st;
2647   char c = 0;
2648   long currpos = lseek(fd, 0L, SEEK_CUR);
2649
2650   if(currpos < 0)
2651     return -1;
2652   /* Do an fstat to see if the file is longer than
2653      the requested size (call ftruncate),
2654      or shorter, in which case seek to len - 1 and write 1
2655      byte of zero */
2656   if(fstat(fd, &st)<0)
2657     return -1;
2658
2659 #ifdef S_ISFIFO
2660   if (S_ISFIFO(st.st_mode)) return 0;
2661 #endif
2662
2663   if(st.st_size == len)
2664     return 0;
2665   if(st.st_size > len)
2666     return ftruncate(fd, len);
2667
2668   if(lseek(fd, len-1, SEEK_SET) != len -1)
2669     return -1;
2670   if(write(fd, &c, 1)!=1)
2671     return -1;
2672   /* Seek to where we were */
2673   lseek(fd, currpos, SEEK_SET);
2674   return 0;
2675 #endif
2676 }
2677
2678
2679 /****************************************************************************
2680 return the byte checksum of some data
2681 ****************************************************************************/
2682 int byte_checksum(char *buf,int len)
2683 {
2684   unsigned char *p = (unsigned char *)buf;
2685   int ret = 0;
2686   while (len--)
2687     ret += *p++;
2688   return(ret);
2689 }
2690
2691
2692
2693 #ifdef HPUX
2694 /****************************************************************************
2695 this is a version of setbuffer() for those machines that only have setvbuf
2696 ****************************************************************************/
2697  void setbuffer(FILE *f,char *buf,int bufsize)
2698 {
2699   setvbuf(f,buf,_IOFBF,bufsize);
2700 }
2701 #endif
2702
2703
2704 /****************************************************************************
2705 parse out a directory name from a path name. Assumes dos style filenames.
2706 ****************************************************************************/
2707 char *dirname_dos(char *path,char *buf)
2708 {
2709   char *p = strrchr(path,'\\');
2710
2711   if (!p)
2712     strcpy(buf,path);
2713   else
2714     {
2715       *p = 0;
2716       strcpy(buf,path);
2717       *p = '\\';
2718     }
2719
2720   return(buf);
2721 }
2722
2723
2724 /****************************************************************************
2725 parse out a filename from a path name. Assumes dos style filenames.
2726 ****************************************************************************/
2727 static char *filename_dos(char *path,char *buf)
2728 {
2729   char *p = strrchr(path,'\\');
2730
2731   if (!p)
2732     strcpy(buf,path);
2733   else
2734     strcpy(buf,p+1);
2735
2736   return(buf);
2737 }
2738
2739
2740
2741 /****************************************************************************
2742 expand a pointer to be a particular size
2743 ****************************************************************************/
2744 void *Realloc(void *p,int size)
2745 {
2746   void *ret=NULL;
2747
2748   if (size == 0) {
2749     if (p) free(p);
2750     DEBUG(5,("Realloc asked for 0 bytes\n"));
2751     return NULL;
2752   }
2753
2754   if (!p)
2755     ret = (void *)malloc(size);
2756   else
2757     ret = (void *)realloc(p,size);
2758
2759   if (!ret)
2760     DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",size));
2761
2762   return(ret);
2763 }
2764
2765 #ifdef NOSTRDUP
2766 /****************************************************************************
2767 duplicate a string
2768 ****************************************************************************/
2769  char *strdup(char *s)
2770 {
2771   char *ret = NULL;
2772   if (!s) return(NULL);
2773   ret = (char *)malloc(strlen(s)+1);
2774   if (!ret) return(NULL);
2775   strcpy(ret,s);
2776   return(ret);
2777 }
2778 #endif
2779
2780
2781 /****************************************************************************
2782   Signal handler for SIGPIPE (write on a disconnected socket) 
2783 ****************************************************************************/
2784 void Abort(void )
2785 {
2786   DEBUG(0,("Probably got SIGPIPE\nExiting\n"));
2787   exit(2);
2788 }
2789
2790 /****************************************************************************
2791 get my own name and IP
2792 ****************************************************************************/
2793 BOOL get_myname(char *my_name,struct in_addr *ip)
2794 {
2795   struct hostent *hp;
2796   pstring hostname;
2797
2798   *hostname = 0;
2799
2800   /* get my host name */
2801   if (gethostname(hostname, MAXHOSTNAMELEN) == -1) 
2802     {
2803       DEBUG(0,("gethostname failed\n"));
2804       return False;
2805     } 
2806
2807   /* get host info */
2808   if ((hp = Get_Hostbyname(hostname)) == 0) 
2809     {
2810       DEBUG(0,( "Get_Hostbyname: Unknown host %s.\n",hostname));
2811       return False;
2812     }
2813
2814   if (my_name)
2815     {
2816       /* split off any parts after an initial . */
2817       char *p = strchr(hostname,'.');
2818       if (p) *p = 0;
2819
2820       strcpy(my_name,hostname);
2821     }
2822
2823   if (ip)
2824     putip((char *)ip,(char *)hp->h_addr);
2825
2826   return(True);
2827 }
2828
2829
2830 /****************************************************************************
2831 true if two IP addresses are equal
2832 ****************************************************************************/
2833 BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
2834 {
2835   uint32 a1,a2;
2836   a1 = ntohl(ip1.s_addr);
2837   a2 = ntohl(ip2.s_addr);
2838   return(a1 == a2);
2839 }
2840
2841
2842 /****************************************************************************
2843 open a socket of the specified type, port and address for incoming data
2844 ****************************************************************************/
2845 int open_socket_in(int type, int port, int dlevel,uint32 socket_addr)
2846 {
2847   struct hostent *hp;
2848   struct sockaddr_in sock;
2849   pstring host_name;
2850   int res;
2851
2852   /* get my host name */
2853   if (gethostname(host_name, MAXHOSTNAMELEN) == -1) 
2854     { DEBUG(0,("gethostname failed\n")); return -1; } 
2855
2856   /* get host info */
2857   if ((hp = Get_Hostbyname(host_name)) == 0) 
2858     {
2859       DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",host_name));
2860       return -1;
2861     }
2862   
2863   bzero((char *)&sock,sizeof(sock));
2864   memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
2865 #if defined(__FreeBSD__) || defined(NETBSD) /* XXX not the right ifdef */
2866   sock.sin_len = sizeof(sock);
2867 #endif
2868   sock.sin_port = htons( port );
2869   sock.sin_family = hp->h_addrtype;
2870   sock.sin_addr.s_addr = socket_addr;
2871   res = socket(hp->h_addrtype, type, 0);
2872   if (res == -1) 
2873     { DEBUG(0,("socket failed\n")); return -1; }
2874
2875   {
2876     int one=1;
2877     setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
2878   }
2879
2880   /* now we've got a socket - we need to bind it */
2881   if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) 
2882     { 
2883       if (port) {
2884         if (port == SMB_PORT || port == NMB_PORT)
2885           DEBUG(dlevel,("bind failed on port %d socket_addr=%x (%s)\n",
2886                         port,socket_addr,strerror(errno))); 
2887         close(res); 
2888
2889         if (dlevel > 0 && port < 1000)
2890           port = 7999;
2891
2892         if (port >= 1000 && port < 9000)
2893           return(open_socket_in(type,port+1,dlevel,socket_addr));
2894       }
2895
2896       return(-1); 
2897     }
2898   DEBUG(3,("bind succeeded on port %d\n",port));
2899
2900   return res;
2901 }
2902
2903
2904 /****************************************************************************
2905   create an outgoing socket
2906   **************************************************************************/
2907 int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
2908 {
2909   struct sockaddr_in sock_out;
2910   int res,ret;
2911   int connect_loop = 250; /* 250 milliseconds */
2912   int loops = (timeout * 1000) / connect_loop;
2913
2914   /* create a socket to write to */
2915   res = socket(PF_INET, type, 0);
2916   if (res == -1) 
2917     { DEBUG(0,("socket error\n")); return -1; }
2918
2919   if (type != SOCK_STREAM) return(res);
2920   
2921   bzero((char *)&sock_out,sizeof(sock_out));
2922   putip((char *)&sock_out.sin_addr,(char *)addr);
2923   
2924   sock_out.sin_port = htons( port );
2925   sock_out.sin_family = PF_INET;
2926
2927   /* set it non-blocking */
2928   set_blocking(res,0);
2929
2930   DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port));
2931   
2932   /* and connect it to the destination */
2933 connect_again:
2934   ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out));
2935
2936   /* Some systems return EAGAIN when they mean EINPROGRESS */
2937   if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
2938         errno == EAGAIN) && loops--) {
2939     msleep(connect_loop);
2940     goto connect_again;
2941   }
2942
2943   if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
2944          errno == EAGAIN)) {
2945       DEBUG(1,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port));
2946       close(res);
2947       return -1;
2948   }
2949
2950 #ifdef EISCONN
2951   if (ret < 0 && errno == EISCONN) {
2952     errno = 0;
2953     ret = 0;
2954   }
2955 #endif
2956
2957   if (ret < 0) {
2958     DEBUG(1,("error connecting to %s:%d (%s)\n",
2959              inet_ntoa(*addr),port,strerror(errno)));
2960     return -1;
2961   }
2962
2963   /* set it blocking again */
2964   set_blocking(res,1);
2965
2966   return res;
2967 }
2968
2969
2970 /****************************************************************************
2971 interpret a protocol description string, with a default
2972 ****************************************************************************/
2973 int interpret_protocol(char *str,int def)
2974 {
2975   if (strequal(str,"NT1"))
2976     return(PROTOCOL_NT1);
2977   if (strequal(str,"LANMAN2"))
2978     return(PROTOCOL_LANMAN2);
2979   if (strequal(str,"LANMAN1"))
2980     return(PROTOCOL_LANMAN1);
2981   if (strequal(str,"CORE"))
2982     return(PROTOCOL_CORE);
2983   if (strequal(str,"COREPLUS"))
2984     return(PROTOCOL_COREPLUS);
2985   if (strequal(str,"CORE+"))
2986     return(PROTOCOL_COREPLUS);
2987   
2988   DEBUG(0,("Unrecognised protocol level %s\n",str));
2989   
2990   return(def);
2991 }
2992
2993 /****************************************************************************
2994 interpret a security level
2995 ****************************************************************************/
2996 int interpret_security(char *str,int def)
2997 {
2998   if (strequal(str,"SERVER"))
2999     return(SEC_SERVER);
3000   if (strequal(str,"USER"))
3001     return(SEC_USER);
3002   if (strequal(str,"SHARE"))
3003     return(SEC_SHARE);
3004   
3005   DEBUG(0,("Unrecognised security level %s\n",str));
3006   
3007   return(def);
3008 }
3009
3010
3011 /****************************************************************************
3012 interpret an internet address or name into an IP address in 4 byte form
3013 ****************************************************************************/
3014 uint32 interpret_addr(char *str)
3015 {
3016   struct hostent *hp;
3017   uint32 res;
3018   int i;
3019   BOOL pure_address = True;
3020
3021   if (strcmp(str,"0.0.0.0") == 0) return(0);
3022   if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
3023
3024   for (i=0; pure_address && str[i]; i++)
3025     if (!(isdigit(str[i]) || str[i] == '.')) 
3026       pure_address = False;
3027
3028   /* if it's in the form of an IP address then get the lib to interpret it */
3029   if (pure_address) {
3030     res = inet_addr(str);
3031   } else {
3032     /* otherwise assume it's a network name of some sort and use 
3033        Get_Hostbyname */
3034     if ((hp = Get_Hostbyname(str)) == 0) {
3035       DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
3036       return 0;
3037     }
3038     putip((char *)&res,(char *)hp->h_addr);
3039   }
3040
3041   if (res == (uint32)-1) return(0);
3042
3043   return(res);
3044 }
3045
3046 /*******************************************************************
3047   a convenient addition to interpret_addr()
3048   ******************************************************************/
3049 struct in_addr *interpret_addr2(char *str)
3050 {
3051   static struct in_addr ret;
3052   uint32 a = interpret_addr(str);
3053   ret.s_addr = a;
3054   return(&ret);
3055 }
3056
3057 /*******************************************************************
3058   check if an IP is the 0.0.0.0
3059   ******************************************************************/
3060 BOOL zero_ip(struct in_addr ip)
3061 {
3062   uint32 a;
3063   putip((char *)&a,(char *)&ip);
3064   return(a == 0);
3065 }
3066
3067
3068 /*******************************************************************
3069  matchname - determine if host name matches IP address 
3070  ******************************************************************/
3071 static BOOL matchname(char *remotehost,struct in_addr  addr)
3072 {
3073   struct hostent *hp;
3074   int     i;
3075   
3076   if ((hp = Get_Hostbyname(remotehost)) == 0) {
3077     DEBUG(0,("Get_Hostbyname(%s): lookup failure", remotehost));
3078     return False;
3079   } 
3080
3081   /*
3082    * Make sure that gethostbyname() returns the "correct" host name.
3083    * Unfortunately, gethostbyname("localhost") sometimes yields
3084    * "localhost.domain". Since the latter host name comes from the
3085    * local DNS, we just have to trust it (all bets are off if the local
3086    * DNS is perverted). We always check the address list, though.
3087    */
3088   
3089   if (strcasecmp(remotehost, hp->h_name)
3090       && strcasecmp(remotehost, "localhost")) {
3091     DEBUG(0,("host name/name mismatch: %s != %s",
3092              remotehost, hp->h_name));
3093     return False;
3094   }
3095         
3096   /* Look up the host address in the address list we just got. */
3097   for (i = 0; hp->h_addr_list[i]; i++) {
3098     if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
3099       return True;
3100   }
3101
3102   /*
3103    * The host name does not map to the original host address. Perhaps
3104    * someone has compromised a name server. More likely someone botched
3105    * it, but that could be dangerous, too.
3106    */
3107   
3108   DEBUG(0,("host name/address mismatch: %s != %s",
3109            inet_ntoa(addr), hp->h_name));
3110   return False;
3111 }
3112
3113 /*******************************************************************
3114  Reset the 'done' variables so after a client process is created
3115  from a fork call these calls will be re-done. This should be
3116  expanded if more variables need reseting.
3117  ******************************************************************/
3118
3119 static BOOL global_client_name_done = False;
3120 static BOOL global_client_addr_done = False;
3121
3122 void reset_globals_after_fork()
3123 {
3124   global_client_name_done = False;
3125   global_client_addr_done = False;
3126 }
3127  
3128 /*******************************************************************
3129  return the DNS name of the client 
3130  ******************************************************************/
3131 char *client_name(void)
3132 {
3133   extern int Client;
3134   struct sockaddr sa;
3135   struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
3136   int     length = sizeof(sa);
3137   static pstring name_buf;
3138   struct hostent *hp;
3139
3140   if (global_client_name_done) 
3141     return name_buf;
3142
3143   strcpy(name_buf,"UNKNOWN");
3144
3145   if (getpeername(Client, &sa, &length) < 0) {
3146     DEBUG(0,("getpeername failed\n"));
3147     return name_buf;
3148   }
3149
3150   /* Look up the remote host name. */
3151   if ((hp = gethostbyaddr((char *) &sockin->sin_addr,
3152                           sizeof(sockin->sin_addr),
3153                           AF_INET)) == 0) {
3154     DEBUG(1,("Gethostbyaddr failed for %s\n",client_addr()));
3155     StrnCpy(name_buf,client_addr(),sizeof(name_buf) - 1);
3156   } else {
3157     StrnCpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1);
3158     if (!matchname(name_buf, sockin->sin_addr)) {
3159       DEBUG(0,("Matchname failed on %s %s\n",name_buf,client_addr()));
3160       strcpy(name_buf,"UNKNOWN");
3161     }
3162   }
3163   global_client_name_done = True;
3164   return name_buf;
3165 }
3166
3167 /*******************************************************************
3168  return the IP addr of the client as a string 
3169  ******************************************************************/
3170 char *client_addr(void)
3171 {
3172   extern int Client;
3173   struct sockaddr sa;
3174   struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
3175   int     length = sizeof(sa);
3176   static fstring addr_buf;
3177
3178   if (global_client_addr_done) 
3179     return addr_buf;
3180
3181   strcpy(addr_buf,"0.0.0.0");
3182
3183   if (getpeername(Client, &sa, &length) < 0) {
3184     DEBUG(0,("getpeername failed\n"));
3185     return addr_buf;
3186   }
3187
3188   strcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr));
3189
3190   global_client_addr_done = True;
3191   return addr_buf;
3192 }
3193
3194 /*******************************************************************
3195 sub strings with useful parameters
3196 ********************************************************************/
3197 void standard_sub_basic(char *s)
3198 {
3199   if (!strchr(s,'%')) return;
3200
3201   string_sub(s,"%R",remote_proto);
3202   string_sub(s,"%a",remote_arch);
3203   string_sub(s,"%m",remote_machine);
3204   string_sub(s,"%L",local_machine);
3205
3206   if (!strchr(s,'%')) return;
3207
3208   string_sub(s,"%v",VERSION);
3209   string_sub(s,"%h",myhostname);
3210   string_sub(s,"%U",sesssetup_user);
3211
3212   if (!strchr(s,'%')) return;
3213
3214   string_sub(s,"%I",client_addr());
3215   if (strstr(s,"%M"))
3216     string_sub(s,"%M",client_name());
3217   string_sub(s,"%T",timestring());
3218
3219   if (!strchr(s,'%')) return;
3220
3221   {
3222     char pidstr[10];
3223     sprintf(pidstr,"%d",(int)getpid());
3224     string_sub(s,"%d",pidstr);
3225   }
3226
3227   if (!strchr(s,'%')) return;
3228
3229   {
3230     struct passwd *pass = Get_Pwnam(sesssetup_user,False);
3231     if (pass) {
3232       string_sub(s,"%G",gidtoname(pass->pw_gid));
3233     }
3234   }
3235 }
3236
3237
3238 /*******************************************************************
3239 are two IPs on the same subnet?
3240 ********************************************************************/
3241 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
3242 {
3243   uint32 net1,net2,nmask;
3244
3245   nmask = ntohl(mask.s_addr);
3246   net1  = ntohl(ip1.s_addr);
3247   net2  = ntohl(ip2.s_addr);
3248             
3249   return((net1 & nmask) == (net2 & nmask));
3250 }
3251
3252
3253 /*******************************************************************
3254 write a string in unicoode format
3255 ********************************************************************/
3256 int PutUniCode(char *dst,char *src)
3257 {
3258   int ret = 0;
3259   while (*src) {
3260     dst[ret++] = src[0];
3261     dst[ret++] = 0;    
3262     src++;
3263   }
3264   dst[ret++]=0;
3265   dst[ret++]=0;
3266   return(ret);
3267 }
3268
3269 /****************************************************************************
3270 a wrapper for gethostbyname() that tries with all lower and all upper case 
3271 if the initial name fails
3272 ****************************************************************************/
3273 struct hostent *Get_Hostbyname(char *name)
3274 {
3275   char *name2 = strdup(name);
3276   struct hostent *ret;
3277
3278   if (!name2)
3279     {
3280       DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
3281       exit(0);
3282     }
3283
3284   if (!isalnum(*name2))
3285     {
3286       free(name2);
3287       return(NULL);
3288     }
3289
3290   ret = sys_gethostbyname(name2);
3291   if (ret != NULL)
3292     {
3293       free(name2);
3294       return(ret);
3295     }
3296
3297   /* try with all lowercase */
3298   strlower(name2);
3299   ret = sys_gethostbyname(name2);
3300   if (ret != NULL)
3301     {
3302       free(name2);
3303       return(ret);
3304     }
3305
3306   /* try with all uppercase */
3307   strupper(name2);
3308   ret = sys_gethostbyname(name2);
3309   if (ret != NULL)
3310     {
3311       free(name2);
3312       return(ret);
3313     }
3314   
3315   /* nothing works :-( */
3316   free(name2);
3317   return(NULL);
3318 }
3319
3320
3321 /****************************************************************************
3322 check if a process exists. Does this work on all unixes?
3323 ****************************************************************************/
3324 BOOL process_exists(int pid)
3325 {
3326 #ifdef LINUX
3327   fstring s;
3328   sprintf(s,"/proc/%d",pid);
3329   return(directory_exist(s,NULL));
3330 #else
3331   {
3332     static BOOL tested=False;
3333     static BOOL ok=False;
3334     fstring s;
3335     if (!tested) {
3336       tested = True;
3337       sprintf(s,"/proc/%05d",(int)getpid());
3338       ok = file_exist(s,NULL);
3339     }
3340     if (ok) {
3341       sprintf(s,"/proc/%05d",pid);
3342       return(file_exist(s,NULL));
3343     }
3344   }
3345
3346   /* CGH 8/16/96 - added ESRCH test */
3347   return(pid == getpid() || kill(pid,0) == 0 || errno != ESRCH);
3348 #endif
3349 }
3350
3351
3352 /*******************************************************************
3353 turn a uid into a user name
3354 ********************************************************************/
3355 char *uidtoname(int uid)
3356 {
3357   static char name[40];
3358   struct passwd *pass = getpwuid(uid);
3359   if (pass) return(pass->pw_name);
3360   sprintf(name,"%d",uid);
3361   return(name);
3362 }
3363
3364 /*******************************************************************
3365 turn a gid into a group name
3366 ********************************************************************/
3367 char *gidtoname(int gid)
3368 {
3369   static char name[40];
3370   struct group *grp = getgrgid(gid);
3371   if (grp) return(grp->gr_name);
3372   sprintf(name,"%d",gid);
3373   return(name);
3374 }
3375
3376 /*******************************************************************
3377 block sigs
3378 ********************************************************************/
3379 void BlockSignals(BOOL block,int signum)
3380 {
3381 #ifdef USE_SIGBLOCK
3382   int block_mask = sigmask(signum);
3383   static int oldmask = 0;
3384   if (block) 
3385     oldmask = sigblock(block_mask);
3386   else
3387     sigsetmask(oldmask);
3388 #elif defined(USE_SIGPROCMASK)
3389   sigset_t set;
3390   sigemptyset(&set);
3391   sigaddset(&set,signum);
3392   sigprocmask(block?SIG_BLOCK:SIG_UNBLOCK,&set,NULL);
3393 #endif
3394 }
3395
3396 #if AJT
3397 /*******************************************************************
3398 my own panic function - not suitable for general use
3399 ********************************************************************/
3400 void ajt_panic(void)
3401 {
3402   system("/usr/bin/X11/xedit -display ljus:0 /tmp/ERROR_FAULT");
3403 }
3404 #endif
3405
3406 #ifdef USE_DIRECT
3407 #define DIRECT direct
3408 #else
3409 #define DIRECT dirent
3410 #endif
3411
3412 /*******************************************************************
3413 a readdir wrapper which just returns the file name
3414 also return the inode number if requested
3415 ********************************************************************/
3416 char *readdirname(void *p)
3417 {
3418   struct DIRECT *ptr;
3419   char *dname;
3420
3421   if (!p) return(NULL);
3422   
3423   ptr = (struct DIRECT *)readdir(p);
3424   if (!ptr) return(NULL);
3425
3426   dname = ptr->d_name;
3427
3428 #ifdef NEXT2
3429   if (telldir(p) < 0) return(NULL);
3430 #endif
3431
3432 #ifdef SUNOS5
3433   /* this handles a broken compiler setup, causing a mixture
3434    of BSD and SYSV headers and libraries */
3435   {
3436     static BOOL broken_readdir = False;
3437     if (!broken_readdir && !(*(dname)) && strequal("..",dname-2))
3438       {
3439         DEBUG(0,("Your readdir() is broken. You have somehow mixed SYSV and BSD headers and libraries\n"));
3440         broken_readdir = True;
3441       }
3442     if (broken_readdir)
3443       dname = dname - 2;
3444   }
3445 #endif
3446
3447   {
3448     static pstring buf;
3449     strcpy(buf, dname);
3450     unix_to_dos(buf, True);
3451     dname = buf;
3452   }
3453
3454   return(dname);
3455 }
3456
3457 /*
3458  * Utility function used by is_hidden_path() and is_vetoed_name()
3459  * to decide if the last component of a path matches a (possibly
3460  * wildcarded) entry in a namelist.
3461  */
3462
3463 static BOOL is_in_path(char *name, char *namelist)
3464 {
3465   pstring last_component;
3466   char *p;
3467   char *nameptr = namelist;
3468   char *name_end;
3469
3470   DEBUG(5, ("is_in_path: %s list: %s\n", name, namelist));
3471
3472   /* if we have no list it's obviously not in the path */
3473   if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0'))) 
3474   {
3475     DEBUG(5,("is_in_path: no name list.  return False\n"));
3476     return False;
3477   }
3478
3479   /* Get the last component of the unix name. */
3480   p = strrchr(name, '/');
3481   strncpy(last_component, p ? p : name, sizeof(last_component)-1);
3482   last_component[sizeof(last_component)-1] = '\0'; 
3483
3484   /* now, we need to find the names one by one and check them
3485      they can contain spaces and all sorts of stuff so we
3486      separate them with of all things '\' which can never be in a filename
3487      I could use "" but then I have to break them all out
3488      maybe such a routine exists somewhere?
3489   */
3490  
3491   /* lkcl 03jul97 - the separator character used to be a '/'.
3492      i changed it to a '\', after examining the code, and seeing
3493      that unix_convert is called before check_path and dos_mode.
3494      unix_convert changes, in the path, all dos '\'s to unix '/'s.
3495
3496      the alternatives are:
3497
3498      1) move all check_path and dos_mode calls to before the
3499         unix_convert calls.
3500
3501      2) have a corresponding dos_convert call, which can be used
3502         in here to reverse '/'s into '\'s and vice-versa.  users
3503         would specify the lp_veto_files and lp_hide_files parameters
3504         in dos mode path format ('\' for directory separator), with a
3505         list separator of '/', and they would be swapped inside this
3506         function, before making the search.
3507
3508    */
3509
3510   while (*nameptr) 
3511     {
3512       if ( *nameptr == '/' ) 
3513       {
3514           /* cope with multiple (useless) /s) */
3515           nameptr++;
3516           continue;
3517       }
3518       /* find the next / */
3519       if ((name_end = strchr(nameptr,'/')) != NULL) 
3520       {
3521           *name_end = 0;
3522       }
3523
3524       /* look for a match. */
3525       if (mask_match(last_component, nameptr, case_sensitive, False))
3526       {
3527          DEBUG(5,("is_in_path: mask match succeeded\n"));
3528          return True;
3529       }
3530
3531       /* oops - the last check for a / didn't find one. */
3532       if (name_end == NULL)
3533       {
3534          DEBUG(5,("is_in_path: last name.  failed\n"));
3535          return False;
3536       }
3537
3538       /* next segment please */
3539       nameptr = name_end + 1;
3540     }
3541   
3542   DEBUG(5,("is_in_path: not found\n"));
3543
3544   return False;
3545 }
3546
3547 BOOL is_hidden_path(int snum, char *name)
3548 {
3549    return is_in_path(name, lp_hide_files(snum));
3550 }
3551
3552 BOOL is_vetoed_name(int snum, char *name)
3553 {
3554    return is_in_path(name, lp_veto_files(snum));
3555 }
3556
3557 /****************************************************************************
3558 routine to do file locking
3559 ****************************************************************************/
3560 BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type)
3561 {
3562 #if HAVE_FCNTL_LOCK
3563   struct flock lock;
3564   int ret;
3565
3566 #if 1
3567   uint32 mask = 0xC0000000;
3568
3569   /* make sure the count is reasonable, we might kill the lockd otherwise */
3570   count &= ~mask;
3571
3572   /* the offset is often strange - remove 2 of its bits if either of
3573      the top two bits are set. Shift the top ones by two bits. This
3574      still allows OLE2 apps to operate, but should stop lockd from
3575      dieing */
3576   if ((offset & mask) != 0)
3577     offset = (offset & ~mask) | ((offset & mask) >> 2);
3578 #else
3579   uint32 mask = ((unsigned)1<<31);
3580
3581   /* interpret negative counts as large numbers */
3582   if (count < 0)
3583     count &= ~mask;
3584
3585   /* no negative offsets */
3586   offset &= ~mask;
3587
3588   /* count + offset must be in range */
3589   while ((offset < 0 || (offset + count < 0)) && mask)
3590     {
3591       offset &= ~mask;
3592       mask = mask >> 1;
3593     }
3594 #endif
3595
3596
3597   DEBUG(5,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type));
3598
3599   lock.l_type = type;
3600   lock.l_whence = SEEK_SET;
3601   lock.l_start = (int)offset;
3602   lock.l_len = (int)count;
3603   lock.l_pid = 0;
3604
3605   errno = 0;
3606
3607   ret = fcntl(fd,op,&lock);
3608
3609   if (errno != 0)
3610     DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
3611
3612   /* a lock query */
3613   if (op == F_GETLK)
3614     {
3615       if ((ret != -1) &&
3616           (lock.l_type != F_UNLCK) && 
3617           (lock.l_pid != 0) && 
3618           (lock.l_pid != getpid()))
3619         {
3620           DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid));
3621           return(True);
3622         }
3623
3624       /* it must be not locked or locked by me */
3625       return(False);
3626     }
3627
3628   /* a lock set or unset */
3629   if (ret == -1)
3630     {
3631       DEBUG(3,("lock failed at offset %d count %d op %d type %d (%s)\n",
3632                offset,count,op,type,strerror(errno)));
3633
3634       /* perhaps it doesn't support this sort of locking?? */
3635       if (errno == EINVAL)
3636         {
3637           DEBUG(3,("locking not supported? returning True\n"));
3638           return(True);
3639         }
3640
3641       return(False);
3642     }
3643
3644   /* everything went OK */
3645   DEBUG(5,("Lock call successful\n"));
3646
3647   return(True);
3648 #else
3649   return(False);
3650 #endif
3651 }
3652
3653 /*******************************************************************
3654 lock a file - returning a open file descriptor or -1 on failure
3655 The timeout is in seconds. 0 means no timeout
3656 ********************************************************************/
3657 int file_lock(char *name,int timeout)
3658 {  
3659   int fd = open(name,O_RDWR|O_CREAT,0666);
3660   time_t t=0;
3661   if (fd < 0) return(-1);
3662
3663 #if HAVE_FCNTL_LOCK
3664   if (timeout) t = time(NULL);
3665   while (!timeout || (time(NULL)-t < timeout)) {
3666     if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)) return(fd);    
3667     msleep(LOCK_RETRY_TIMEOUT);
3668   }
3669   return(-1);
3670 #else
3671   return(fd);
3672 #endif
3673 }
3674
3675 /*******************************************************************
3676 unlock a file locked by file_lock
3677 ********************************************************************/
3678 void file_unlock(int fd)
3679 {
3680   if (fd<0) return;
3681 #if HAVE_FCNTL_LOCK
3682   fcntl_lock(fd,F_SETLK,0,1,F_UNLCK);
3683 #endif
3684   close(fd);
3685 }
3686
3687