1/*
2   Unix SMB/Netbios implementation.
3   Version 1.9.
4   Samba utility functions
5   Copyright (C) Andrew Tridgell 1992-1998
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#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
25#ifdef WITH_NISPLUS_HOME
26#ifdef BROKEN_NISPLUS_INCLUDE_FILES
27/*
28 * The following lines are needed due to buggy include files
29 * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
30 * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
31 * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
32 * an enum in /usr/include/rpcsvc/nis.h.
33 */
34
35#if defined(GROUP)
36#undef GROUP
37#endif
38
39#if defined(GROUP_OBJ)
40#undef GROUP_OBJ
41#endif
42
43#endif /* BROKEN_NISPLUS_INCLUDE_FILES */
44
45#include <rpcsvc/nis.h>
46
47#else /* !WITH_NISPLUS_HOME */
48
49#include "rpcsvc/ypclnt.h"
50
51#endif /* WITH_NISPLUS_HOME */
52#endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
53
54#ifdef WITH_SSL
55#include <ssl.h>
56#undef Realloc  /* SSLeay defines this and samba has a function of this name */
57extern SSL  *ssl;
58extern int  sslFd;
59#endif  /* WITH_SSL */
60
61extern int DEBUGLEVEL;
62
63int Protocol = PROTOCOL_COREPLUS;
64
65/* a default finfo structure to ensure all fields are sensible */
66file_info def_finfo = {-1,0,0,0,0,0,0,""};
67
68/* the client file descriptor */
69extern int Client;
70
71/* this is used by the chaining code */
72int chain_size = 0;
73
74int trans_num = 0;
75
76/*
77   case handling on filenames
78*/
79int case_default = CASE_LOWER;
80
81/* the following control case operations - they are put here so the
82   client can link easily */
83BOOL case_sensitive;
84BOOL case_preserve;
85BOOL use_mangled_map = False;
86BOOL short_case_preserve;
87BOOL case_mangle;
88
89fstring remote_machine="";
90fstring local_machine="";
91fstring remote_arch="UNKNOWN";
92static enum remote_arch_types ra_type = RA_UNKNOWN;
93fstring remote_proto="UNKNOWN";
94pstring user_socket_options=DEFAULT_SOCKET_OPTIONS;
95
96pstring sesssetup_user="";
97pstring samlogon_user="";
98
99BOOL sam_logon_in_ssb = False;
100
101pstring global_myname = "";
102fstring global_myworkgroup = "";
103char **my_netbios_names;
104
105static char *filename_dos(char *path,char *buf);
106
107
108
109/****************************************************************************
110  find a suitable temporary directory. The result should be copied immediately
111  as it may be overwritten by a subsequent call
112  ****************************************************************************/
113char *tmpdir(void)
114{
115  char *p;
116  if ((p = getenv("TMPDIR"))) {
117    return p;
118  }
119  return "/tmp";
120}
121
122/****************************************************************************
123determine whether we are in the specified group
124****************************************************************************/
125
126BOOL in_group(gid_t group, gid_t current_gid, int ngroups, gid_t *groups)
127{
128	int i;
129
130	if (group == current_gid) return(True);
131
132	for (i=0;i<ngroups;i++)
133		if (group == groups[i])
134			return(True);
135
136	return(False);
137}
138
139
140/****************************************************************************
141like atoi but gets the value up to the separater character
142****************************************************************************/
143char *Atoic(char *p, int *n, char *c)
144{
145	if (!isdigit((int)*p))
146	{
147		DEBUG(5, ("Atoic: malformed number\n"));
148		return NULL;
149	}
150
151	(*n) = atoi(p);
152
153	while ((*p) && isdigit((int)*p))
154	{
155		p++;
156	}
157
158	if (strchr(c, *p) == NULL)
159	{
160		DEBUG(5, ("Atoic: no separator characters (%s) not found\n", c));
161		return NULL;
162	}
163
164	return p;
165}
166
167/*************************************************************************
168 reads a list of numbers
169 *************************************************************************/
170char *get_numlist(char *p, uint32 **num, int *count)
171{
172	int val;
173
174	if (num == NULL || count == NULL)
175	{
176		return NULL;
177	}
178
179	(*count) = 0;
180	(*num  ) = NULL;
181
182	while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':')
183	{
184		(*num) = Realloc((*num), ((*count)+1) * sizeof(uint32));
185		if ((*num) == NULL)
186		{
187			return NULL;
188		}
189		(*num)[(*count)] = val;
190		(*count)++;
191		p++;
192	}
193
194	return p;
195}
196
197#define TRUNCATE_NETBIOS_NAME 1
198
199/*******************************************************************
200 convert, possibly using a stupid microsoft-ism which has destroyed
201 the transport independence of netbios (for CIFS vendors that usually
202 use the Win95-type methods, not for NT to NT communication, which uses
203 DCE/RPC and therefore full-length unicode strings...) a dns name into
204 a netbios name.
205
206 the netbios name (NOT necessarily null-terminated) is truncated to 15
207 characters.
208
209 ******************************************************************/
210char *dns_to_netbios_name(char *dns_name)
211{
212	static char netbios_name[16];
213	int i;
214	StrnCpy(netbios_name, dns_name, 15);
215	netbios_name[15] = 0;
216
217#ifdef TRUNCATE_NETBIOS_NAME
218	/* ok.  this is because of a stupid microsoft-ism.  if the called host
219	   name contains a '.', microsoft clients expect you to truncate the
220	   netbios name up to and including the '.'  this even applies, by
221	   mistake, to workgroup (domain) names, which is _really_ daft.
222	 */
223	for (i = 15; i >= 0; i--)
224	{
225		if (netbios_name[i] == '.')
226		{
227			netbios_name[i] = 0;
228			break;
229		}
230	}
231#endif /* TRUNCATE_NETBIOS_NAME */
232
233	return netbios_name;
234}
235
236
237/****************************************************************************
238interpret the weird netbios "name". Return the name type
239****************************************************************************/
240static int name_interpret(char *in,char *out)
241{
242  int ret;
243  int len = (*in++) / 2;
244
245  *out=0;
246
247  if (len > 30 || len<1) return(0);
248
249  while (len--)
250    {
251      if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
252	*out = 0;
253	return(0);
254      }
255      *out = ((in[0]-'A')<<4) + (in[1]-'A');
256      in += 2;
257      out++;
258    }
259  *out = 0;
260  ret = out[-1];
261
262#ifdef NETBIOS_SCOPE
263  /* Handle any scope names */
264  while(*in)
265    {
266      *out++ = '.'; /* Scope names are separated by periods */
267      len = *(unsigned char *)in++;
268      StrnCpy(out, in, len);
269      out += len;
270      *out=0;
271      in += len;
272    }
273#endif
274  return(ret);
275}
276
277/****************************************************************************
278mangle a name into netbios format
279
280  Note:  <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
281****************************************************************************/
282int name_mangle( char *In, char *Out, char name_type )
283  {
284  int   i;
285  int   c;
286  int   len;
287  char  buf[20];
288  char *p = Out;
289  extern pstring global_scope;
290
291  /* Safely copy the input string, In, into buf[]. */
292  (void)memset( buf, 0, 20 );
293  if (strcmp(In,"*") == 0)
294    buf[0] = '*';
295  else
296    (void)slprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, name_type );
297
298  /* Place the length of the first field into the output buffer. */
299  p[0] = 32;
300  p++;
301
302  /* Now convert the name to the rfc1001/1002 format. */
303  for( i = 0; i < 16; i++ )
304    {
305    c = toupper( buf[i] );
306    p[i*2]     = ( (c >> 4) & 0x000F ) + 'A';
307    p[(i*2)+1] = (c & 0x000F) + 'A';
308    }
309  p += 32;
310  p[0] = '\0';
311
312  /* Add the scope string. */
313  for( i = 0, len = 0; NULL != global_scope; i++, len++ )
314    {
315    switch( global_scope[i] )
316      {
317      case '\0':
318        p[0]     = len;
319        if( len > 0 )
320          p[len+1] = 0;
321        return( name_len(Out) );
322      case '.':
323        p[0] = len;
324        p   += (len + 1);
325        len  = -1;
326        break;
327      default:
328        p[len+1] = global_scope[i];
329        break;
330      }
331    }
332
333  return( name_len(Out) );
334  } /* name_mangle */
335
336/*******************************************************************
337  check if a file exists
338********************************************************************/
339BOOL file_exist(char *fname,SMB_STRUCT_STAT *sbuf)
340{
341  SMB_STRUCT_STAT st;
342  if (!sbuf) sbuf = &st;
343
344  if (sys_stat(fname,sbuf) != 0)
345    return(False);
346
347  return(S_ISREG(sbuf->st_mode));
348}
349
350/*******************************************************************
351check a files mod time
352********************************************************************/
353time_t file_modtime(char *fname)
354{
355  SMB_STRUCT_STAT st;
356
357  if (sys_stat(fname,&st) != 0)
358    return(0);
359
360  return(st.st_mtime);
361}
362
363/*******************************************************************
364  check if a directory exists
365********************************************************************/
366BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st)
367{
368  SMB_STRUCT_STAT st2;
369  BOOL ret;
370
371  if (!st) st = &st2;
372
373  if (sys_stat(dname,st) != 0)
374    return(False);
375
376  ret = S_ISDIR(st->st_mode);
377  if(!ret)
378    errno = ENOTDIR;
379  return ret;
380}
381
382/*******************************************************************
383returns the size in bytes of the named file
384********************************************************************/
385SMB_OFF_T get_file_size(char *file_name)
386{
387  SMB_STRUCT_STAT buf;
388  buf.st_size = 0;
389  if(sys_stat(file_name,&buf) != 0)
390    return (SMB_OFF_T)-1;
391  return(buf.st_size);
392}
393
394/*******************************************************************
395return a string representing an attribute for a file
396********************************************************************/
397char *attrib_string(uint16 mode)
398{
399  static fstring attrstr;
400
401  attrstr[0] = 0;
402
403  if (mode & aVOLID) fstrcat(attrstr,"V");
404  if (mode & aDIR) fstrcat(attrstr,"D");
405  if (mode & aARCH) fstrcat(attrstr,"A");
406  if (mode & aHIDDEN) fstrcat(attrstr,"H");
407  if (mode & aSYSTEM) fstrcat(attrstr,"S");
408  if (mode & aRONLY) fstrcat(attrstr,"R");
409
410  return(attrstr);
411}
412
413/*******************************************************************
414  show a smb message structure
415********************************************************************/
416void show_msg(char *buf)
417{
418	int i;
419	int bcc=0;
420
421	if (DEBUGLEVEL < 5) return;
422
423	DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
424			smb_len(buf),
425			(int)CVAL(buf,smb_com),
426			(int)CVAL(buf,smb_rcls),
427			(int)CVAL(buf,smb_reh),
428			(int)SVAL(buf,smb_err),
429			(int)CVAL(buf,smb_flg),
430			(int)SVAL(buf,smb_flg2)));
431	DEBUG(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n",
432			(int)SVAL(buf,smb_tid),
433			(int)SVAL(buf,smb_pid),
434			(int)SVAL(buf,smb_uid),
435			(int)SVAL(buf,smb_mid),
436			(int)CVAL(buf,smb_wct)));
437
438	for (i=0;i<(int)CVAL(buf,smb_wct);i++)
439	{
440		DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i,
441			SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
442	}
443
444	bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
445
446	DEBUG(5,("smb_bcc=%d\n",bcc));
447
448	if (DEBUGLEVEL < 10) return;
449
450	if (DEBUGLEVEL < 50)
451	{
452		bcc = MIN(bcc, 512);
453	}
454
455	dump_data(10, smb_buf(buf), bcc);
456}
457
458/*******************************************************************
459  set the length and marker of an smb packet
460********************************************************************/
461void smb_setlen(char *buf,int len)
462{
463  _smb_setlen(buf,len);
464
465  CVAL(buf,4) = 0xFF;
466  CVAL(buf,5) = 'S';
467  CVAL(buf,6) = 'M';
468  CVAL(buf,7) = 'B';
469}
470
471/*******************************************************************
472  setup the word count and byte count for a smb message
473********************************************************************/
474int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
475{
476  if (zero)
477    memset(buf + smb_size,'\0',num_words*2 + num_bytes);
478  CVAL(buf,smb_wct) = num_words;
479  SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
480  smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
481  return (smb_size + num_words*2 + num_bytes);
482}
483
484/*******************************************************************
485reduce a file name, removing .. elements.
486********************************************************************/
487void dos_clean_name(char *s)
488{
489  char *p=NULL;
490
491  DEBUG(3,("dos_clean_name [%s]\n",s));
492
493  /* remove any double slashes */
494  all_string_sub(s, "\\\\", "\\", 0);
495
496  while ((p = strstr(s,"\\..\\")) != NULL)
497    {
498      pstring s1;
499
500      *p = 0;
501      pstrcpy(s1,p+3);
502
503      if ((p=strrchr(s,'\\')) != NULL)
504	*p = 0;
505      else
506	*s = 0;
507      pstrcat(s,s1);
508    }
509
510  trim_string(s,NULL,"\\..");
511
512  all_string_sub(s, "\\.\\", "\\", 0);
513}
514
515/*******************************************************************
516reduce a file name, removing .. elements.
517********************************************************************/
518void unix_clean_name(char *s)
519{
520  char *p=NULL;
521
522  DEBUG(3,("unix_clean_name [%s]\n",s));
523
524  /* remove any double slashes */
525  all_string_sub(s, "//","/", 0);
526
527  /* Remove leading ./ characters */
528  if(strncmp(s, "./", 2) == 0) {
529    trim_string(s, "./", NULL);
530    if(*s == 0)
531      pstrcpy(s,"./");
532  }
533
534  while ((p = strstr(s,"/../")) != NULL)
535    {
536      pstring s1;
537
538      *p = 0;
539      pstrcpy(s1,p+3);
540
541      if ((p=strrchr(s,'/')) != NULL)
542	*p = 0;
543      else
544	*s = 0;
545      pstrcat(s,s1);
546    }
547
548  trim_string(s,NULL,"/..");
549}
550
551/*******************************************************************
552reduce a file name, removing .. elements and checking that
553it is below dir in the heirachy. This uses dos_GetWd() and so must be run
554on the system that has the referenced file system.
555
556widelinks are allowed if widelinks is true
557********************************************************************/
558
559BOOL reduce_name(char *s,char *dir,BOOL widelinks)
560{
561#ifndef REDUCE_PATHS
562  return True;
563#else
564  pstring dir2;
565  pstring wd;
566  pstring base_name;
567  pstring newname;
568  char *p=NULL;
569  BOOL relative = (*s != '/');
570
571  *dir2 = *wd = *base_name = *newname = 0;
572
573  if (widelinks)
574  {
575    unix_clean_name(s);
576    /* can't have a leading .. */
577    if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
578    {
579      DEBUG(3,("Illegal file name? (%s)\n",s));
580      return(False);
581    }
582
583    if (strlen(s) == 0)
584      pstrcpy(s,"./");
585
586    return(True);
587  }
588
589  DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
590
591  /* remove any double slashes */
592  all_string_sub(s,"//","/",0);
593
594  pstrcpy(base_name,s);
595  p = strrchr(base_name,'/');
596
597  if (!p)
598    return(True);
599
600  if (!dos_GetWd(wd))
601  {
602    DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
603    return(False);
604  }
605
606  if (dos_ChDir(dir) != 0)
607  {
608    DEBUG(0,("couldn't chdir to %s\n",dir));
609    return(False);
610  }
611
612  if (!dos_GetWd(dir2))
613  {
614    DEBUG(0,("couldn't getwd for %s\n",dir));
615    dos_ChDir(wd);
616    return(False);
617  }
618
619  if (p && (p != base_name))
620  {
621    *p = 0;
622    if (strcmp(p+1,".")==0)
623      p[1]=0;
624    if (strcmp(p+1,"..")==0)
625      *p = '/';
626  }
627
628  if (dos_ChDir(base_name) != 0)
629  {
630    dos_ChDir(wd);
631    DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name));
632    return(False);
633  }
634
635  if (!dos_GetWd(newname))
636  {
637    dos_ChDir(wd);
638    DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
639    return(False);
640  }
641
642  if (p && (p != base_name))
643  {
644    pstrcat(newname,"/");
645    pstrcat(newname,p+1);
646  }
647
648  {
649    size_t l = strlen(dir2);
650    if (dir2[l-1] == '/')
651      l--;
652
653    if (strncmp(newname,dir2,l) != 0)
654    {
655      dos_ChDir(wd);
656      DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,(int)l));
657      return(False);
658    }
659
660    if (relative)
661    {
662      if (newname[l] == '/')
663        pstrcpy(s,newname + l + 1);
664      else
665        pstrcpy(s,newname+l);
666    }
667    else
668      pstrcpy(s,newname);
669  }
670
671  dos_ChDir(wd);
672
673  if (strlen(s) == 0)
674    pstrcpy(s,"./");
675
676  DEBUG(3,("reduced to %s\n",s));
677  return(True);
678#endif
679}
680
681/****************************************************************************
682expand some *s
683****************************************************************************/
684static void expand_one(char *Mask,int len)
685{
686  char *p1;
687  while ((p1 = strchr(Mask,'*')) != NULL)
688    {
689      int lfill = (len+1) - strlen(Mask);
690      int l1= (p1 - Mask);
691      pstring tmp;
692      pstrcpy(tmp,Mask);
693      memset(tmp+l1,'?',lfill);
694      pstrcpy(tmp + l1 + lfill,Mask + l1 + 1);
695      pstrcpy(Mask,tmp);
696    }
697}
698
699/****************************************************************************
700expand a wildcard expression, replacing *s with ?s
701****************************************************************************/
702void expand_mask(char *Mask,BOOL doext)
703{
704  pstring mbeg,mext;
705  pstring dirpart;
706  pstring filepart;
707  BOOL hasdot = False;
708  char *p1;
709  BOOL absolute = (*Mask == '\\');
710
711  *mbeg = *mext = *dirpart = *filepart = 0;
712
713  /* parse the directory and filename */
714  if (strchr(Mask,'\\'))
715    split_at_last_component(Mask,dirpart,'\\',NULL);
716
717  filename_dos(Mask,filepart);
718
719  pstrcpy(mbeg,filepart);
720  if ((p1 = strchr(mbeg,'.')) != NULL)
721    {
722      hasdot = True;
723      *p1 = 0;
724      p1++;
725      pstrcpy(mext,p1);
726    }
727  else
728    {
729      pstrcpy(mext,"");
730      if (strlen(mbeg) > 8)
731	{
732	  pstrcpy(mext,mbeg + 8);
733	  mbeg[8] = 0;
734	}
735    }
736
737  if (*mbeg == 0)
738    pstrcpy(mbeg,"????????");
739  if ((*mext == 0) && doext && !hasdot)
740    pstrcpy(mext,"???");
741
742  if (strequal(mbeg,"*") && *mext==0)
743    pstrcpy(mext,"*");
744
745  /* expand *'s */
746  expand_one(mbeg,8);
747  if (*mext)
748    expand_one(mext,3);
749
750  pstrcpy(Mask,dirpart);
751  if (*dirpart || absolute) pstrcat(Mask,"\\");
752  pstrcat(Mask,mbeg);
753  pstrcat(Mask,".");
754  pstrcat(Mask,mext);
755
756  DEBUG(6,("Mask expanded to [%s]\n",Mask));
757}
758
759
760
761/****************************************************************************
762  make a dir struct
763****************************************************************************/
764void make_dir_struct(char *buf,char *mask,char *fname,SMB_OFF_T size,int mode,time_t date)
765{
766  char *p;
767  pstring mask2;
768
769  pstrcpy(mask2,mask);
770
771  if ((mode & aDIR) != 0)
772    size = 0;
773
774  memset(buf+1,' ',11);
775  if ((p = strchr(mask2,'.')) != NULL)
776    {
777      *p = 0;
778      memcpy(buf+1,mask2,MIN(strlen(mask2),8));
779      memcpy(buf+9,p+1,MIN(strlen(p+1),3));
780      *p = '.';
781    }
782  else
783    memcpy(buf+1,mask2,MIN(strlen(mask2),11));
784
785  memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
786  CVAL(buf,21) = mode;
787  put_dos_date(buf,22,date);
788  SSVAL(buf,26,size & 0xFFFF);
789  SSVAL(buf,28,(size >> 16)&0xFFFF);
790  StrnCpy(buf+30,fname,12);
791  if (!case_sensitive)
792    strupper(buf+30);
793  DEBUG(8,("put name [%s] into dir struct\n",buf+30));
794}
795
796
797/*******************************************************************
798close the low 3 fd's and open dev/null in their place
799********************************************************************/
800void close_low_fds(void)
801{
802  int fd;
803  int i;
804  close(0); close(1); close(2);
805  /* try and use up these file descriptors, so silly
806     library routines writing to stdout etc won't cause havoc */
807  for (i=0;i<3;i++) {
808    fd = sys_open("/dev/null",O_RDWR,0);
809    if (fd < 0) fd = sys_open("/dev/null",O_WRONLY,0);
810    if (fd < 0) {
811      DEBUG(0,("Can't open /dev/null\n"));
812      return;
813    }
814    if (fd != i) {
815      DEBUG(0,("Didn't get file descriptor %d\n",i));
816      return;
817    }
818  }
819}
820
821/****************************************************************************
822Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
823else
824if SYSV use O_NDELAY
825if BSD use FNDELAY
826****************************************************************************/
827int set_blocking(int fd, BOOL set)
828{
829  int val;
830#ifdef O_NONBLOCK
831#define FLAG_TO_SET O_NONBLOCK
832#else
833#ifdef SYSV
834#define FLAG_TO_SET O_NDELAY
835#else /* BSD */
836#define FLAG_TO_SET FNDELAY
837#endif
838#endif
839
840  if((val = fcntl(fd, F_GETFL, 0)) == -1)
841	return -1;
842  if(set) /* Turn blocking on - ie. clear nonblock flag */
843	val &= ~FLAG_TO_SET;
844  else
845    val |= FLAG_TO_SET;
846  return fcntl( fd, F_SETFL, val);
847#undef FLAG_TO_SET
848}
849
850/****************************************************************************
851transfer some data between two fd's
852****************************************************************************/
853SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n,char *header,int headlen,int align)
854{
855  static char *buf=NULL;
856  static int size=0;
857  char *buf1,*abuf;
858  SMB_OFF_T total = 0;
859
860  DEBUG(4,("transfer_file n=%.0f  (head=%d) called\n",(double)n,headlen));
861
862  if (size == 0) {
863    size = lp_readsize();
864    size = MAX(size,1024);
865  }
866
867  while (!buf && size>0) {
868    buf = (char *)Realloc(buf,size+8);
869    if (!buf) size /= 2;
870  }
871
872  if (!buf) {
873    DEBUG(0,("Can't allocate transfer buffer!\n"));
874    exit(1);
875  }
876
877  abuf = buf + (align%8);
878
879  if (header)
880    n += headlen;
881
882  while (n > 0)
883  {
884    int s = (int)MIN(n,(SMB_OFF_T)size);
885    int ret,ret2=0;
886
887    ret = 0;
888
889    if (header && (headlen >= MIN(s,1024))) {
890      buf1 = header;
891      s = headlen;
892      ret = headlen;
893      headlen = 0;
894      header = NULL;
895    } else {
896      buf1 = abuf;
897    }
898
899    if (header && headlen > 0)
900    {
901      ret = MIN(headlen,size);
902      memcpy(buf1,header,ret);
903      headlen -= ret;
904      header += ret;
905      if (headlen <= 0) header = NULL;
906    }
907
908    if (s > ret)
909      ret += read(infd,buf1+ret,s-ret);
910
911    if (ret > 0)
912    {
913      ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret);
914      if (ret2 > 0) total += ret2;
915      /* if we can't write then dump excess data */
916      if (ret2 != ret)
917        transfer_file(infd,-1,n-(ret+headlen),NULL,0,0);
918    }
919    if (ret <= 0 || ret2 != ret)
920      return(total);
921    n -= ret;
922  }
923  return(total);
924}
925
926
927
928/****************************************************************************
929find a pointer to a netbios name
930****************************************************************************/
931static char *name_ptr(char *buf,int ofs)
932{
933  unsigned char c = *(unsigned char *)(buf+ofs);
934
935  if ((c & 0xC0) == 0xC0)
936    {
937      uint16 l = RSVAL(buf, ofs) & 0x3FFF;
938      DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
939      return(buf + l);
940    }
941  else
942    return(buf+ofs);
943}
944
945/****************************************************************************
946extract a netbios name from a buf
947****************************************************************************/
948int name_extract(char *buf,int ofs,char *name)
949{
950  char *p = name_ptr(buf,ofs);
951  int d = PTR_DIFF(p,buf+ofs);
952  pstrcpy(name,"");
953  if (d < -50 || d > 50) return(0);
954  return(name_interpret(p,name));
955}
956
957/****************************************************************************
958return the total storage length of a mangled name
959****************************************************************************/
960int name_len(char *s1)
961{
962	/* NOTE: this argument _must_ be unsigned */
963	unsigned char *s = (unsigned char *)s1;
964	int len;
965
966	/* If the two high bits of the byte are set, return 2. */
967	if (0xC0 == (*s & 0xC0))
968		return(2);
969
970	/* Add up the length bytes. */
971	for (len = 1; (*s); s += (*s) + 1) {
972		len += *s + 1;
973		SMB_ASSERT(len < 80);
974	}
975
976	return(len);
977} /* name_len */
978
979
980/*******************************************************************
981sleep for a specified number of milliseconds
982********************************************************************/
983void msleep(int t)
984{
985  int tdiff=0;
986  struct timeval tval,t1,t2;
987  fd_set fds;
988
989  GetTimeOfDay(&t1);
990  GetTimeOfDay(&t2);
991
992  while (tdiff < t) {
993    tval.tv_sec = (t-tdiff)/1000;
994    tval.tv_usec = 1000*((t-tdiff)%1000);
995
996    FD_ZERO(&fds);
997    errno = 0;
998    sys_select(0,&fds,&tval);
999
1000    GetTimeOfDay(&t2);
1001    tdiff = TvalDiff(&t1,&t2);
1002  }
1003}
1004
1005
1006/*********************************************************
1007* Recursive routine that is called by unix_mask_match.
1008* Does the actual matching. This is the 'original code'
1009* used by the unix matcher.
1010*********************************************************/
1011
1012BOOL unix_do_match(char *str, char *regexp, BOOL case_sig)
1013{
1014  char *p;
1015
1016  for( p = regexp; *p && *str; ) {
1017    switch(*p) {
1018    case '?':
1019      str++; p++;
1020      break;
1021
1022    case '*':
1023      /*
1024       * Look for a character matching
1025       * the one after the '*'.
1026       */
1027      p++;
1028      if(!*p)
1029        return True; /* Automatic match */
1030      while(*str) {
1031
1032        while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
1033          str++;
1034
1035        /*
1036         * Patch from weidel@multichart.de. In the case of the regexp
1037         * '*XX*' we want to ensure there are at least 2 'X' characters
1038         * in the filename after the '*' for a match to be made.
1039         */
1040
1041        {
1042          int matchcount=0;
1043
1044          /*
1045           * Eat all the characters that match, but count how many there were.
1046           */
1047
1048          while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str)))) {
1049            str++;
1050            matchcount++;
1051          }
1052
1053          /*
1054           * Now check that if the regexp had n identical characters that
1055           * matchcount had at least that many matches.
1056           */
1057
1058          while (( *(p+1) && (case_sig ? (*(p+1) == *p) : (toupper(*(p+1))==toupper(*p))))) {
1059            p++;
1060            matchcount--;
1061          }
1062          if ( matchcount <= 0 ) {
1063            return False;
1064          }
1065        }
1066        str--; /* We've eaten the match char after the '*' */
1067        if(unix_do_match(str,p,case_sig))
1068          return True;
1069        if(!*str)
1070          return False;
1071        else
1072          str++;
1073      }
1074      return False;
1075
1076    default:
1077      if(case_sig) {
1078        if(*str != *p)
1079          return False;
1080      } else {
1081        if(toupper(*str) != toupper(*p))
1082          return False;
1083      }
1084      str++, p++;
1085      break;
1086    }
1087  }
1088
1089  if(!*p && !*str)
1090    return True;
1091
1092  if (!*p && str[0] == '.' && str[1] == 0)
1093    return(True);
1094
1095  if (!*str && *p == '?')
1096    {
1097      while (*p == '?') p++;
1098      return(!*p);
1099    }
1100
1101  if(!*str && (*p == '*' && p[1] == '\0'))
1102    return True;
1103  return False;
1104}
1105
1106
1107/*********************************************************
1108* Routine to match a given string with a regexp - uses
1109* simplified regexp that takes * and ? only. Case can be
1110* significant or not.
1111* This is the 'original code' used by the unix matcher.
1112*********************************************************/
1113
1114static BOOL unix_mask_match(char *str, char *regexp, BOOL case_sig)
1115{
1116  char *p;
1117  pstring p1, p2;
1118  fstring ebase,sbase;
1119  BOOL matched;
1120
1121  /* Make local copies of str and regexp */
1122  StrnCpy(p1,regexp,sizeof(pstring)-1);
1123  StrnCpy(p2,str,sizeof(pstring)-1);
1124
1125  /* Remove any *? and ** as they are meaningless */
1126  for(p = p1; *p; p++)
1127    while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
1128      (void)pstrcpy( &p[1], &p[2]);
1129
1130  if (strequal(p1,"*")) return(True);
1131
1132  DEBUG(8,("unix_mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
1133
1134  fstrcpy(ebase,p1);
1135  fstrcpy(sbase,p2);
1136
1137  matched = unix_do_match(sbase,ebase,case_sig);
1138
1139  DEBUG(8,("unix_mask_match returning %d\n", matched));
1140
1141  return matched;
1142}
1143
1144/*********************************************************
1145* Recursive routine that is called by mask_match.
1146* Does the actual matching. Returns True if matched,
1147* False if failed. This is the 'new' NT style matcher.
1148* The win9x_semantics parameter is needed as Win9x matching
1149* is *actually different*. In Win9x, trailing '?' characters
1150* will only match the *exact* number of characters. Under
1151* DOS and NT they match any number. This makes no
1152* sense.....
1153*********************************************************/
1154
1155static BOOL do_match(char *str, char *regexp, int case_sig, BOOL win9x_semantics)
1156{
1157  char *p;
1158
1159  for( p = regexp; *p && *str; ) {
1160    switch(*p) {
1161    case '?':
1162      str++; p++;
1163      break;
1164
1165    case '*':
1166      /* Look for a character matching
1167         the one after the '*' */
1168      p++;
1169      if(!*p)
1170        return True; /* Automatic match */
1171      while(*str) {
1172        while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
1173          str++;
1174
1175        /*
1176         * Patch from weidel@multichart.de. In the case of the regexp
1177         * '*XX*' we want to ensure there are at least 2 'X' characters
1178         * in the filename after the '*' for a match to be made.
1179         */
1180
1181        {
1182          int matchcount=0;
1183
1184          /*
1185           * Eat all the characters that match, but count how many there were.
1186           */
1187
1188          while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str)))) {
1189            str++;
1190            matchcount++;
1191          }
1192
1193          /*
1194           * Now check that if the regexp had n identical characters that
1195           * matchcount had at least that many matches.
1196           */
1197
1198          while (( *(p+1) && (case_sig ? (*(p+1) == *p) : (toupper(*(p+1))==toupper(*p))))) {
1199            p++;
1200            matchcount--;
1201          }
1202          if ( matchcount <= 0 ) {
1203            return False;
1204          }
1205        }
1206        str--; /* We've eaten the match char after the '*' */
1207        if(do_match(str,p,case_sig,win9x_semantics)) {
1208          return True;
1209        }
1210        if(!*str) {
1211          return False;
1212        } else {
1213          str++;
1214        }
1215      }
1216      return False;
1217
1218    default:
1219      if(case_sig) {
1220        if(*str != *p) {
1221          return False;
1222        }
1223      } else {
1224        if(toupper(*str) != toupper(*p)) {
1225          return False;
1226        }
1227      }
1228      str++, p++;
1229      break;
1230    }
1231  }
1232
1233  if(!*p && !*str)
1234    return True;
1235
1236  if (!*p && str[0] == '.' && str[1] == 0) {
1237    return(True);
1238  }
1239
1240  if (!win9x_semantics) {
1241    if (!*str && *p == '?') {
1242      while (*p == '?')
1243        p++;
1244      return(!*p);
1245    }
1246  }
1247
1248  if(!*str && (*p == '*' && p[1] == '\0')) {
1249    return True;
1250  }
1251
1252  return False;
1253}
1254
1255/*********************************************************
1256* Routine to match a given string with a regexp - uses
1257* simplified regexp that takes * and ? only. Case can be
1258* significant or not.
1259* The 8.3 handling was rewritten by Ums Harald <Harald.Ums@pro-sieben.de>
1260* This is the new 'NT style' matcher.
1261*********************************************************/
1262
1263BOOL mask_match(char *str, char *regexp, BOOL case_sig, BOOL trans2)
1264{
1265  char *p;
1266  pstring t_pattern, t_filename, te_pattern, te_filename;
1267  fstring ebase,eext,sbase,sext;
1268  BOOL matched = False;
1269  BOOL win9x_semantics = (get_remote_arch() == RA_WIN95) && trans2;
1270
1271  /* special case - if it is exactly the same then it always matches! */
1272  if(exact_match(str, regexp, case_sig))
1273    return True;
1274
1275  /* Make local copies of str and regexp */
1276  pstrcpy(t_pattern,regexp);
1277  pstrcpy(t_filename,str);
1278
1279  if(trans2) {
1280
1281    /* a special case for 16 bit apps */
1282    if (strequal(t_pattern,"????????.???"))
1283      pstrcpy(t_pattern,"*");
1284
1285#if 0
1286    /*
1287     * Handle broken clients that send us old 8.3 format.
1288     */
1289    pstring_sub(t_pattern,"????????","*");
1290    pstring_sub(t_pattern,".???",".*");
1291#endif
1292  }
1293
1294#if 0
1295  /*
1296   * Not sure if this is a good idea. JRA.
1297   */
1298  if(trans2 && is_8_3(t_pattern,False) && is_8_3(t_filename,False))
1299    trans2 = False;
1300#endif
1301
1302#if 0
1303  if (!strchr(t_filename,'.')) {
1304    pstrcat(t_filename,".");
1305  }
1306#endif
1307
1308  /* Remove any *? and ** as they are meaningless */
1309  while(all_string_sub(t_pattern, "*?", "*", sizeof(pstring)))
1310    ;
1311
1312  while(all_string_sub(t_pattern, "**", "*", sizeof(pstring)))
1313    ;
1314
1315  if (strequal(t_pattern,"*"))
1316    return(True);
1317
1318  DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", t_filename, t_pattern, case_sig));
1319
1320  if(trans2) {
1321    /*
1322     * Match each component of the regexp, split up by '.'
1323     * characters.
1324     */
1325    char *fp, *rp, *cp2, *cp1;
1326    BOOL last_wcard_was_star = False;
1327    int num_path_components, num_regexp_components;
1328
1329    if(strequal(t_pattern, "."))
1330      return False; /* A dot pattern never matches... ???? */
1331
1332    /*
1333     * NT *always* treats '.' and '..' as identical for a match.... why ?
1334     */
1335
1336    if(strequal(t_filename, ".."))
1337      pstrcpy(t_filename, ".");
1338
1339    pstrcpy(te_pattern,t_pattern);
1340    pstrcpy(te_filename,t_filename);
1341    /*
1342     * Remove multiple "*." patterns.
1343     */
1344    while(all_string_sub(te_pattern, "*.*.", "*.", sizeof(pstring)))
1345      ;
1346    num_regexp_components = count_chars(te_pattern, '.');
1347    num_path_components = count_chars(te_filename, '.');
1348
1349    /*
1350     * Check for special 'hack' case of "DIR a*z". - needs to match a.b.c...z
1351     */
1352    if(num_regexp_components == 0)
1353      matched = do_match( te_filename, te_pattern, case_sig, win9x_semantics);
1354    else {
1355      for( cp1 = te_pattern, cp2 = te_filename; cp1;) {
1356        fp = strchr(cp2, '.');
1357        if(fp)
1358          *fp = '\0';
1359        rp = strchr(cp1, '.');
1360        if(rp)
1361          *rp = '\0';
1362
1363        if(cp1[0] && cp1[strlen(cp1)-1] == '*')
1364          last_wcard_was_star = True;
1365        else
1366          last_wcard_was_star = False;
1367
1368        if(!do_match(cp2, cp1, case_sig, win9x_semantics))
1369          break;
1370
1371        /*
1372         * Ugly ! Special case for Win9x *only*. If filename is XXXX and pattern extension
1373         * is '*' or all '?' then disallow match.
1374         */
1375
1376        if (win9x_semantics) {
1377          if (*cp2 == '\0' && str_is_all(cp1, '?'))
1378            break;
1379        }
1380
1381        cp1 = rp ? rp + 1 : NULL;
1382        cp2 = fp ? fp + 1 : "";
1383
1384        if(last_wcard_was_star || ((cp1 != NULL) && (*cp1 == '*'))) {
1385          /* Eat the extra path components. */
1386          int i;
1387
1388          for(i = 0; i < num_path_components - num_regexp_components; i++) {
1389            fp = strchr(cp2, '.');
1390            if(fp)
1391              *fp = '\0';
1392
1393            if((cp1 != NULL) && do_match( cp2, cp1, case_sig, win9x_semantics)) {
1394              cp2 = fp ? fp + 1 : "";
1395              break;
1396            }
1397            cp2 = fp ? fp + 1 : "";
1398          }
1399          num_path_components -= i;
1400        }
1401      }
1402      if(cp1 == NULL && ((*cp2 == '\0') || last_wcard_was_star))
1403        matched = True;
1404    }
1405  } else {
1406
1407    /* -------------------------------------------------
1408     * Behaviour of Win95
1409     * for 8.3 filenames and 8.3 Wildcards
1410     * -------------------------------------------------
1411     */
1412    if (strequal (t_filename, ".")) {
1413      /*
1414       *  Patterns:  *.*  *. ?. ? ????????.??? are valid.
1415       *
1416       */
1417      if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
1418         strequal(t_pattern, "????????.???") ||
1419         strequal(t_pattern, "?.") || strequal(t_pattern, "?"))
1420        matched = True;
1421    } else if (strequal (t_filename, "..")) {
1422      /*
1423       *  Patterns:  *.*  *. ?. ? *.? ????????.??? are valid.
1424       *
1425       */
1426      if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
1427         strequal(t_pattern, "?.") || strequal(t_pattern, "?") ||
1428         strequal(t_pattern, "????????.???") ||
1429         strequal(t_pattern, "*.?") || strequal(t_pattern, "?.*"))
1430        matched = True;
1431    } else {
1432
1433      if ((p = strrchr (t_pattern, '.'))) {
1434        /*
1435         * Wildcard has a suffix.
1436         */
1437        *p = 0;
1438        fstrcpy (ebase, t_pattern);
1439        if (p[1]) {
1440          fstrcpy (eext, p + 1);
1441        } else {
1442          /* pattern ends in DOT: treat as if there is no DOT */
1443          *eext = 0;
1444          if (strequal (ebase, "*"))
1445            return (True);
1446        }
1447      } else {
1448        /*
1449         * No suffix for wildcard.
1450         */
1451        fstrcpy (ebase, t_pattern);
1452        eext[0] = 0;
1453      }
1454
1455      p = strrchr (t_filename, '.');
1456      if (p && (p[1] == 0)	) {
1457        /*
1458         * Filename has an extension of '.' only.
1459         */
1460        *p = 0; /* nuke dot at end of string */
1461        p = 0;  /* and treat it as if there is no extension */
1462      }
1463
1464      if (p) {
1465        /*
1466         * Filename has an extension.
1467         */
1468        *p = 0;
1469        fstrcpy (sbase, t_filename);
1470        fstrcpy (sext, p + 1);
1471        if (*eext) {
1472          matched = do_match(sbase, ebase, case_sig, False)
1473                    && do_match(sext, eext, case_sig, False);
1474        } else {
1475          /* pattern has no extension */
1476          /* Really: match complete filename with pattern ??? means exactly 3 chars */
1477          matched = do_match(str, ebase, case_sig, False);
1478        }
1479      } else {
1480        /*
1481         * Filename has no extension.
1482         */
1483        fstrcpy (sbase, t_filename);
1484        fstrcpy (sext, "");
1485        if (*eext) {
1486          /* pattern has extension */
1487          matched = do_match(sbase, ebase, case_sig, False)
1488                    && do_match(sext, eext, case_sig, False);
1489
1490        } else {
1491          matched = do_match(sbase, ebase, case_sig, False);
1492#ifdef EMULATE_WEIRD_W95_MATCHING
1493          /*
1494           * Even Microsoft has some problems
1495           * Behaviour Win95 -> local disk
1496           * is different from Win95 -> smb drive from Nt 4.0
1497           * This branch would reflect the Win95 local disk behaviour
1498           */
1499          if (!matched) {
1500            /* a? matches aa and a in w95 */
1501            fstrcat (sbase, ".");
1502            matched = do_match(sbase, ebase, case_sig, False);
1503          }
1504#endif
1505        }
1506      }
1507    }
1508  }
1509
1510  DEBUG(8,("mask_match returning %d\n", matched));
1511
1512  return matched;
1513}
1514
1515/****************************************************************************
1516become a daemon, discarding the controlling terminal
1517****************************************************************************/
1518void become_daemon(void)
1519{
1520	if (fork()) {
1521		_exit(0);
1522	}
1523
1524  /* detach from the terminal */
1525#ifdef HAVE_SETSID
1526	setsid();
1527#elif defined(TIOCNOTTY)
1528	{
1529		int i = sys_open("/dev/tty", O_RDWR, 0);
1530		if (i != -1) {
1531			ioctl(i, (int) TIOCNOTTY, (char *)0);
1532			close(i);
1533		}
1534	}
1535#endif /* HAVE_SETSID */
1536
1537	/* Close fd's 0,1,2. Needed if started by rsh */
1538	close_low_fds();
1539}
1540
1541
1542/****************************************************************************
1543put up a yes/no prompt
1544****************************************************************************/
1545BOOL yesno(char *p)
1546{
1547  pstring ans;
1548  printf("%s",p);
1549
1550  if (!fgets(ans,sizeof(ans)-1,stdin))
1551    return(False);
1552
1553  if (*ans == 'y' || *ans == 'Y')
1554    return(True);
1555
1556  return(False);
1557}
1558
1559/****************************************************************************
1560set the length of a file from a filedescriptor.
1561Returns 0 on success, -1 on failure.
1562****************************************************************************/
1563
1564int set_filelen(int fd, SMB_OFF_T len)
1565{
1566/* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1567   extend a file with ftruncate. Provide alternate implementation
1568   for this */
1569
1570#ifdef HAVE_FTRUNCATE_EXTEND
1571  return sys_ftruncate(fd, len);
1572#else
1573  SMB_STRUCT_STAT st;
1574  char c = 0;
1575  SMB_OFF_T currpos = sys_lseek(fd, (SMB_OFF_T)0, SEEK_CUR);
1576
1577  if(currpos == -1)
1578    return -1;
1579  /* Do an fstat to see if the file is longer than
1580     the requested size (call ftruncate),
1581     or shorter, in which case seek to len - 1 and write 1
1582     byte of zero */
1583  if(sys_fstat(fd, &st)<0)
1584    return -1;
1585
1586#ifdef S_ISFIFO
1587  if (S_ISFIFO(st.st_mode))
1588    return 0;
1589#endif
1590
1591  if(st.st_size == len)
1592    return 0;
1593  if(st.st_size > len)
1594    return sys_ftruncate(fd, len);
1595
1596  if(sys_lseek(fd, len-1, SEEK_SET) != len -1)
1597    return -1;
1598  if(write(fd, &c, 1)!=1)
1599    return -1;
1600  /* Seek to where we were */
1601  if(sys_lseek(fd, currpos, SEEK_SET) != currpos)
1602    return -1;
1603  return 0;
1604#endif
1605}
1606
1607
1608#ifdef HPUX
1609/****************************************************************************
1610this is a version of setbuffer() for those machines that only have setvbuf
1611****************************************************************************/
1612 void setbuffer(FILE *f,char *buf,int bufsize)
1613{
1614  setvbuf(f,buf,_IOFBF,bufsize);
1615}
1616#endif
1617
1618
1619/****************************************************************************
1620parse out a filename from a path name. Assumes dos style filenames.
1621****************************************************************************/
1622static char *filename_dos(char *path,char *buf)
1623{
1624  char *p = strrchr(path,'\\');
1625
1626  if (!p)
1627    pstrcpy(buf,path);
1628  else
1629    pstrcpy(buf,p+1);
1630
1631  return(buf);
1632}
1633
1634
1635
1636/****************************************************************************
1637expand a pointer to be a particular size
1638****************************************************************************/
1639void *Realloc(void *p,size_t size)
1640{
1641  void *ret=NULL;
1642
1643  if (size == 0) {
1644    if (p) free(p);
1645    DEBUG(5,("Realloc asked for 0 bytes\n"));
1646    return NULL;
1647  }
1648
1649  if (!p)
1650    ret = (void *)malloc(size);
1651  else
1652    ret = (void *)realloc(p,size);
1653
1654#ifdef MEM_MAN
1655  {
1656	extern FILE *dbf;
1657	smb_mem_write_info(ret, dbf);
1658  }
1659#endif
1660
1661  if (!ret)
1662    DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size));
1663
1664  return(ret);
1665}
1666
1667
1668/****************************************************************************
1669get my own name and IP
1670****************************************************************************/
1671BOOL get_myname(char *my_name)
1672{
1673	pstring hostname;
1674
1675	*hostname = 0;
1676
1677	/* get my host name */
1678	if (gethostname(hostname, sizeof(hostname)) == -1) {
1679		DEBUG(0,("gethostname failed\n"));
1680		return False;
1681	}
1682
1683	/* Ensure null termination. */
1684	hostname[sizeof(hostname)-1] = '\0';
1685
1686	if (my_name) {
1687		/* split off any parts after an initial . */
1688		char *p = strchr(hostname,'.');
1689		if (p) *p = 0;
1690
1691		fstrcpy(my_name,hostname);
1692	}
1693
1694	return(True);
1695}
1696
1697/****************************************************************************
1698interpret a protocol description string, with a default
1699****************************************************************************/
1700int interpret_protocol(char *str,int def)
1701{
1702  if (strequal(str,"NT1"))
1703    return(PROTOCOL_NT1);
1704  if (strequal(str,"LANMAN2"))
1705    return(PROTOCOL_LANMAN2);
1706  if (strequal(str,"LANMAN1"))
1707    return(PROTOCOL_LANMAN1);
1708  if (strequal(str,"CORE"))
1709    return(PROTOCOL_CORE);
1710  if (strequal(str,"COREPLUS"))
1711    return(PROTOCOL_COREPLUS);
1712  if (strequal(str,"CORE+"))
1713    return(PROTOCOL_COREPLUS);
1714
1715  DEBUG(0,("Unrecognised protocol level %s\n",str));
1716
1717  return(def);
1718}
1719
1720/****************************************************************************
1721 Return true if a string could be a pure IP address.
1722****************************************************************************/
1723
1724BOOL is_ipaddress(const char *str)
1725{
1726  BOOL pure_address = True;
1727  int i;
1728
1729  for (i=0; pure_address && str[i]; i++)
1730    if (!(isdigit((int)str[i]) || str[i] == '.'))
1731      pure_address = False;
1732
1733  /* Check that a pure number is not misinterpreted as an IP */
1734  pure_address = pure_address && (strchr(str, '.') != NULL);
1735
1736  return pure_address;
1737}
1738
1739/****************************************************************************
1740interpret an internet address or name into an IP address in 4 byte form
1741****************************************************************************/
1742
1743uint32 interpret_addr(char *str)
1744{
1745  struct hostent *hp;
1746  uint32 res;
1747
1748  if (strcmp(str,"0.0.0.0") == 0) return(0);
1749  if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
1750
1751  /* if it's in the form of an IP address then get the lib to interpret it */
1752  if (is_ipaddress(str)) {
1753    res = inet_addr(str);
1754  } else {
1755    /* otherwise assume it's a network name of some sort and use
1756       Get_Hostbyname */
1757    if ((hp = Get_Hostbyname(str)) == 0) {
1758      DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
1759      return 0;
1760    }
1761    if(hp->h_addr == NULL) {
1762      DEBUG(3,("Get_Hostbyname: host address is invalid for host %s\n",str));
1763      return 0;
1764    }
1765    putip((char *)&res,(char *)hp->h_addr);
1766  }
1767
1768  if (res == (uint32)-1) return(0);
1769
1770  return(res);
1771}
1772
1773/*******************************************************************
1774  a convenient addition to interpret_addr()
1775  ******************************************************************/
1776struct in_addr *interpret_addr2(char *str)
1777{
1778  static struct in_addr ret;
1779  uint32 a = interpret_addr(str);
1780  ret.s_addr = a;
1781  return(&ret);
1782}
1783
1784/*******************************************************************
1785  check if an IP is the 0.0.0.0
1786  ******************************************************************/
1787BOOL zero_ip(struct in_addr ip)
1788{
1789  uint32 a;
1790  putip((char *)&a,(char *)&ip);
1791  return(a == 0);
1792}
1793
1794
1795/*******************************************************************
1796 matchname - determine if host name matches IP address
1797 ******************************************************************/
1798BOOL matchname(char *remotehost,struct in_addr  addr)
1799{
1800  struct hostent *hp;
1801  int     i;
1802
1803  if ((hp = Get_Hostbyname(remotehost)) == 0) {
1804    DEBUG(0,("Get_Hostbyname(%s): lookup failure.\n", remotehost));
1805    return False;
1806  }
1807
1808  /*
1809   * Make sure that gethostbyname() returns the "correct" host name.
1810   * Unfortunately, gethostbyname("localhost") sometimes yields
1811   * "localhost.domain". Since the latter host name comes from the
1812   * local DNS, we just have to trust it (all bets are off if the local
1813   * DNS is perverted). We always check the address list, though.
1814   */
1815
1816  if (strcasecmp(remotehost, hp->h_name)
1817      && strcasecmp(remotehost, "localhost")) {
1818    DEBUG(0,("host name/name mismatch: %s != %s\n",
1819	     remotehost, hp->h_name));
1820    return False;
1821  }
1822
1823  /* Look up the host address in the address list we just got. */
1824  for (i = 0; hp->h_addr_list[i]; i++) {
1825    if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
1826      return True;
1827  }
1828
1829  /*
1830   * The host name does not map to the original host address. Perhaps
1831   * someone has compromised a name server. More likely someone botched
1832   * it, but that could be dangerous, too.
1833   */
1834
1835  DEBUG(0,("host name/address mismatch: %s != %s\n",
1836	   inet_ntoa(addr), hp->h_name));
1837  return False;
1838}
1839
1840
1841#if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1842/******************************************************************
1843 Remove any mount options such as -rsize=2048,wsize=2048 etc.
1844 Based on a fix from <Thomas.Hepper@icem.de>.
1845*******************************************************************/
1846
1847static void strip_mount_options( pstring *str)
1848{
1849  if (**str == '-')
1850  {
1851    char *p = *str;
1852    while(*p && !isspace(*p))
1853      p++;
1854    while(*p && isspace(*p))
1855      p++;
1856    if(*p) {
1857      pstring tmp_str;
1858
1859      pstrcpy(tmp_str, p);
1860      pstrcpy(*str, tmp_str);
1861    }
1862  }
1863}
1864
1865/*******************************************************************
1866 Patch from jkf@soton.ac.uk
1867 Split Luke's automount_server into YP lookup and string splitter
1868 so can easily implement automount_path().
1869 As we may end up doing both, cache the last YP result.
1870*******************************************************************/
1871
1872#ifdef WITH_NISPLUS_HOME
1873static char *automount_lookup(char *user_name)
1874{
1875  static fstring last_key = "";
1876  static pstring last_value = "";
1877
1878  char *nis_map = (char *)lp_nis_home_map_name();
1879
1880  char nis_domain[NIS_MAXNAMELEN + 1];
1881  char buffer[NIS_MAXATTRVAL + 1];
1882  nis_result *result;
1883  nis_object *object;
1884  entry_obj  *entry;
1885
1886  strncpy(nis_domain, (char *)nis_local_directory(), NIS_MAXNAMELEN);
1887  nis_domain[NIS_MAXNAMELEN] = '\0';
1888
1889  DEBUG(5, ("NIS+ Domain: %s\n", nis_domain));
1890
1891  if (strcmp(user_name, last_key))
1892  {
1893    slprintf(buffer, sizeof(buffer)-1, "[%s=%s]%s.%s", "key", user_name, nis_map, nis_domain);
1894    DEBUG(5, ("NIS+ querystring: %s\n", buffer));
1895
1896    if (result = nis_list(buffer, RETURN_RESULT, NULL, NULL))
1897    {
1898       if (result->status != NIS_SUCCESS)
1899      {
1900        DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
1901        fstrcpy(last_key, ""); pstrcpy(last_value, "");
1902      }
1903      else
1904      {
1905        object = result->objects.objects_val;
1906        if (object->zo_data.zo_type == ENTRY_OBJ)
1907        {
1908           entry = &object->zo_data.objdata_u.en_data;
1909           DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
1910           DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
1911
1912           pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
1913           pstring_sub(last_value, "&", user_name);
1914           fstrcpy(last_key, user_name);
1915        }
1916      }
1917    }
1918    nis_freeresult(result);
1919  }
1920
1921  strip_mount_options(&last_value);
1922
1923  DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
1924  return last_value;
1925}
1926#else /* WITH_NISPLUS_HOME */
1927static char *automount_lookup(char *user_name)
1928{
1929  static fstring last_key = "";
1930  static pstring last_value = "";
1931
1932  int nis_error;        /* returned by yp all functions */
1933  char *nis_result;     /* yp_match inits this */
1934  int nis_result_len;  /* and set this */
1935  char *nis_domain;     /* yp_get_default_domain inits this */
1936  char *nis_map = (char *)lp_nis_home_map_name();
1937
1938  if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
1939  {
1940    DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
1941    return last_value;
1942  }
1943
1944  DEBUG(5, ("NIS Domain: %s\n", nis_domain));
1945
1946  if (!strcmp(user_name, last_key))
1947  {
1948    nis_result = last_value;
1949    nis_result_len = strlen(last_value);
1950    nis_error = 0;
1951  }
1952  else
1953  {
1954    if ((nis_error = yp_match(nis_domain, nis_map,
1955                              user_name, strlen(user_name),
1956                              &nis_result, &nis_result_len)) != 0)
1957    {
1958      DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
1959               yperr_string(nis_error), user_name, nis_map));
1960    }
1961    if (!nis_error && nis_result_len >= sizeof(pstring))
1962    {
1963      nis_result_len = sizeof(pstring)-1;
1964    }
1965    fstrcpy(last_key, user_name);
1966    strncpy(last_value, nis_result, nis_result_len);
1967    last_value[nis_result_len] = '\0';
1968  }
1969
1970  strip_mount_options(&last_value);
1971
1972  DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
1973  return last_value;
1974}
1975#endif /* WITH_NISPLUS_HOME */
1976#endif
1977
1978/*******************************************************************
1979 Patch from jkf@soton.ac.uk
1980 This is Luke's original function with the NIS lookup code
1981 moved out to a separate function.
1982*******************************************************************/
1983static char *automount_server(char *user_name)
1984{
1985	static pstring server_name;
1986
1987	/* use the local machine name as the default */
1988	/* this will be the default if WITH_AUTOMOUNT is not used or fails */
1989	pstrcpy(server_name, local_machine);
1990
1991#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
1992
1993	if (lp_nis_home_map())
1994	{
1995	        int home_server_len;
1996		char *automount_value = automount_lookup(user_name);
1997		home_server_len = strcspn(automount_value,":");
1998		DEBUG(5, ("NIS lookup succeeded.  Home server length: %d\n",home_server_len));
1999		if (home_server_len > sizeof(pstring))
2000		{
2001			home_server_len = sizeof(pstring);
2002		}
2003		strncpy(server_name, automount_value, home_server_len);
2004                server_name[home_server_len] = '\0';
2005	}
2006#endif
2007
2008	DEBUG(4,("Home server: %s\n", server_name));
2009
2010	return server_name;
2011}
2012
2013/*******************************************************************
2014 Patch from jkf@soton.ac.uk
2015 Added this to implement %p (NIS auto-map version of %H)
2016*******************************************************************/
2017static char *automount_path(char *user_name)
2018{
2019	static pstring server_path;
2020
2021	/* use the passwd entry as the default */
2022	/* this will be the default if WITH_AUTOMOUNT is not used or fails */
2023	/* pstrcpy() copes with get_user_home_dir() returning NULL */
2024	pstrcpy(server_path, get_user_home_dir(user_name));
2025
2026#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2027
2028	if (lp_nis_home_map())
2029	{
2030	        char *home_path_start;
2031		char *automount_value = automount_lookup(user_name);
2032		home_path_start = strchr(automount_value,':');
2033		if (home_path_start != NULL)
2034		{
2035		  DEBUG(5, ("NIS lookup succeeded.  Home path is: %s\n",
2036		        home_path_start?(home_path_start+1):""));
2037		  pstrcpy(server_path, home_path_start+1);
2038		}
2039	}
2040#endif
2041
2042	DEBUG(4,("Home server path: %s\n", server_path));
2043
2044	return server_path;
2045}
2046
2047/*******************************************************************
2048 Given a pointer to a %$(NAME) expand it as an environment variable.
2049 Return the number of characters by which the pointer should be advanced.
2050 Based on code by Branko Cibej <branko.cibej@hermes.si>
2051 When this is called p points at the '%' character.
2052********************************************************************/
2053
2054static size_t expand_env_var(char *p, int len)
2055{
2056	fstring envname;
2057	char *envval;
2058	char *q, *r;
2059	int copylen;
2060
2061	if (p[1] != '$')
2062		return 1;
2063
2064	if (p[2] != '(')
2065		return 2;
2066
2067	/*
2068	 * Look for the terminating ')'.
2069	 */
2070
2071	if ((q = strchr(p,')')) == NULL) {
2072		DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p));
2073		return 2;
2074	}
2075
2076	/*
2077	 * Extract the name from within the %$(NAME) string.
2078	 */
2079
2080	r = p+3;
2081	copylen = MIN((q-r),(sizeof(envname)-1));
2082	strncpy(envname,r,copylen);
2083	envname[copylen] = '\0';
2084
2085	if ((envval = getenv(envname)) == NULL) {
2086		DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname));
2087		return 2;
2088	}
2089
2090	/*
2091	 * Copy the full %$(NAME) into envname so it
2092	 * can be replaced.
2093	 */
2094
2095	copylen = MIN((q+1-p),(sizeof(envname)-1));
2096	strncpy(envname,p,copylen);
2097	envname[copylen] = '\0';
2098	string_sub(p,envname,envval,len);
2099	return 0; /* Allow the environment contents to be parsed. */
2100}
2101
2102/*******************************************************************
2103 Substitute strings with useful parameters.
2104 Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
2105 Paul Rippin <pr3245@nopc.eurostat.cec.be>.
2106********************************************************************/
2107
2108void standard_sub_basic(char *str)
2109{
2110	char *s, *p;
2111	char pidstr[10];
2112	struct passwd *pass;
2113	char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user;
2114
2115	for (s = str ; s && *s && (p = strchr(s,'%')); s = p )
2116	{
2117		int l = sizeof(pstring) - (int)(p-str);
2118
2119		if (l < 0) {
2120			DEBUG(0,("ERROR: string overflow by %d in standard_sub_basic(%.50s)\n",
2121				 -l, str));
2122
2123			return;
2124		}
2125
2126		switch (*(p+1))
2127		{
2128			case 'G' :
2129			{
2130				if ((pass = Get_Pwnam(username,False))!=NULL) {
2131					string_sub(p,"%G",gidtoname(pass->pw_gid),l);
2132				} else {
2133					p += 2;
2134				}
2135				break;
2136			}
2137			case 'N' : string_sub(p,"%N", automount_server(username),l); break;
2138			case 'I' : string_sub(p,"%I", client_addr(Client),l); break;
2139			case 'L' : string_sub(p,"%L", local_machine,l); break;
2140			case 'M' : string_sub(p,"%M", client_name(Client),l); break;
2141			case 'R' : string_sub(p,"%R", remote_proto,l); break;
2142			case 'T' : string_sub(p,"%T", timestring(False),l); break;
2143			case 'U' : string_sub(p,"%U", username,l); break;
2144			case 'a' : string_sub(p,"%a", remote_arch,l); break;
2145			case 'd' :
2146			{
2147				slprintf(pidstr,sizeof(pidstr) - 1, "%d",(int)getpid());
2148				string_sub(p,"%d", pidstr,l);
2149				break;
2150			}
2151			case 'h' : string_sub(p,"%h", myhostname(),l); break;
2152			case 'm' : string_sub(p,"%m", remote_machine,l); break;
2153			case 'v' : string_sub(p,"%v", VERSION,l); break;
2154			case '$' : p += expand_env_var(p,l); break; /* Expand environment variables */
2155			case '\0': p++; break; /* don't run off end if last character is % */
2156			default  : p+=2; break;
2157		}
2158	}
2159	return;
2160}
2161
2162
2163/****************************************************************************
2164 Do some standard substitutions in a string.
2165****************************************************************************/
2166
2167void standard_sub(connection_struct *conn,char *str)
2168{
2169	char *p, *s, *home;
2170
2171	for (s=str; (p=strchr(s, '%'));s=p) {
2172		int l = sizeof(pstring) - (int)(p-str);
2173
2174		switch (*(p+1)) {
2175		case 'H':
2176			if ((home = get_user_home_dir(conn->user))) {
2177				string_sub(p,"%H",home,l);
2178			} else {
2179				p += 2;
2180			}
2181			break;
2182
2183		case 'P':
2184			string_sub(p,"%P",conn->connectpath,l);
2185			break;
2186
2187		case 'S':
2188			string_sub(p,"%S",
2189				   lp_servicename(SNUM(conn)),l);
2190			break;
2191
2192		case 'g':
2193			string_sub(p,"%g",
2194				   gidtoname(conn->gid),l);
2195			break;
2196		case 'u':
2197			string_sub(p,"%u",conn->user,l);
2198			break;
2199
2200			/* Patch from jkf@soton.ac.uk Left the %N (NIS
2201			 * server name) in standard_sub_basic as it is
2202			 * a feature for logon servers, hence uses the
2203			 * username.  The %p (NIS server path) code is
2204			 * here as it is used instead of the default
2205			 * "path =" string in [homes] and so needs the
2206			 * service name, not the username.  */
2207		case 'p':
2208			string_sub(p,"%p",
2209				   automount_path(lp_servicename(SNUM(conn))),l);
2210			break;
2211		case '\0':
2212			p++;
2213			break; /* don't run off the end of the string
2214				*/
2215
2216		default: p+=2;
2217			break;
2218		}
2219	}
2220
2221	standard_sub_basic(str);
2222}
2223
2224
2225
2226/*******************************************************************
2227are two IPs on the same subnet?
2228********************************************************************/
2229BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
2230{
2231  uint32 net1,net2,nmask;
2232
2233  nmask = ntohl(mask.s_addr);
2234  net1  = ntohl(ip1.s_addr);
2235  net2  = ntohl(ip2.s_addr);
2236
2237  return((net1 & nmask) == (net2 & nmask));
2238}
2239
2240
2241/****************************************************************************
2242a wrapper for gethostbyname() that tries with all lower and all upper case
2243if the initial name fails
2244****************************************************************************/
2245struct hostent *Get_Hostbyname(const char *name)
2246{
2247  char *name2 = strdup(name);
2248  struct hostent *ret;
2249
2250  if (!name2)
2251    {
2252      DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
2253      exit(0);
2254    }
2255
2256
2257  /*
2258   * This next test is redundent and causes some systems (with
2259   * broken isalnum() calls) problems.
2260   * JRA.
2261   */
2262
2263#if 0
2264  if (!isalnum(*name2))
2265    {
2266      free(name2);
2267      return(NULL);
2268    }
2269#endif /* 0 */
2270
2271  ret = sys_gethostbyname(name2);
2272  if (ret != NULL)
2273    {
2274      free(name2);
2275      return(ret);
2276    }
2277
2278  /* try with all lowercase */
2279  strlower(name2);
2280  ret = sys_gethostbyname(name2);
2281  if (ret != NULL)
2282    {
2283      free(name2);
2284      return(ret);
2285    }
2286
2287  /* try with all uppercase */
2288  strupper(name2);
2289  ret = sys_gethostbyname(name2);
2290  if (ret != NULL)
2291    {
2292      free(name2);
2293      return(ret);
2294    }
2295
2296  /* nothing works :-( */
2297  free(name2);
2298  return(NULL);
2299}
2300
2301
2302/****************************************************************************
2303check if a process exists. Does this work on all unixes?
2304****************************************************************************/
2305
2306BOOL process_exists(pid_t pid)
2307{
2308	return(kill(pid,0) == 0 || errno != ESRCH);
2309}
2310
2311
2312/*******************************************************************
2313turn a uid into a user name
2314********************************************************************/
2315char *uidtoname(uid_t uid)
2316{
2317  static char name[40];
2318  struct passwd *pass = sys_getpwuid(uid);
2319  if (pass) return(pass->pw_name);
2320  slprintf(name, sizeof(name) - 1, "%d",(int)uid);
2321  return(name);
2322}
2323
2324
2325/*******************************************************************
2326turn a gid into a group name
2327********************************************************************/
2328
2329char *gidtoname(gid_t gid)
2330{
2331	static char name[40];
2332	struct group *grp = getgrgid(gid);
2333	if (grp) return(grp->gr_name);
2334	slprintf(name,sizeof(name) - 1, "%d",(int)gid);
2335	return(name);
2336}
2337
2338/*******************************************************************
2339turn a user name into a uid
2340********************************************************************/
2341uid_t nametouid(const char *name)
2342{
2343	struct passwd *pass;
2344	char *p;
2345	uid_t u;
2346
2347	u = strtol(name, &p, 0);
2348	if (p != name) return u;
2349
2350	pass = sys_getpwnam(name);
2351	if (pass) return(pass->pw_uid);
2352	return (uid_t)-1;
2353}
2354
2355/*******************************************************************
2356turn a group name into a gid
2357********************************************************************/
2358gid_t nametogid(const char *name)
2359{
2360	struct group *grp;
2361	char *p;
2362	gid_t g;
2363
2364	g = strtol(name, &p, 0);
2365	if (p != name) return g;
2366
2367	grp = getgrnam(name);
2368	if (grp) return(grp->gr_gid);
2369	return (gid_t)-1;
2370}
2371
2372/*******************************************************************
2373something really nasty happened - panic!
2374********************************************************************/
2375void smb_panic(char *why)
2376{
2377	char *cmd = lp_panic_action();
2378	if (cmd && *cmd) {
2379		system(cmd);
2380	}
2381	DEBUG(0,("PANIC: %s\n", why));
2382	dbgflush();
2383	abort();
2384}
2385
2386
2387/*******************************************************************
2388a readdir wrapper which just returns the file name
2389********************************************************************/
2390char *readdirname(DIR *p)
2391{
2392	SMB_STRUCT_DIRENT *ptr;
2393	char *dname;
2394
2395	if (!p) return(NULL);
2396
2397	ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
2398	if (!ptr) return(NULL);
2399
2400	dname = ptr->d_name;
2401
2402#ifdef NEXT2
2403	if (telldir(p) < 0) return(NULL);
2404#endif
2405
2406#ifdef HAVE_BROKEN_READDIR
2407	/* using /usr/ucb/cc is BAD */
2408	dname = dname - 2;
2409#endif
2410
2411	{
2412		static pstring buf;
2413		memcpy(buf, dname, NAMLEN(ptr)+1);
2414		dname = buf;
2415	}
2416
2417	return(dname);
2418}
2419
2420/*******************************************************************
2421 Utility function used to decide if the last component
2422 of a path matches a (possibly wildcarded) entry in a namelist.
2423********************************************************************/
2424
2425BOOL is_in_path(char *name, name_compare_entry *namelist)
2426{
2427  pstring last_component;
2428  char *p;
2429
2430  DEBUG(8, ("is_in_path: %s\n", name));
2431
2432  /* if we have no list it's obviously not in the path */
2433  if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL)))
2434  {
2435    DEBUG(8,("is_in_path: no name list.\n"));
2436    return False;
2437  }
2438
2439  /* Get the last component of the unix name. */
2440  p = strrchr(name, '/');
2441  strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
2442  last_component[sizeof(last_component)-1] = '\0';
2443
2444  for(; namelist->name != NULL; namelist++)
2445  {
2446    if(namelist->is_wild)
2447    {
2448      /*
2449       * Look for a wildcard match. Use the old
2450       * 'unix style' mask match, rather than the
2451       * new NT one.
2452       */
2453      if (unix_mask_match(last_component, namelist->name, case_sensitive))
2454      {
2455         DEBUG(8,("is_in_path: mask match succeeded\n"));
2456         return True;
2457      }
2458    }
2459    else
2460    {
2461      if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
2462       (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0)))
2463        {
2464         DEBUG(8,("is_in_path: match succeeded\n"));
2465         return True;
2466        }
2467    }
2468  }
2469  DEBUG(8,("is_in_path: match not found\n"));
2470
2471  return False;
2472}
2473
2474/*******************************************************************
2475 Strip a '/' separated list into an array of
2476 name_compare_enties structures suitable for
2477 passing to is_in_path(). We do this for
2478 speed so we can pre-parse all the names in the list
2479 and don't do it for each call to is_in_path().
2480 namelist is modified here and is assumed to be
2481 a copy owned by the caller.
2482 We also check if the entry contains a wildcard to
2483 remove a potentially expensive call to mask_match
2484 if possible.
2485********************************************************************/
2486
2487void set_namearray(name_compare_entry **ppname_array, char *namelist)
2488{
2489  char *name_end;
2490  char *nameptr = namelist;
2491  int num_entries = 0;
2492  int i;
2493
2494  (*ppname_array) = NULL;
2495
2496  if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0')))
2497    return;
2498
2499  /* We need to make two passes over the string. The
2500     first to count the number of elements, the second
2501     to split it.
2502   */
2503  while(*nameptr)
2504    {
2505      if ( *nameptr == '/' )
2506        {
2507          /* cope with multiple (useless) /s) */
2508          nameptr++;
2509          continue;
2510        }
2511      /* find the next / */
2512      name_end = strchr(nameptr, '/');
2513
2514      /* oops - the last check for a / didn't find one. */
2515      if (name_end == NULL)
2516        break;
2517
2518      /* next segment please */
2519      nameptr = name_end + 1;
2520      num_entries++;
2521    }
2522
2523  if(num_entries == 0)
2524    return;
2525
2526  if(( (*ppname_array) = (name_compare_entry *)malloc(
2527           (num_entries + 1) * sizeof(name_compare_entry))) == NULL)
2528        {
2529    DEBUG(0,("set_namearray: malloc fail\n"));
2530    return;
2531        }
2532
2533  /* Now copy out the names */
2534  nameptr = namelist;
2535  i = 0;
2536  while(*nameptr)
2537             {
2538      if ( *nameptr == '/' )
2539      {
2540          /* cope with multiple (useless) /s) */
2541          nameptr++;
2542          continue;
2543      }
2544      /* find the next / */
2545      if ((name_end = strchr(nameptr, '/')) != NULL)
2546      {
2547          *name_end = 0;
2548         }
2549
2550      /* oops - the last check for a / didn't find one. */
2551      if(name_end == NULL)
2552        break;
2553
2554      (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
2555                                (strchr( nameptr, '*')!=NULL));
2556      if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
2557      {
2558        DEBUG(0,("set_namearray: malloc fail (1)\n"));
2559        return;
2560      }
2561
2562      /* next segment please */
2563      nameptr = name_end + 1;
2564      i++;
2565    }
2566
2567  (*ppname_array)[i].name = NULL;
2568
2569  return;
2570}
2571
2572/****************************************************************************
2573routine to free a namearray.
2574****************************************************************************/
2575
2576void free_namearray(name_compare_entry *name_array)
2577{
2578  if(name_array == 0)
2579    return;
2580
2581  if(name_array->name != NULL)
2582    free(name_array->name);
2583
2584  free((char *)name_array);
2585}
2586
2587/****************************************************************************
2588 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
2589****************************************************************************/
2590
2591uint32 map_lock_offset(uint32 high, uint32 low)
2592{
2593  unsigned int i;
2594  uint32 mask = 0;
2595  uint32 highcopy = high;
2596
2597  /*
2598   * Try and find out how many significant bits there are in high.
2599   */
2600
2601  for(i = 0; highcopy; i++)
2602    highcopy >>= 1;
2603
2604  /*
2605   * We use 31 bits not 32 here as POSIX
2606   * lock offsets may not be negative.
2607   */
2608
2609  mask = (~0) << (31 - i);
2610
2611  if(low & mask)
2612    return 0; /* Fail. */
2613
2614  high <<= (31 - i);
2615
2616  return (high|low);
2617}
2618
2619/****************************************************************************
2620routine to do file locking
2621****************************************************************************/
2622
2623BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
2624{
2625#if HAVE_FCNTL_LOCK
2626  SMB_STRUCT_FLOCK lock;
2627  int ret;
2628#if defined(LARGE_SMB_OFF_T)
2629  /*
2630   * In the 64 bit locking case we store the original
2631   * values in case we have to map to a 32 bit lock on
2632   * a filesystem that doesn't support 64 bit locks.
2633   */
2634  SMB_OFF_T orig_offset = offset;
2635  SMB_OFF_T orig_count = count;
2636#endif /* LARGE_SMB_OFF_T */
2637
2638  if(lp_ole_locking_compat()) {
2639    SMB_OFF_T mask2= ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4);
2640    SMB_OFF_T mask = (mask2<<2);
2641
2642    /* make sure the count is reasonable, we might kill the lockd otherwise */
2643    count &= ~mask;
2644
2645    /* the offset is often strange - remove 2 of its bits if either of
2646       the top two bits are set. Shift the top ones by two bits. This
2647       still allows OLE2 apps to operate, but should stop lockd from
2648       dieing */
2649    if ((offset & mask) != 0)
2650      offset = (offset & ~mask) | (((offset & mask) >> 2) & mask2);
2651  } else {
2652    SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
2653    SMB_OFF_T mask = (mask2<<1);
2654    SMB_OFF_T neg_mask = ~mask;
2655
2656    /* interpret negative counts as large numbers */
2657    if (count < 0)
2658      count &= ~mask;
2659
2660    /* no negative offsets */
2661    if(offset < 0)
2662      offset &= ~mask;
2663
2664    /* count + offset must be in range */
2665    while ((offset < 0 || (offset + count < 0)) && mask)
2666    {
2667      offset &= ~mask;
2668      mask = ((mask >> 1) & neg_mask);
2669    }
2670  }
2671
2672  DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
2673
2674  lock.l_type = type;
2675  lock.l_whence = SEEK_SET;
2676  lock.l_start = offset;
2677  lock.l_len = count;
2678  lock.l_pid = 0;
2679
2680  errno = 0;
2681
2682  ret = fcntl(fd,op,&lock);
2683  if (errno == EFBIG)
2684  {
2685    if( DEBUGLVL( 0 ))
2686    {
2687      dbgtext("fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count);
2688      dbgtext("a 'file too large' error. This can happen when using 64 bit lock offsets\n");
2689      dbgtext("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n");
2690    }
2691    /* 32 bit NFS file system, retry with smaller offset */
2692    errno = 0;
2693    lock.l_len = count & 0x7fffffff;
2694    ret = fcntl(fd,op,&lock);
2695  }
2696
2697  if (errno != 0)
2698    DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
2699
2700  /* a lock query */
2701  if (op == SMB_F_GETLK)
2702  {
2703    if ((ret != -1) &&
2704        (lock.l_type != F_UNLCK) &&
2705        (lock.l_pid != 0) &&
2706        (lock.l_pid != getpid()))
2707    {
2708      DEBUG(3,("fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
2709      return(True);
2710    }
2711
2712    /* it must be not locked or locked by me */
2713    return(False);
2714  }
2715
2716  /* a lock set or unset */
2717  if (ret == -1)
2718  {
2719    DEBUG(3,("lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
2720          (double)offset,(double)count,op,type,strerror(errno)));
2721
2722    /* perhaps it doesn't support this sort of locking?? */
2723    if (errno == EINVAL)
2724    {
2725
2726#if defined(LARGE_SMB_OFF_T)
2727      {
2728        /*
2729         * Ok - if we get here then we have a 64 bit lock request
2730         * that has returned EINVAL. Try and map to 31 bits for offset
2731         * and length and try again. This may happen if a filesystem
2732         * doesn't support 64 bit offsets (efs/ufs) although the underlying
2733         * OS does.
2734         */
2735        uint32 off_low = (orig_offset & 0xFFFFFFFF);
2736        uint32 off_high = ((orig_offset >> 32) & 0xFFFFFFFF);
2737
2738        lock.l_len = (orig_count & 0x7FFFFFFF);
2739        lock.l_start = (SMB_OFF_T)map_lock_offset(off_high, off_low);
2740        ret = fcntl(fd,op,&lock);
2741        if (ret == -1)
2742        {
2743          if (errno == EINVAL)
2744          {
2745            DEBUG(3,("locking not supported? returning True\n"));
2746            return(True);
2747          }
2748          return False;
2749        }
2750        DEBUG(3,("64 -> 32 bit modified lock call successful\n"));
2751        return True;
2752      }
2753#else /* LARGE_SMB_OFF_T */
2754      DEBUG(3,("locking not supported? returning True\n"));
2755      return(True);
2756#endif /* LARGE_SMB_OFF_T */
2757    }
2758
2759    return(False);
2760  }
2761
2762  /* everything went OK */
2763  DEBUG(8,("Lock call successful\n"));
2764
2765  return(True);
2766#else
2767  return(False);
2768#endif
2769}
2770
2771/*******************************************************************
2772is the name specified one of my netbios names
2773returns true is it is equal, false otherwise
2774********************************************************************/
2775BOOL is_myname(char *s)
2776{
2777  int n;
2778  BOOL ret = False;
2779
2780  for (n=0; my_netbios_names[n]; n++) {
2781    if (strequal(my_netbios_names[n], s))
2782      ret=True;
2783  }
2784  DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
2785  return(ret);
2786}
2787
2788/*******************************************************************
2789set the horrid remote_arch string based on an enum.
2790********************************************************************/
2791void set_remote_arch(enum remote_arch_types type)
2792{
2793  ra_type = type;
2794  switch( type )
2795  {
2796  case RA_WFWG:
2797    fstrcpy(remote_arch, "WfWg");
2798    return;
2799  case RA_OS2:
2800    fstrcpy(remote_arch, "OS2");
2801    return;
2802  case RA_WIN95:
2803    fstrcpy(remote_arch, "Win95");
2804    return;
2805  case RA_WINNT:
2806    fstrcpy(remote_arch, "WinNT");
2807    return;
2808  case RA_WIN2K:
2809    fstrcpy(remote_arch, "Win2K");
2810    return;
2811  case RA_SAMBA:
2812    fstrcpy(remote_arch,"Samba");
2813    return;
2814  default:
2815    ra_type = RA_UNKNOWN;
2816    fstrcpy(remote_arch, "UNKNOWN");
2817    break;
2818  }
2819}
2820
2821/*******************************************************************
2822 Get the remote_arch type.
2823********************************************************************/
2824enum remote_arch_types get_remote_arch(void)
2825{
2826  return ra_type;
2827}
2828
2829
2830/*******************************************************************
2831align a pointer to a multiple of 2 bytes
2832********************************************************************/
2833char *align2(char *q, char *base)
2834{
2835    if (PTR_DIFF(q, base) & 1)
2836    {
2837        q++;
2838    }
2839    return q;
2840}
2841
2842/*******************************************************************
2843 align a pointer to a multiple of 4 bytes.
2844 ********************************************************************/
2845char *align4(char *q, char *base)
2846{
2847    int mod = PTR_DIFF(q, base) & 3;
2848    if (mod != 0)
2849    {
2850        q += 4-mod;
2851    }
2852    return q;
2853}
2854
2855void out_ascii(FILE *f, unsigned char *buf,int len)
2856{
2857	int i;
2858	for (i=0;i<len;i++)
2859	{
2860		fprintf(f, "%c", isprint(buf[i])?buf[i]:'.');
2861	}
2862}
2863
2864void out_data(FILE *f,char *buf1,int len, int per_line)
2865{
2866	unsigned char *buf = (unsigned char *)buf1;
2867	int i=0;
2868	if (len<=0)
2869	{
2870		return;
2871	}
2872
2873	fprintf(f, "[%03X] ",i);
2874	for (i=0;i<len;)
2875	{
2876		fprintf(f, "%02X ",(int)buf[i]);
2877		i++;
2878		if (i%(per_line/2) == 0) fprintf(f, " ");
2879		if (i%per_line == 0)
2880		{
2881			out_ascii(f,&buf[i-per_line  ],per_line/2); fprintf(f, " ");
2882			out_ascii(f,&buf[i-per_line/2],per_line/2); fprintf(f, "\n");
2883			if (i<len) fprintf(f, "[%03X] ",i);
2884		}
2885	}
2886	if ((i%per_line) != 0)
2887	{
2888		int n;
2889
2890		n = per_line - (i%per_line);
2891		fprintf(f, " ");
2892		if (n>(per_line/2)) fprintf(f, " ");
2893		while (n--)
2894		{
2895			fprintf(f, "   ");
2896		}
2897		n = MIN(per_line/2,i%per_line);
2898		out_ascii(f,&buf[i-(i%per_line)],n); fprintf(f, " ");
2899		n = (i%per_line) - n;
2900		if (n>0) out_ascii(f,&buf[i-n],n);
2901		fprintf(f, "\n");
2902	}
2903}
2904
2905void print_asc(int level, unsigned char *buf,int len)
2906{
2907	int i;
2908	for (i=0;i<len;i++)
2909		DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
2910}
2911
2912void dump_data(int level,char *buf1,int len)
2913{
2914  unsigned char *buf = (unsigned char *)buf1;
2915  int i=0;
2916  if (len<=0) return;
2917
2918  DEBUG(level,("[%03X] ",i));
2919  for (i=0;i<len;) {
2920    DEBUG(level,("%02X ",(int)buf[i]));
2921    i++;
2922    if (i%8 == 0) DEBUG(level,(" "));
2923    if (i%16 == 0) {
2924      print_asc(level,&buf[i-16],8); DEBUG(level,(" "));
2925      print_asc(level,&buf[i-8],8); DEBUG(level,("\n"));
2926      if (i<len) DEBUG(level,("[%03X] ",i));
2927    }
2928  }
2929  if (i%16) {
2930    int n;
2931
2932    n = 16 - (i%16);
2933    DEBUG(level,(" "));
2934    if (n>8) DEBUG(level,(" "));
2935    while (n--) DEBUG(level,("   "));
2936
2937    n = MIN(8,i%16);
2938    print_asc(level,&buf[i-(i%16)],n); DEBUG(level,(" "));
2939    n = (i%16) - n;
2940    if (n>0) print_asc(level,&buf[i-n],n);
2941    DEBUG(level,("\n"));
2942  }
2943}
2944
2945char *tab_depth(int depth)
2946{
2947	static pstring spaces;
2948	memset(spaces, ' ', depth * 4);
2949	spaces[depth * 4] = 0;
2950	return spaces;
2951}
2952
2953/*****************************************************************************
2954 * Provide a checksum on a string
2955 *
2956 *  Input:  s - the null-terminated character string for which the checksum
2957 *              will be calculated.
2958 *
2959 *  Output: The checksum value calculated for s.
2960 *
2961 * ****************************************************************************
2962 */
2963int str_checksum(const char *s)
2964{
2965	int res = 0;
2966	int c;
2967	int i=0;
2968
2969	while(*s) {
2970		c = *s;
2971		res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
2972		s++;
2973		i++;
2974	}
2975	return(res);
2976} /* str_checksum */
2977
2978
2979
2980/*****************************************************************
2981zero a memory area then free it. Used to catch bugs faster
2982*****************************************************************/
2983void zero_free(void *p, size_t size)
2984{
2985	memset(p, 0, size);
2986	free(p);
2987}
2988
2989
2990/*****************************************************************
2991set our open file limit to a requested max and return the limit
2992*****************************************************************/
2993int set_maxfiles(int requested_max)
2994{
2995#if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
2996	struct rlimit rlp;
2997	int saved_current_limit;
2998
2999	if(getrlimit(RLIMIT_NOFILE, &rlp)) {
3000		DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
3001			strerror(errno) ));
3002		/* just guess... */
3003		return requested_max;
3004	}
3005
3006	/*
3007     * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
3008	 * account for the extra fd we need
3009	 * as well as the log files and standard
3010	 * handles etc. Save the limit we want to set in case
3011	 * we are running on an OS that doesn't support this limit (AIX)
3012	 * which always returns RLIM_INFINITY for rlp.rlim_max.
3013	 */
3014
3015	saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
3016
3017	if(setrlimit(RLIMIT_NOFILE, &rlp)) {
3018		DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n",
3019			(int)rlp.rlim_cur, strerror(errno) ));
3020		/* just guess... */
3021		return saved_current_limit;
3022	}
3023
3024	if(getrlimit(RLIMIT_NOFILE, &rlp)) {
3025		DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
3026			strerror(errno) ));
3027		/* just guess... */
3028		return saved_current_limit;
3029    }
3030
3031#if defined(RLIM_INFINITY)
3032	if(rlp.rlim_cur == RLIM_INFINITY)
3033		return saved_current_limit;
3034#endif
3035
3036    if((int)rlp.rlim_cur > saved_current_limit)
3037		return saved_current_limit;
3038
3039	return rlp.rlim_cur;
3040#else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
3041	/*
3042	 * No way to know - just guess...
3043	 */
3044	return requested_max;
3045#endif
3046}
3047
3048/*****************************************************************
3049 splits out the start of the key (HKLM or HKU) and the rest of the key
3050 *****************************************************************/
3051BOOL reg_split_key(char *full_keyname, uint32 *reg_type, char *key_name)
3052{
3053	pstring tmp;
3054
3055	if (!next_token(&full_keyname, tmp, "\\", sizeof(tmp)))
3056	{
3057		return False;
3058	}
3059
3060	(*reg_type) = 0;
3061
3062	DEBUG(10, ("reg_split_key: hive %s\n", tmp));
3063
3064	if (strequal(tmp, "HKLM") || strequal(tmp, "HKEY_LOCAL_MACHINE"))
3065	{
3066		(*reg_type) = HKEY_LOCAL_MACHINE;
3067	}
3068	else if (strequal(tmp, "HKU") || strequal(tmp, "HKEY_USERS"))
3069	{
3070		(*reg_type) = HKEY_USERS;
3071	}
3072	else
3073	{
3074		DEBUG(10,("reg_split_key: unrecognised hive key %s\n", tmp));
3075		return False;
3076	}
3077
3078	if (next_token(NULL, tmp, "\n\r", sizeof(tmp)))
3079	{
3080		fstrcpy(key_name, tmp);
3081	}
3082	else
3083	{
3084		key_name[0] = 0;
3085	}
3086
3087	DEBUG(10, ("reg_split_key: name %s\n", key_name));
3088
3089	return True;
3090}
3091
3092
3093/*****************************************************************
3094like mktemp() but make sure that no % characters are used
3095% characters are bad for us because of the macro subs
3096 *****************************************************************/
3097char *smbd_mktemp(char *template)
3098{
3099	char *p = mktemp(template);
3100	char *p2;
3101	SMB_STRUCT_STAT st;
3102
3103	if (!p) return NULL;
3104
3105	while ((p2=strchr(p,'%'))) {
3106		p2[0] = 'A';
3107		while (sys_stat(p,&st) == 0 && p2[0] < 'Z') {
3108			/* damn, it exists */
3109			p2[0]++;
3110		}
3111		if (p2[0] == 'Z') {
3112			/* oh well ... better return something */
3113			p2[0] = '%';
3114			return p;
3115		}
3116	}
3117
3118	return p;
3119}
3120
3121/*****************************************************************
3122possibly replace mkstemp if it is broken
3123 *****************************************************************/
3124int smb_mkstemp(char *template)
3125{
3126#if HAVE_SECURE_MKSTEMP
3127	return mkstemp(template);
3128#else
3129	/* have a reasonable go at emulating it. Hope that
3130	   the system mktemp() isn't completly hopeless */
3131	if (!mktemp(template)) return -1;
3132	return open(template, O_CREAT|O_EXCL|O_RDWR, 0600);
3133#endif
3134}
3135
3136
3137/*****************************************************************
3138like strdup but for memory
3139 *****************************************************************/
3140void *memdup(void *p, size_t size)
3141{
3142	void *p2;
3143	p2 = malloc(size);
3144	if (!p2) return NULL;
3145	memcpy(p2, p, size);
3146	return p2;
3147}
3148
3149/*****************************************************************
3150get local hostname and cache result
3151 *****************************************************************/
3152char *myhostname(void)
3153{
3154	static pstring ret;
3155	if (ret[0] == 0) {
3156		get_myname(ret);
3157	}
3158	return ret;
3159}
3160
3161/*******************************************************************
3162 Given a filename - get its directory name
3163 NB: Returned in static storage.  Caveats:
3164 o  Not safe in thread environment.
3165 o  Caller must not free.
3166 o  If caller wishes to preserve, they should copy.
3167********************************************************************/
3168
3169char *parent_dirname(const char *path)
3170{
3171	static pstring dirpath;
3172	char *p;
3173
3174	if (!path)
3175		return(NULL);
3176
3177	pstrcpy(dirpath, path);
3178	p = strrchr(dirpath, '/');  /* Find final '/', if any */
3179	if (!p) {
3180		pstrcpy(dirpath, ".");    /* No final "/", so dir is "." */
3181	} else {
3182		if (p == dirpath)
3183			++p;    /* For root "/", leave "/" in place */
3184		*p = '\0';
3185	}
3186	return dirpath;
3187}
3188