b7ad0bb5bcef46b7066645d6d751c825f32b8993
[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
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
2541 #endif
2542 #endif
2543 }
2544
2545
2546 /****************************************************************************
2547 put up a yes/no prompt
2548 ****************************************************************************/
2549 BOOL yesno(char *p)
2550 {
2551   pstring ans;
2552   printf("%s",p);
2553
2554   if (!fgets(ans,sizeof(ans)-1,stdin))
2555     return(False);
2556
2557   if (*ans == 'y' || *ans == 'Y')
2558     return(True);
2559
2560   return(False);
2561 }
2562
2563 /****************************************************************************
2564 read a line from a file with possible \ continuation chars. 
2565 Blanks at the start or end of a line are stripped.
2566 The string will be allocated if s2 is NULL
2567 ****************************************************************************/
2568 char *fgets_slash(char *s2,int maxlen,FILE *f)
2569 {
2570   char *s=s2;
2571   int len = 0;
2572   int c;
2573   BOOL start_of_line = True;
2574
2575   if (feof(f))
2576     return(NULL);
2577
2578   if (!s2)
2579     {
2580       maxlen = MIN(maxlen,8);
2581       s = (char *)Realloc(s,maxlen);
2582     }
2583
2584   if (!s || maxlen < 2) return(NULL);
2585
2586   *s = 0;
2587
2588   while (len < maxlen-1)
2589     {
2590       c = getc(f);
2591       switch (c)
2592         {
2593         case '\r':
2594           break;
2595         case '\n':
2596           while (len > 0 && s[len-1] == ' ')
2597             {
2598               s[--len] = 0;
2599             }
2600           if (len > 0 && s[len-1] == '\\')
2601             {
2602               s[--len] = 0;
2603               start_of_line = True;
2604               break;
2605             }
2606           return(s);
2607         case EOF:
2608           if (len <= 0 && !s2) 
2609             free(s);
2610           return(len>0?s:NULL);
2611         case ' ':
2612           if (start_of_line)
2613             break;
2614         default:
2615           start_of_line = False;
2616           s[len++] = c;
2617           s[len] = 0;
2618         }
2619       if (!s2 && len > maxlen-3)
2620         {
2621           maxlen *= 2;
2622           s = (char *)Realloc(s,maxlen);
2623           if (!s) return(NULL);
2624         }
2625     }
2626   return(s);
2627 }
2628
2629
2630
2631 /****************************************************************************
2632 set the length of a file from a filedescriptor.
2633 Returns 0 on success, -1 on failure.
2634 ****************************************************************************/
2635 int set_filelen(int fd, long len)
2636 {
2637 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2638    extend a file with ftruncate. Provide alternate implementation
2639    for this */
2640
2641 #if FTRUNCATE_CAN_EXTEND
2642   return ftruncate(fd, len);
2643 #else
2644   struct stat st;
2645   char c = 0;
2646   long currpos = lseek(fd, 0L, SEEK_CUR);
2647
2648   if(currpos < 0)
2649     return -1;
2650   /* Do an fstat to see if the file is longer than
2651      the requested size (call ftruncate),
2652      or shorter, in which case seek to len - 1 and write 1
2653      byte of zero */
2654   if(fstat(fd, &st)<0)
2655     return -1;
2656
2657 #ifdef S_ISFIFO
2658   if (S_ISFIFO(st.st_mode)) return 0;
2659 #endif
2660
2661   if(st.st_size == len)
2662     return 0;
2663   if(st.st_size > len)
2664     return ftruncate(fd, len);
2665
2666   if(lseek(fd, len-1, SEEK_SET) != len -1)
2667     return -1;
2668   if(write(fd, &c, 1)!=1)
2669     return -1;
2670   /* Seek to where we were */
2671   lseek(fd, currpos, SEEK_SET);
2672   return 0;
2673 #endif
2674 }
2675
2676
2677 /****************************************************************************
2678 return the byte checksum of some data
2679 ****************************************************************************/
2680 int byte_checksum(char *buf,int len)
2681 {
2682   unsigned char *p = (unsigned char *)buf;
2683   int ret = 0;
2684   while (len--)
2685     ret += *p++;
2686   return(ret);
2687 }
2688
2689
2690
2691 #ifdef HPUX
2692 /****************************************************************************
2693 this is a version of setbuffer() for those machines that only have setvbuf
2694 ****************************************************************************/
2695  void setbuffer(FILE *f,char *buf,int bufsize)
2696 {
2697   setvbuf(f,buf,_IOFBF,bufsize);
2698 }
2699 #endif
2700
2701
2702 /****************************************************************************
2703 parse out a directory name from a path name. Assumes dos style filenames.
2704 ****************************************************************************/
2705 char *dirname_dos(char *path,char *buf)
2706 {
2707   char *p = strrchr(path,'\\');
2708
2709   if (!p)
2710     strcpy(buf,path);
2711   else
2712     {
2713       *p = 0;
2714       strcpy(buf,path);
2715       *p = '\\';
2716     }
2717
2718   return(buf);
2719 }
2720
2721
2722 /****************************************************************************
2723 parse out a filename from a path name. Assumes dos style filenames.
2724 ****************************************************************************/
2725 static char *filename_dos(char *path,char *buf)
2726 {
2727   char *p = strrchr(path,'\\');
2728
2729   if (!p)
2730     strcpy(buf,path);
2731   else
2732     strcpy(buf,p+1);
2733
2734   return(buf);
2735 }
2736
2737
2738
2739 /****************************************************************************
2740 expand a pointer to be a particular size
2741 ****************************************************************************/
2742 void *Realloc(void *p,int size)
2743 {
2744   void *ret=NULL;
2745
2746   if (size == 0) {
2747     if (p) free(p);
2748     DEBUG(5,("Realloc asked for 0 bytes\n"));
2749     return NULL;
2750   }
2751
2752   if (!p)
2753     ret = (void *)malloc(size);
2754   else
2755     ret = (void *)realloc(p,size);
2756
2757   if (!ret)
2758     DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",size));
2759
2760   return(ret);
2761 }
2762
2763 #ifdef NOSTRDUP
2764 /****************************************************************************
2765 duplicate a string
2766 ****************************************************************************/
2767  char *strdup(char *s)
2768 {
2769   char *ret = NULL;
2770   if (!s) return(NULL);
2771   ret = (char *)malloc(strlen(s)+1);
2772   if (!ret) return(NULL);
2773   strcpy(ret,s);
2774   return(ret);
2775 }
2776 #endif
2777
2778
2779 /****************************************************************************
2780   Signal handler for SIGPIPE (write on a disconnected socket) 
2781 ****************************************************************************/
2782 void Abort(void )
2783 {
2784   DEBUG(0,("Probably got SIGPIPE\nExiting\n"));
2785   exit(2);
2786 }
2787
2788 /****************************************************************************
2789 get my own name and IP
2790 ****************************************************************************/
2791 BOOL get_myname(char *my_name,struct in_addr *ip)
2792 {
2793   struct hostent *hp;
2794   pstring hostname;
2795
2796   *hostname = 0;
2797
2798   /* get my host name */
2799   if (gethostname(hostname, MAXHOSTNAMELEN) == -1) 
2800     {
2801       DEBUG(0,("gethostname failed\n"));
2802       return False;
2803     } 
2804
2805   /* get host info */
2806   if ((hp = Get_Hostbyname(hostname)) == 0) 
2807     {
2808       DEBUG(0,( "Get_Hostbyname: Unknown host %s.\n",hostname));
2809       return False;
2810     }
2811
2812   if (my_name)
2813     {
2814       /* split off any parts after an initial . */
2815       char *p = strchr(hostname,'.');
2816       if (p) *p = 0;
2817
2818       strcpy(my_name,hostname);
2819     }
2820
2821   if (ip)
2822     putip((char *)ip,(char *)hp->h_addr);
2823
2824   return(True);
2825 }
2826
2827
2828 /****************************************************************************
2829 true if two IP addresses are equal
2830 ****************************************************************************/
2831 BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
2832 {
2833   uint32 a1,a2;
2834   a1 = ntohl(ip1.s_addr);
2835   a2 = ntohl(ip2.s_addr);
2836   return(a1 == a2);
2837 }
2838
2839
2840 /****************************************************************************
2841 open a socket of the specified type, port and address for incoming data
2842 ****************************************************************************/
2843 int open_socket_in(int type, int port, int dlevel,uint32 socket_addr)
2844 {
2845   struct hostent *hp;
2846   struct sockaddr_in sock;
2847   pstring host_name;
2848   int res;
2849
2850   /* get my host name */
2851   if (gethostname(host_name, MAXHOSTNAMELEN) == -1) 
2852     { DEBUG(0,("gethostname failed\n")); return -1; } 
2853
2854   /* get host info */
2855   if ((hp = Get_Hostbyname(host_name)) == 0) 
2856     {
2857       DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",host_name));
2858       return -1;
2859     }
2860   
2861   bzero((char *)&sock,sizeof(sock));
2862   memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
2863 #if defined(__FreeBSD__) || defined(NETBSD) /* XXX not the right ifdef */
2864   sock.sin_len = sizeof(sock);
2865 #endif
2866   sock.sin_port = htons( port );
2867   sock.sin_family = hp->h_addrtype;
2868   sock.sin_addr.s_addr = socket_addr;
2869   res = socket(hp->h_addrtype, type, 0);
2870   if (res == -1) 
2871     { DEBUG(0,("socket failed\n")); return -1; }
2872
2873   {
2874     int one=1;
2875     setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
2876   }
2877
2878   /* now we've got a socket - we need to bind it */
2879   if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) 
2880     { 
2881       if (port) {
2882         if (port == SMB_PORT || port == NMB_PORT)
2883           DEBUG(dlevel,("bind failed on port %d socket_addr=%x (%s)\n",
2884                         port,socket_addr,strerror(errno))); 
2885         close(res); 
2886
2887         if (dlevel > 0 && port < 1000)
2888           port = 7999;
2889
2890         if (port >= 1000 && port < 9000)
2891           return(open_socket_in(type,port+1,dlevel,socket_addr));
2892       }
2893
2894       return(-1); 
2895     }
2896   DEBUG(3,("bind succeeded on port %d\n",port));
2897
2898   return res;
2899 }
2900
2901
2902 /****************************************************************************
2903   create an outgoing socket
2904   **************************************************************************/
2905 int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
2906 {
2907   struct sockaddr_in sock_out;
2908   int res,ret;
2909   int connect_loop = 250; /* 250 milliseconds */
2910   int loops = (timeout * 1000) / connect_loop;
2911
2912   /* create a socket to write to */
2913   res = socket(PF_INET, type, 0);
2914   if (res == -1) 
2915     { DEBUG(0,("socket error\n")); return -1; }
2916
2917   if (type != SOCK_STREAM) return(res);
2918   
2919   bzero((char *)&sock_out,sizeof(sock_out));
2920   putip((char *)&sock_out.sin_addr,(char *)addr);
2921   
2922   sock_out.sin_port = htons( port );
2923   sock_out.sin_family = PF_INET;
2924
2925   /* set it non-blocking */
2926   set_blocking(res,0);
2927
2928   DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port));
2929   
2930   /* and connect it to the destination */
2931 connect_again:
2932   ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out));
2933
2934   /* Some systems return EAGAIN when they mean EINPROGRESS */
2935   if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
2936         errno == EAGAIN) && loops--) {
2937     msleep(connect_loop);
2938     goto connect_again;
2939   }
2940
2941   if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
2942          errno == EAGAIN)) {
2943       DEBUG(1,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port));
2944       close(res);
2945       return -1;
2946   }
2947
2948 #ifdef EISCONN
2949   if (ret < 0 && errno == EISCONN) {
2950     errno = 0;
2951     ret = 0;
2952   }
2953 #endif
2954
2955   if (ret < 0) {
2956     DEBUG(1,("error connecting to %s:%d (%s)\n",
2957              inet_ntoa(*addr),port,strerror(errno)));
2958     return -1;
2959   }
2960
2961   /* set it blocking again */
2962   set_blocking(res,1);
2963
2964   return res;
2965 }
2966
2967
2968 /****************************************************************************
2969 interpret a protocol description string, with a default
2970 ****************************************************************************/
2971 int interpret_protocol(char *str,int def)
2972 {
2973   if (strequal(str,"NT1"))
2974     return(PROTOCOL_NT1);
2975   if (strequal(str,"LANMAN2"))
2976     return(PROTOCOL_LANMAN2);
2977   if (strequal(str,"LANMAN1"))
2978     return(PROTOCOL_LANMAN1);
2979   if (strequal(str,"CORE"))
2980     return(PROTOCOL_CORE);
2981   if (strequal(str,"COREPLUS"))
2982     return(PROTOCOL_COREPLUS);
2983   if (strequal(str,"CORE+"))
2984     return(PROTOCOL_COREPLUS);
2985   
2986   DEBUG(0,("Unrecognised protocol level %s\n",str));
2987   
2988   return(def);
2989 }
2990
2991 /****************************************************************************
2992 interpret a security level
2993 ****************************************************************************/
2994 int interpret_security(char *str,int def)
2995 {
2996   if (strequal(str,"SERVER"))
2997     return(SEC_SERVER);
2998   if (strequal(str,"USER"))
2999     return(SEC_USER);
3000   if (strequal(str,"SHARE"))
3001     return(SEC_SHARE);
3002   
3003   DEBUG(0,("Unrecognised security level %s\n",str));
3004   
3005   return(def);
3006 }
3007
3008
3009 /****************************************************************************
3010 interpret an internet address or name into an IP address in 4 byte form
3011 ****************************************************************************/
3012 uint32 interpret_addr(char *str)
3013 {
3014   struct hostent *hp;
3015   uint32 res;
3016   int i;
3017   BOOL pure_address = True;
3018
3019   if (strcmp(str,"0.0.0.0") == 0) return(0);
3020   if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
3021
3022   for (i=0; pure_address && str[i]; i++)
3023     if (!(isdigit(str[i]) || str[i] == '.')) 
3024       pure_address = False;
3025
3026   /* if it's in the form of an IP address then get the lib to interpret it */
3027   if (pure_address) {
3028     res = inet_addr(str);
3029   } else {
3030     /* otherwise assume it's a network name of some sort and use 
3031        Get_Hostbyname */
3032     if ((hp = Get_Hostbyname(str)) == 0) {
3033       DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
3034       return 0;
3035     }
3036     putip((char *)&res,(char *)hp->h_addr);
3037   }
3038
3039   if (res == (uint32)-1) return(0);
3040
3041   return(res);
3042 }
3043
3044 /*******************************************************************
3045   a convenient addition to interpret_addr()
3046   ******************************************************************/
3047 struct in_addr *interpret_addr2(char *str)
3048 {
3049   static struct in_addr ret;
3050   uint32 a = interpret_addr(str);
3051   ret.s_addr = a;
3052   return(&ret);
3053 }
3054
3055 /*******************************************************************
3056   check if an IP is the 0.0.0.0
3057   ******************************************************************/
3058 BOOL zero_ip(struct in_addr ip)
3059 {
3060   uint32 a;
3061   putip((char *)&a,(char *)&ip);
3062   return(a == 0);
3063 }
3064
3065
3066 /*******************************************************************
3067  matchname - determine if host name matches IP address 
3068  ******************************************************************/
3069 static BOOL matchname(char *remotehost,struct in_addr  addr)
3070 {
3071   struct hostent *hp;
3072   int     i;
3073   
3074   if ((hp = Get_Hostbyname(remotehost)) == 0) {
3075     DEBUG(0,("Get_Hostbyname(%s): lookup failure", remotehost));
3076     return False;
3077   } 
3078
3079   /*
3080    * Make sure that gethostbyname() returns the "correct" host name.
3081    * Unfortunately, gethostbyname("localhost") sometimes yields
3082    * "localhost.domain". Since the latter host name comes from the
3083    * local DNS, we just have to trust it (all bets are off if the local
3084    * DNS is perverted). We always check the address list, though.
3085    */
3086   
3087   if (strcasecmp(remotehost, hp->h_name)
3088       && strcasecmp(remotehost, "localhost")) {
3089     DEBUG(0,("host name/name mismatch: %s != %s",
3090              remotehost, hp->h_name));
3091     return False;
3092   }
3093         
3094   /* Look up the host address in the address list we just got. */
3095   for (i = 0; hp->h_addr_list[i]; i++) {
3096     if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
3097       return True;
3098   }
3099
3100   /*
3101    * The host name does not map to the original host address. Perhaps
3102    * someone has compromised a name server. More likely someone botched
3103    * it, but that could be dangerous, too.
3104    */
3105   
3106   DEBUG(0,("host name/address mismatch: %s != %s",
3107            inet_ntoa(addr), hp->h_name));
3108   return False;
3109 }
3110
3111 /*******************************************************************
3112  Reset the 'done' variables so after a client process is created
3113  from a fork call these calls will be re-done. This should be
3114  expanded if more variables need reseting.
3115  ******************************************************************/
3116
3117 static BOOL global_client_name_done = False;
3118 static BOOL global_client_addr_done = False;
3119
3120 void reset_globals_after_fork()
3121 {
3122   global_client_name_done = False;
3123   global_client_addr_done = False;
3124 }
3125  
3126 /*******************************************************************
3127  return the DNS name of the client 
3128  ******************************************************************/
3129 char *client_name(void)
3130 {
3131   extern int Client;
3132   struct sockaddr sa;
3133   struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
3134   int     length = sizeof(sa);
3135   static pstring name_buf;
3136   struct hostent *hp;
3137
3138   if (global_client_name_done) 
3139     return name_buf;
3140
3141   strcpy(name_buf,"UNKNOWN");
3142
3143   if (getpeername(Client, &sa, &length) < 0) {
3144     DEBUG(0,("getpeername failed\n"));
3145     return name_buf;
3146   }
3147
3148   /* Look up the remote host name. */
3149   if ((hp = gethostbyaddr((char *) &sockin->sin_addr,
3150                           sizeof(sockin->sin_addr),
3151                           AF_INET)) == 0) {
3152     DEBUG(1,("Gethostbyaddr failed for %s\n",client_addr()));
3153     StrnCpy(name_buf,client_addr(),sizeof(name_buf) - 1);
3154   } else {
3155     StrnCpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1);
3156     if (!matchname(name_buf, sockin->sin_addr)) {
3157       DEBUG(0,("Matchname failed on %s %s\n",name_buf,client_addr()));
3158       strcpy(name_buf,"UNKNOWN");
3159     }
3160   }
3161   global_client_name_done = True;
3162   return name_buf;
3163 }
3164
3165 /*******************************************************************
3166  return the IP addr of the client as a string 
3167  ******************************************************************/
3168 char *client_addr(void)
3169 {
3170   extern int Client;
3171   struct sockaddr sa;
3172   struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
3173   int     length = sizeof(sa);
3174   static fstring addr_buf;
3175
3176   if (global_client_addr_done) 
3177     return addr_buf;
3178
3179   strcpy(addr_buf,"0.0.0.0");
3180
3181   if (getpeername(Client, &sa, &length) < 0) {
3182     DEBUG(0,("getpeername failed\n"));
3183     return addr_buf;
3184   }
3185
3186   strcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr));
3187
3188   global_client_addr_done = True;
3189   return addr_buf;
3190 }
3191
3192 /*******************************************************************
3193 sub strings with useful parameters
3194 ********************************************************************/
3195 void standard_sub_basic(char *s)
3196 {
3197   if (!strchr(s,'%')) return;
3198
3199   string_sub(s,"%R",remote_proto);
3200   string_sub(s,"%a",remote_arch);
3201   string_sub(s,"%m",remote_machine);
3202   string_sub(s,"%L",local_machine);
3203
3204   if (!strchr(s,'%')) return;
3205
3206   string_sub(s,"%v",VERSION);
3207   string_sub(s,"%h",myhostname);
3208   string_sub(s,"%U",sesssetup_user);
3209
3210   if (!strchr(s,'%')) return;
3211
3212   string_sub(s,"%I",client_addr());
3213   if (strstr(s,"%M"))
3214     string_sub(s,"%M",client_name());
3215   string_sub(s,"%T",timestring());
3216
3217   if (!strchr(s,'%')) return;
3218
3219   {
3220     char pidstr[10];
3221     sprintf(pidstr,"%d",(int)getpid());
3222     string_sub(s,"%d",pidstr);
3223   }
3224
3225   if (!strchr(s,'%')) return;
3226
3227   {
3228     struct passwd *pass = Get_Pwnam(sesssetup_user,False);
3229     if (pass) {
3230       string_sub(s,"%G",gidtoname(pass->pw_gid));
3231     }
3232   }
3233 }
3234
3235
3236 /*******************************************************************
3237 are two IPs on the same subnet?
3238 ********************************************************************/
3239 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
3240 {
3241   uint32 net1,net2,nmask;
3242
3243   nmask = ntohl(mask.s_addr);
3244   net1  = ntohl(ip1.s_addr);
3245   net2  = ntohl(ip2.s_addr);
3246             
3247   return((net1 & nmask) == (net2 & nmask));
3248 }
3249
3250
3251 /*******************************************************************
3252 write a string in unicoode format
3253 ********************************************************************/
3254 int PutUniCode(char *dst,char *src)
3255 {
3256   int ret = 0;
3257   while (*src) {
3258     dst[ret++] = src[0];
3259     dst[ret++] = 0;    
3260     src++;
3261   }
3262   dst[ret++]=0;
3263   dst[ret++]=0;
3264   return(ret);
3265 }
3266
3267 /****************************************************************************
3268 a wrapper for gethostbyname() that tries with all lower and all upper case 
3269 if the initial name fails
3270 ****************************************************************************/
3271 struct hostent *Get_Hostbyname(char *name)
3272 {
3273   char *name2 = strdup(name);
3274   struct hostent *ret;
3275
3276   if (!name2)
3277     {
3278       DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
3279       exit(0);
3280     }
3281
3282   if (!isalnum(*name2))
3283     {
3284       free(name2);
3285       return(NULL);
3286     }
3287
3288   ret = sys_gethostbyname(name2);
3289   if (ret != NULL)
3290     {
3291       free(name2);
3292       return(ret);
3293     }
3294
3295   /* try with all lowercase */
3296   strlower(name2);
3297   ret = sys_gethostbyname(name2);
3298   if (ret != NULL)
3299     {
3300       free(name2);
3301       return(ret);
3302     }
3303
3304   /* try with all uppercase */
3305   strupper(name2);
3306   ret = sys_gethostbyname(name2);
3307   if (ret != NULL)
3308     {
3309       free(name2);
3310       return(ret);
3311     }
3312   
3313   /* nothing works :-( */
3314   free(name2);
3315   return(NULL);
3316 }
3317
3318
3319 /****************************************************************************
3320 check if a process exists. Does this work on all unixes?
3321 ****************************************************************************/
3322 BOOL process_exists(int pid)
3323 {
3324 #ifdef LINUX
3325   fstring s;
3326   sprintf(s,"/proc/%d",pid);
3327   return(directory_exist(s,NULL));
3328 #else
3329   {
3330     static BOOL tested=False;
3331     static BOOL ok=False;
3332     fstring s;
3333     if (!tested) {
3334       tested = True;
3335       sprintf(s,"/proc/%05d",(int)getpid());
3336       ok = file_exist(s,NULL);
3337     }
3338     if (ok) {
3339       sprintf(s,"/proc/%05d",pid);
3340       return(file_exist(s,NULL));
3341     }
3342   }
3343
3344   /* CGH 8/16/96 - added ESRCH test */
3345   return(pid == getpid() || kill(pid,0) == 0 || errno != ESRCH);
3346 #endif
3347 }
3348
3349
3350 /*******************************************************************
3351 turn a uid into a user name
3352 ********************************************************************/
3353 char *uidtoname(int uid)
3354 {
3355   static char name[40];
3356   struct passwd *pass = getpwuid(uid);
3357   if (pass) return(pass->pw_name);
3358   sprintf(name,"%d",uid);
3359   return(name);
3360 }
3361
3362 /*******************************************************************
3363 turn a gid into a group name
3364 ********************************************************************/
3365 char *gidtoname(int gid)
3366 {
3367   static char name[40];
3368   struct group *grp = getgrgid(gid);
3369   if (grp) return(grp->gr_name);
3370   sprintf(name,"%d",gid);
3371   return(name);
3372 }
3373
3374 /*******************************************************************
3375 block sigs
3376 ********************************************************************/
3377 void BlockSignals(BOOL block,int signum)
3378 {
3379 #ifdef USE_SIGBLOCK
3380   int block_mask = sigmask(signum);
3381   static int oldmask = 0;
3382   if (block) 
3383     oldmask = sigblock(block_mask);
3384   else
3385     sigsetmask(oldmask);
3386 #elif defined(USE_SIGPROCMASK)
3387   sigset_t set;
3388   sigemptyset(&set);
3389   sigaddset(&set,signum);
3390   sigprocmask(block?SIG_BLOCK:SIG_UNBLOCK,&set,NULL);
3391 #endif
3392 }
3393
3394 #if AJT
3395 /*******************************************************************
3396 my own panic function - not suitable for general use
3397 ********************************************************************/
3398 void ajt_panic(void)
3399 {
3400   system("/usr/bin/X11/xedit -display ljus:0 /tmp/ERROR_FAULT");
3401 }
3402 #endif
3403
3404 #ifdef USE_DIRECT
3405 #define DIRECT direct
3406 #else
3407 #define DIRECT dirent
3408 #endif
3409
3410 /*******************************************************************
3411 a readdir wrapper which just returns the file name
3412 also return the inode number if requested
3413 ********************************************************************/
3414 char *readdirname(void *p)
3415 {
3416   struct DIRECT *ptr;
3417   char *dname;
3418
3419   if (!p) return(NULL);
3420   
3421   ptr = (struct DIRECT *)readdir(p);
3422   if (!ptr) return(NULL);
3423
3424   dname = ptr->d_name;
3425
3426 #ifdef NEXT2
3427   if (telldir(p) < 0) return(NULL);
3428 #endif
3429
3430 #ifdef SUNOS5
3431   /* this handles a broken compiler setup, causing a mixture
3432    of BSD and SYSV headers and libraries */
3433   {
3434     static BOOL broken_readdir = False;
3435     if (!broken_readdir && !(*(dname)) && strequal("..",dname-2))
3436       {
3437         DEBUG(0,("Your readdir() is broken. You have somehow mixed SYSV and BSD headers and libraries\n"));
3438         broken_readdir = True;
3439       }
3440     if (broken_readdir)
3441       dname = dname - 2;
3442   }
3443 #endif
3444
3445   {
3446     static pstring buf;
3447     strcpy(buf, dname);
3448     unix_to_dos(buf, True);
3449     dname = buf;
3450   }
3451
3452   return(dname);
3453 }
3454
3455 /*
3456  * Utility function used by is_hidden_path() and is_vetoed_name()
3457  * to decide if the last component of a path matches a (possibly
3458  * wildcarded) entry in a namelist.
3459  */
3460
3461 static BOOL is_in_path(char *name, char *namelist)
3462 {
3463   pstring last_component;
3464   char *p;
3465   char *nameptr = namelist;
3466   char *name_end;
3467
3468   DEBUG(5, ("is_in_path: %s list: %s\n", name, namelist));
3469
3470   /* if we have no list it's obviously not in the path */
3471   if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0'))) 
3472   {
3473     DEBUG(5,("is_in_path: no name list.  return False\n"));
3474     return False;
3475   }
3476
3477   /* Get the last component of the unix name. */
3478   p = strrchr(name, '/');
3479   strncpy(last_component, p ? p : name, sizeof(last_component)-1);
3480   last_component[sizeof(last_component)-1] = '\0'; 
3481
3482   /* now, we need to find the names one by one and check them
3483      they can contain spaces and all sorts of stuff so we
3484      separate them with of all things '\' which can never be in a filename
3485      I could use "" but then I have to break them all out
3486      maybe such a routine exists somewhere?
3487   */
3488  
3489   /* lkcl 03jul97 - the separator character used to be a '/'.
3490      i changed it to a '\', after examining the code, and seeing
3491      that unix_convert is called before check_path and dos_mode.
3492      unix_convert changes, in the path, all dos '\'s to unix '/'s.
3493
3494      the alternatives are:
3495
3496      1) move all check_path and dos_mode calls to before the
3497         unix_convert calls.
3498
3499      2) have a corresponding dos_convert call, which can be used
3500         in here to reverse '/'s into '\'s and vice-versa.  users
3501         would specify the lp_veto_files and lp_hide_files parameters
3502         in dos mode path format ('\' for directory separator), with a
3503         list separator of '/', and they would be swapped inside this
3504         function, before making the search.
3505
3506    */
3507
3508   while (*nameptr) 
3509     {
3510       if ( *nameptr == '\\' ) 
3511       {
3512           /* cope with multiple (useless) \s) */
3513           nameptr++;
3514           continue;
3515       }
3516       /* find the next \ */
3517       if ((name_end = strchr(nameptr,'\\')) != NULL) 
3518       {
3519           *name_end = 0;
3520       }
3521
3522       /* look for a match. */
3523       if (mask_match(last_component, nameptr, case_sensitive, False))
3524       {
3525          DEBUG(5,("is_in_path: mask match succeeded\n"));
3526          return True;
3527       }
3528
3529       /* oops - the last check for a \ didn't find one. */
3530       if (name_end == NULL)
3531       {
3532          DEBUG(5,("is_in_path: last name.  failed\n"));
3533          return False;
3534       }
3535
3536       /* next segment please */
3537       nameptr = name_end + 1;
3538     }
3539   
3540   DEBUG(5,("is_in_path: not found\n"));
3541
3542   return False;
3543 }
3544
3545 BOOL is_hidden_path(int snum, char *name)
3546 {
3547    return is_in_path(name, lp_hide_files(snum));
3548 }
3549
3550 BOOL is_vetoed_name(int snum, char *name)
3551 {
3552    return is_in_path(name, lp_veto_files(snum));
3553 }
3554
3555 /****************************************************************************
3556 routine to do file locking
3557 ****************************************************************************/
3558 BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type)
3559 {
3560 #if HAVE_FCNTL_LOCK
3561   struct flock lock;
3562   int ret;
3563
3564 #if 1
3565   uint32 mask = 0xC0000000;
3566
3567   /* make sure the count is reasonable, we might kill the lockd otherwise */
3568   count &= ~mask;
3569
3570   /* the offset is often strange - remove 2 of its bits if either of
3571      the top two bits are set. Shift the top ones by two bits. This
3572      still allows OLE2 apps to operate, but should stop lockd from
3573      dieing */
3574   if ((offset & mask) != 0)
3575     offset = (offset & ~mask) | ((offset & mask) >> 2);
3576 #else
3577   uint32 mask = ((unsigned)1<<31);
3578
3579   /* interpret negative counts as large numbers */
3580   if (count < 0)
3581     count &= ~mask;
3582
3583   /* no negative offsets */
3584   offset &= ~mask;
3585
3586   /* count + offset must be in range */
3587   while ((offset < 0 || (offset + count < 0)) && mask)
3588     {
3589       offset &= ~mask;
3590       mask = mask >> 1;
3591     }
3592 #endif
3593
3594
3595   DEBUG(5,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type));
3596
3597   lock.l_type = type;
3598   lock.l_whence = SEEK_SET;
3599   lock.l_start = (int)offset;
3600   lock.l_len = (int)count;
3601   lock.l_pid = 0;
3602
3603   errno = 0;
3604
3605   ret = fcntl(fd,op,&lock);
3606
3607   if (errno != 0)
3608     DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
3609
3610   /* a lock query */
3611   if (op == F_GETLK)
3612     {
3613       if ((ret != -1) &&
3614           (lock.l_type != F_UNLCK) && 
3615           (lock.l_pid != 0) && 
3616           (lock.l_pid != getpid()))
3617         {
3618           DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid));
3619           return(True);
3620         }
3621
3622       /* it must be not locked or locked by me */
3623       return(False);
3624     }
3625
3626   /* a lock set or unset */
3627   if (ret == -1)
3628     {
3629       DEBUG(3,("lock failed at offset %d count %d op %d type %d (%s)\n",
3630                offset,count,op,type,strerror(errno)));
3631
3632       /* perhaps it doesn't support this sort of locking?? */
3633       if (errno == EINVAL)
3634         {
3635           DEBUG(3,("locking not supported? returning True\n"));
3636           return(True);
3637         }
3638
3639       return(False);
3640     }
3641
3642   /* everything went OK */
3643   DEBUG(5,("Lock call successful\n"));
3644
3645   return(True);
3646 #else
3647   return(False);
3648 #endif
3649 }
3650
3651 /*******************************************************************
3652 lock a file - returning a open file descriptor or -1 on failure
3653 The timeout is in seconds. 0 means no timeout
3654 ********************************************************************/
3655 int file_lock(char *name,int timeout)
3656 {  
3657   int fd = open(name,O_RDWR|O_CREAT,0666);
3658   time_t t=0;
3659   if (fd < 0) return(-1);
3660
3661 #if HAVE_FCNTL_LOCK
3662   if (timeout) t = time(NULL);
3663   while (!timeout || (time(NULL)-t < timeout)) {
3664     if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)) return(fd);    
3665     msleep(LOCK_RETRY_TIMEOUT);
3666   }
3667   return(-1);
3668 #else
3669   return(fd);
3670 #endif
3671 }
3672
3673 /*******************************************************************
3674 unlock a file locked by file_lock
3675 ********************************************************************/
3676 void file_unlock(int fd)
3677 {
3678   if (fd<0) return;
3679 #if HAVE_FCNTL_LOCK
3680   fcntl_lock(fd,F_SETLK,0,1,F_UNLCK);
3681 #endif
3682   close(fd);
3683 }
3684
3685