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