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