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