Unix SMB/Netbios implementation.
Version 1.9.
Samba utility functions
- Copyright (C) Andrew Tridgell 1992-1997
+ Copyright (C) Andrew Tridgell 1992-1998
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "includes.h"
+#if (defined(NETGROUP) && defined (AUTOMOUNT))
+#include "rpcsvc/ypclnt.h"
+#endif
+
pstring scope = "";
int DEBUGLEVEL = 1;
fstring remote_machine="";
fstring local_machine="";
fstring remote_arch="UNKNOWN";
+static enum remote_arch_types ra_type = RA_UNKNOWN;
fstring remote_proto="UNKNOWN";
pstring myhostname="";
pstring user_socket_options="";
+
pstring sesssetup_user="";
+pstring samlogon_user="";
+
+BOOL sam_logon_in_ssb = False;
+
pstring myname = "";
fstring myworkgroup = "";
char **my_netbios_names;
static char *filename_dos(char *path,char *buf);
+#if defined(SIGUSR2)
+/******************************************************************************
+ catch a sigusr2 - decrease the debug log level.
+ *****************************************************************************/
+int sig_usr2(void)
+{
+ BlockSignals( True, SIGUSR2);
+
+ DEBUGLEVEL--;
+
+ if(DEBUGLEVEL < 0)
+ DEBUGLEVEL = 0;
+
+ DEBUG( 0, ( "Got SIGUSR2 set debug level to %d.\n", DEBUGLEVEL ) );
+
+ BlockSignals( False, SIGUSR2);
+#ifndef DONT_REINSTALL_SIG
+ signal(SIGUSR2, SIGNAL_CAST sig_usr2);
+#endif
+ return(0);
+}
+#endif /* SIGUSR1 */
+
+#if defined(SIGUSR1)
+/**************************************************************************** **
+ catch a sigusr1 - increase the debug log level.
+ **************************************************************************** */
+int sig_usr1(void)
+{
+ BlockSignals( True, SIGUSR1);
+
+ DEBUGLEVEL++;
+
+ if(DEBUGLEVEL > 10)
+ DEBUGLEVEL = 10;
+
+ DEBUG( 0, ( "Got SIGUSR1 set debug level to %d.\n", DEBUGLEVEL ) );
+
+ BlockSignals( False, SIGUSR1);
+#ifndef DONT_REINSTALL_SIG
+ signal(SIGUSR1, SIGNAL_CAST sig_usr1);
+#endif
+ return(0);
+}
+#endif /* SIGUSR1 */
+
+
/*******************************************************************
get ready for syslog stuff
******************************************************************/
if (!interactive) {
char *p = strrchr(pname,'/');
if (p) pname = p+1;
- openlog(pname, LOG_PID, LOG_DAEMON);
+#ifdef LOG_DAEMON
+ openlog(pname, LOG_PID, SYSLOG_FACILITY);
+#else /* for old systems that have no facility codes. */
+ openlog(pname, LOG_PID);
+#endif
}
#endif
if (interactive) {
****************************************************************************/
void reopen_logs(void)
{
- extern FILE *dbf;
pstring fname;
if (DEBUGLEVEL > 0)
int maxlog;
struct stat st;
- if (debug_count++ < 100) return;
+ if (debug_count++ < 100 || getuid() != 0) return;
maxlog = lp_max_log_size() * 1024;
if (!dbf || maxlog <= 0) return;
char *format_str;
#endif
va_list ap;
-
+ int old_errno = errno;
+
if (stdout_logging) {
#ifdef __STDC__
va_start(ap, format_str);
#endif
vfprintf(dbf,format_str,ap);
va_end(ap);
+ errno = old_errno;
return(0);
}
if (!lp_syslog_only())
#endif
{
- if (!dbf)
- {
- int oldumask = umask(022);
- dbf = fopen(debugf,"w");
- umask(oldumask);
- if (dbf)
- setbuf(dbf,NULL);
- else
- return(0);
- }
+ if (!dbf) {
+ int oldumask = umask(022);
+ dbf = fopen(debugf,"w");
+ umask(oldumask);
+ if (dbf) {
+ setbuf(dbf,NULL);
+ } else {
+ errno = old_errno;
+ return(0);
+ }
+ }
}
#ifdef SYSLOG
check_log_size();
+ errno = old_errno;
+
return(0);
}
/****************************************************************************
mangle a name into netbios format
+
+ Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
****************************************************************************/
-int name_mangle(char *In,char *Out,char name_type)
-{
- fstring name;
- char buf[20];
- char *in = (char *)&buf[0];
- char *out = (char *)Out;
- char *p, *label;
- int i;
+int name_mangle( char *In, char *Out, char name_type )
+ {
+ int i;
+ int c;
+ int len;
+ char buf[20];
+ char *p = Out;
+
+ /* Safely copy the input string, In, into buf[]. */
+ (void)memset( buf, 0, 20 );
+ if( '*' == In[0] )
+ buf[0] = '*';
+ else
+ (void)sprintf( buf, "%-15.15s%c", In, name_type );
- if (In[0] != '*') {
- StrnCpy(name,In,sizeof(name)-1);
- sprintf(buf,"%-15.15s%c",name,name_type);
- } else {
- buf[0]='*';
- memset(&buf[1],0,16);
- }
+ /* Place the length of the first field into the output buffer. */
+ p[0] = 32;
+ p++;
- *out++ = 32;
- for (i=0;i<16;i++) {
- char c = toupper(in[i]);
- out[i*2] = (c>>4) + 'A';
- out[i*2+1] = (c & 0xF) + 'A';
- }
- out[32]=0;
- out += 32;
-
- label = scope;
- while (*label)
+ /* Now convert the name to the rfc1001/1002 format. */
+ for( i = 0; i < 16; i++ )
{
- p = strchr(label, '.');
- if (p == 0)
- p = label + strlen(label);
- *out++ = p - label;
- memcpy(out, label, p - label);
- out += p - label;
- label += p - label + (*p == '.');
+ c = toupper( buf[i] );
+ p[i*2] = ( (c >> 4) & 0x000F ) + 'A';
+ p[(i*2)+1] = (c & 0x000F) + 'A';
+ }
+ p += 32;
+ p[0] = '\0';
+
+ /* Add the scope string. */
+ for( i = 0, len = 0; NULL != scope; i++, len++ )
+ {
+ switch( scope[i] )
+ {
+ case '\0':
+ p[0] = len;
+ if( len > 0 )
+ p[len+1] = 0;
+ return( name_len(Out) );
+ case '.':
+ p[0] = len;
+ p += (len + 1);
+ len = 0;
+ break;
+ default:
+ p[len+1] = scope[i];
+ break;
+ }
}
- *out = 0;
- return(name_len(Out));
-}
+ return( name_len(Out) );
+ } /* name_mangle */
/*******************************************************************
check if a file exists
/*******************************************************************
case insensitive string compararison
********************************************************************/
-int StrCaseCmp(const char *s, const char *t)
+int StrCaseCmp(char *s, char *t)
{
/* compare until we run out of string, either t or s, or find a difference */
/* We *must* use toupper rather than tolower here due to the
asynchronous upper to lower mapping.
*/
- while (*s && *t && toupper(*s) == toupper(*t))
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
+ if(lp_client_code_page() == KANJI_CODEPAGE)
{
- s++; t++;
+ /* Win95 treats full width ascii characters as case sensitive. */
+ int diff;
+ for (;;)
+ {
+ if (!*s || !*t)
+ return toupper (*s) - toupper (*t);
+ else if (is_sj_alph (*s) && is_sj_alph (*t))
+ {
+ diff = sj_toupper2 (*(s+1)) - sj_toupper2 (*(t+1));
+ if (diff)
+ return diff;
+ s += 2;
+ t += 2;
+ }
+ else if (is_shift_jis (*s) && is_shift_jis (*t))
+ {
+ diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t);
+ if (diff)
+ return diff;
+ diff = ((int) (unsigned char) *(s+1)) - ((int) (unsigned char) *(t+1));
+ if (diff)
+ return diff;
+ s += 2;
+ t += 2;
+ }
+ else if (is_shift_jis (*s))
+ return 1;
+ else if (is_shift_jis (*t))
+ return -1;
+ else
+ {
+ diff = toupper (*s) - toupper (*t);
+ if (diff)
+ return diff;
+ s++;
+ t++;
+ }
+ }
}
+ else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+ {
+ while (*s && *t && toupper(*s) == toupper(*t))
+ {
+ s++;
+ t++;
+ }
- return(toupper(*s) - toupper(*t));
+ return(toupper(*s) - toupper(*t));
+ }
}
/*******************************************************************
case insensitive string compararison, length limited
********************************************************************/
-int StrnCaseCmp(const char *s, const char *t, int n)
+int StrnCaseCmp(char *s, char *t, int n)
{
/* compare until we run out of string, either t or s, or chars */
/* We *must* use toupper rather than tolower here due to the
asynchronous upper to lower mapping.
*/
- while (n-- && *s && *t && toupper(*s) == toupper(*t))
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
+ if(lp_client_code_page() == KANJI_CODEPAGE)
{
- s++; t++;
+ /* Win95 treats full width ascii characters as case sensitive. */
+ int diff;
+ for (;n > 0;)
+ {
+ if (!*s || !*t)
+ return toupper (*s) - toupper (*t);
+ else if (is_sj_alph (*s) && is_sj_alph (*t))
+ {
+ diff = sj_toupper2 (*(s+1)) - sj_toupper2 (*(t+1));
+ if (diff)
+ return diff;
+ s += 2;
+ t += 2;
+ n -= 2;
+ }
+ else if (is_shift_jis (*s) && is_shift_jis (*t))
+ {
+ diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t);
+ if (diff)
+ return diff;
+ diff = ((int) (unsigned char) *(s+1)) - ((int) (unsigned char) *(t+1));
+ if (diff)
+ return diff;
+ s += 2;
+ t += 2;
+ n -= 2;
+ }
+ else if (is_shift_jis (*s))
+ return 1;
+ else if (is_shift_jis (*t))
+ return -1;
+ else
+ {
+ diff = toupper (*s) - toupper (*t);
+ if (diff)
+ return diff;
+ s++;
+ t++;
+ n--;
+ }
+ }
+ return 0;
}
+ else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+ {
+ while (n && *s && *t && toupper(*s) == toupper(*t))
+ {
+ s++;
+ t++;
+ n--;
+ }
- /* not run out of chars - strings are different lengths */
- if (n) return(toupper(*s) - toupper(*t));
+ /* not run out of chars - strings are different lengths */
+ if (n)
+ return(toupper(*s) - toupper(*t));
- /* identical up to where we run out of chars, and strings are same length */
- return(0);
+ /* identical up to where we run out of chars,
+ and strings are same length */
+ return(0);
+ }
}
/*******************************************************************
compare 2 strings
********************************************************************/
-BOOL strequal(const char *s1, const char *s2)
+BOOL strequal(char *s1, char *s2)
{
if (s1 == s2) return(True);
if (!s1 || !s2) return(False);
/*******************************************************************
compare 2 strings up to and including the nth char.
******************************************************************/
-BOOL strnequal(const char *s1,const char *s2,int n)
+BOOL strnequal(char *s1,char *s2,int n)
{
if (s1 == s2) return(True);
if (!s1 || !s2 || !n) return(False);
void strlower(char *s)
{
while (*s)
+ {
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
+ if(lp_client_code_page() == KANJI_CODEPAGE)
+ {
+ /* Win95 treats full width ascii characters as case sensitive. */
+ if (is_shift_jis (*s))
+ {
+ if (is_sj_upper (s[0], s[1]))
+ s[1] = sj_tolower2 (s[1]);
+ s += 2;
+ }
+ else if (is_kana (*s))
+ {
+ s++;
+ }
+ else
+ {
+ if (isupper(*s))
+ *s = tolower(*s);
+ s++;
+ }
+ }
+ else
+#endif /* KANJI_WIN95_COMPATIBILITY */
{
-#ifdef KANJI
- if (is_shift_jis (*s)) {
- s += 2;
- } else if (is_kana (*s)) {
- s++;
- } else {
- if (isupper(*s))
- *s = tolower(*s);
- s++;
- }
-#else
if (isupper(*s))
- *s = tolower(*s);
+ *s = tolower(*s);
s++;
-#endif /* KANJI */
}
+ }
}
/*******************************************************************
void strupper(char *s)
{
while (*s)
+ {
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
+ if(lp_client_code_page() == KANJI_CODEPAGE)
+ {
+ /* Win95 treats full width ascii characters as case sensitive. */
+ if (is_shift_jis (*s))
+ {
+ if (is_sj_lower (s[0], s[1]))
+ s[1] = sj_toupper2 (s[1]);
+ s += 2;
+ }
+ else if (is_kana (*s))
+ {
+ s++;
+ }
+ else
+ {
+ if (islower(*s))
+ *s = toupper(*s);
+ s++;
+ }
+ }
+ else
+#endif /* KANJI_WIN95_COMPATIBILITY */
{
-#ifdef KANJI
- if (is_shift_jis (*s)) {
- s += 2;
- } else if (is_kana (*s)) {
- s++;
- } else {
- if (islower(*s))
- *s = toupper(*s);
- s++;
- }
-#else
if (islower(*s))
- *s = toupper(*s);
+ *s = toupper(*s);
s++;
-#endif
}
+ }
}
/*******************************************************************
void string_replace(char *s,char oldc,char newc)
{
while (*s)
+ {
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
+ if(lp_client_code_page() == KANJI_CODEPAGE)
+ {
+ /* Win95 treats full width ascii characters as case sensitive. */
+ if (is_shift_jis (*s))
+ s += 2;
+ else if (is_kana (*s))
+ s++;
+ else
+ {
+ if (oldc == *s)
+ *s = newc;
+ s++;
+ }
+ }
+ else
+#endif /* KANJI_WIN95_COMPATIBILITY */
{
-#ifdef KANJI
- if (is_shift_jis (*s)) {
- s += 2;
- } else if (is_kana (*s)) {
- s++;
- } else {
- if (oldc == *s)
- *s = newc;
- s++;
- }
-#else
if (oldc == *s)
- *s = newc;
+ *s = newc;
s++;
-#endif /* KANJI */
}
+ }
}
/****************************************************************************
if (*fname == '/')
{
- strcpy(namecopy,fname);
+ pstrcpy(namecopy,fname);
strcpy(fname,".");
strcat(fname,namecopy);
}
void show_msg(char *buf)
{
int i;
- int j;
int bcc=0;
- if (DEBUGLEVEL < 5)
- return;
+
+ if (DEBUGLEVEL < 5) return;
DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
smb_len(buf),
(int)SVAL(buf,smb_uid),
(int)SVAL(buf,smb_mid),
(int)CVAL(buf,smb_wct)));
+
for (i=0;i<(int)CVAL(buf,smb_wct);i++)
DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i,
SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
+
bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
DEBUG(5,("smb_bcc=%d\n",bcc));
- if (DEBUGLEVEL < 10)
- return;
- for (i = 0; i < MIN(bcc, 256); i += 16)
- {
- for (j = 0; j < 16 && i+j < MIN(bcc,256); j++)
- {
-
- DEBUG(10,("%2X ",CVAL(smb_buf(buf),i+j)));
- if (j == 7) DEBUG(10, (" "));
-
- }
- DEBUG(10,(" "));
- for (j = 0; j < 16 && i+j < MIN(bcc,256); j++)
- {
- unsigned char c = CVAL(smb_buf(buf),i+j);
- if (c < 32 || c > 128) c = '.';
- DEBUG(10,("%c",c));
-
- if (j == 7) DEBUG(10, (" "));
- }
+ if (DEBUGLEVEL < 10) return;
- DEBUG(10,("\n"));
- }
+ dump_data(10, smb_buf(buf), MIN(bcc, 512));
}
/*******************************************************************
pstring s1;
*p = 0;
- strcpy(s1,p+3);
+ pstrcpy(s1,p+3);
if ((p=strrchr(s,'\\')) != NULL)
*p = 0;
pstring s1;
*p = 0;
- strcpy(s1,p+3);
+ pstrcpy(s1,p+3);
if ((p=strrchr(s,'/')) != NULL)
*p = 0;
DEBUG(3,("chdir to %s\n",path));
res = sys_chdir(path);
if (!res)
- strcpy(LastDir,path);
+ pstrcpy(LastDir,path);
return(res);
}
-
-/*******************************************************************
- return the absolute current directory path. A dumb version.
-********************************************************************/
-static char *Dumb_GetWd(char *s)
-{
- char *p;
-#ifdef USE_GETCWD
- p = (char *)getcwd(s,sizeof(pstring));
-#else
- p = (char *)getwd(s));
-#endif
- if(!p)
- return NULL;
-
- /* Ensure we always return in dos format. */
- unix_to_dos(p,True);
- return p;
-}
-
-
/* number of list structures for a caching GetWd function. */
#define MAX_GETWDCACHE (50)
*s = 0;
if (!use_getwd_cache)
- return(Dumb_GetWd(str));
+ return(sys_getwd(str));
/* init the cache */
if (!getwd_cache_init)
if (stat(".",&st) == -1)
{
DEBUG(0,("Very strange, couldn't stat \".\"\n"));
- return(Dumb_GetWd(str));
+ return(sys_getwd(str));
}
The very slow getcwd, which spawns a process on some systems, or the
not quite so bad getwd. */
- if (!Dumb_GetWd(s))
+ if (!sys_getwd(s))
{
- DEBUG(0,("Getwd failed, errno %d\n",errno));
+ DEBUG(0,("Getwd failed, errno %s\n",strerror(errno)));
return (NULL);
}
#else
pstring dir2;
pstring wd;
- pstring basename;
+ pstring base_name;
pstring newname;
char *p=NULL;
BOOL relative = (*s != '/');
- *dir2 = *wd = *basename = *newname = 0;
+ *dir2 = *wd = *base_name = *newname = 0;
if (widelinks)
{
/* remove any double slashes */
string_sub(s,"//","/");
- strcpy(basename,s);
- p = strrchr(basename,'/');
+ pstrcpy(base_name,s);
+ p = strrchr(base_name,'/');
if (!p)
return(True);
}
- if (p && (p != basename))
+ if (p && (p != base_name))
{
*p = 0;
if (strcmp(p+1,".")==0)
*p = '/';
}
- if (ChDir(basename) != 0)
+ if (ChDir(base_name) != 0)
{
ChDir(wd);
- DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,basename));
+ DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name));
return(False);
}
return(False);
}
- if (p && (p != basename))
+ if (p && (p != base_name))
{
strcat(newname,"/");
strcat(newname,p+1);
if (relative)
{
if (newname[l] == '/')
- strcpy(s,newname + l + 1);
+ pstrcpy(s,newname + l + 1);
else
- strcpy(s,newname+l);
+ pstrcpy(s,newname+l);
}
else
- strcpy(s,newname);
+ pstrcpy(s,newname);
}
ChDir(wd);
int lfill = (len+1) - strlen(Mask);
int l1= (p1 - Mask);
pstring tmp;
- strcpy(tmp,Mask);
+ pstrcpy(tmp,Mask);
memset(tmp+l1,'?',lfill);
- strcpy(tmp + l1 + lfill,Mask + l1 + 1);
- strcpy(Mask,tmp);
+ pstrcpy(tmp + l1 + lfill,Mask + l1 + 1);
+ pstrcpy(Mask,tmp);
}
}
filename_dos(Mask,filepart);
- strcpy(mbeg,filepart);
+ pstrcpy(mbeg,filepart);
if ((p1 = strchr(mbeg,'.')) != NULL)
{
hasdot = True;
*p1 = 0;
p1++;
- strcpy(mext,p1);
+ pstrcpy(mext,p1);
}
else
{
strcpy(mext,"");
if (strlen(mbeg) > 8)
{
- strcpy(mext,mbeg + 8);
+ pstrcpy(mext,mbeg + 8);
mbeg[8] = 0;
}
}
if (*mext)
expand_one(mext,3);
- strcpy(Mask,dirpart);
+ pstrcpy(Mask,dirpart);
if (*dirpart || absolute) strcat(Mask,"\\");
strcat(Mask,mbeg);
strcat(Mask,".");
BOOL strhasupper(char *s)
{
while (*s)
+ {
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
+ if(lp_client_code_page() == KANJI_CODEPAGE)
{
-#ifdef KANJI
- if (is_shift_jis (*s)) {
- s += 2;
- } else if (is_kana (*s)) {
- s++;
- } else {
- if (isupper(*s)) return(True);
- s++;
- }
-#else
- if (isupper(*s)) return(True);
+ /* Win95 treats full width ascii characters as case sensitive. */
+ if (is_shift_jis (*s))
+ s += 2;
+ else if (is_kana (*s))
+ s++;
+ else
+ {
+ if (isupper(*s))
+ return(True);
+ s++;
+ }
+ }
+ else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+ {
+ if (isupper(*s))
+ return(True);
s++;
-#endif /* KANJI */
}
+ }
return(False);
}
BOOL strhaslower(char *s)
{
while (*s)
+ {
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
+ if(lp_client_code_page() == KANJI_CODEPAGE)
{
-#ifdef KANJI
- if (is_shift_jis (*s)) {
- s += 2;
- } else if (is_kana (*s)) {
- s++;
- } else {
- if (islower(*s)) return(True);
- s++;
- }
-#else
- if (islower(*s)) return(True);
+ /* Win95 treats full width ascii characters as case sensitive. */
+ if (is_shift_jis (*s))
+ {
+ if (is_sj_upper (s[0], s[1]))
+ return(True);
+ if (is_sj_lower (s[0], s[1]))
+ return (True);
+ s += 2;
+ }
+ else if (is_kana (*s))
+ {
+ s++;
+ }
+ else
+ {
+ if (islower(*s))
+ return(True);
+ s++;
+ }
+ }
+ else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+ {
+ if (islower(*s))
+ return(True);
s++;
-#endif /* KANJI */
}
+ }
return(False);
}
int count_chars(char *s,char c)
{
int count=0;
- while (*s)
+
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
+ if(lp_client_code_page() == KANJI_CODEPAGE)
+ {
+ /* Win95 treats full width ascii characters as case sensitive. */
+ while (*s)
+ {
+ if (is_shift_jis (*s))
+ s += 2;
+ else
+ {
+ if (*s == c)
+ count++;
+ s++;
+ }
+ }
+ }
+ else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+ {
+ while (*s)
{
if (*s == c)
- count++;
+ count++;
s++;
}
+ }
return(count);
}
char *p;
pstring mask2;
- strcpy(mask2,mask);
+ pstrcpy(mask2,mask);
if ((mode & aDIR) != 0)
size = 0;
ret = write_data(fd,buf,len);
DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,len,ret));
+ if(ret <= 0)
+ DEBUG(0,("write_socket: Error writing %d bytes to socket %d: ERRNO = %s\n",
+ len, fd, strerror(errno) ));
+
return(ret);
}
int read_udp_socket(int fd,char *buf,int len)
{
int ret;
- struct sockaddr sock;
+ struct sockaddr_in sock;
int socklen;
socklen = sizeof(sock);
bzero((char *)&sock,socklen);
bzero((char *)&lastip,sizeof(lastip));
- ret = recvfrom(fd,buf,len,0,&sock,&socklen);
+ ret = recvfrom(fd,buf,len,0,(struct sockaddr *)&sock,&socklen);
if (ret <= 0) {
- DEBUG(2,("read socket failed. ERRNO=%d\n",errno));
+ DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno)));
return(0);
}
- lastip = *(struct in_addr *) &sock.sa_data[2];
- lastport = ntohs(((struct sockaddr_in *)&sock)->sin_port);
+ lastip = sock.sin_addr;
+ lastport = ntohs(sock.sin_port);
+
+ DEBUG(10,("read_udp_socket: lastip %s lastport %d read: %d\n",
+ inet_ntoa(lastip), lastport, ret));
return(ret);
}
/****************************************************************************
read 4 bytes of a smb packet and return the smb length of the packet
-possibly store the result in the buffer
+store the result in the buffer
+This version of the function will return a length of zero on receiving
+a keepalive packet.
****************************************************************************/
-int read_smb_length(int fd,char *inbuf,int timeout)
+static int read_smb_length_return_keepalive(int fd,char *inbuf,int timeout)
{
- char *buffer;
- char buf[4];
int len=0, msg_type;
BOOL ok=False;
- if (inbuf)
- buffer = inbuf;
- else
- buffer = buf;
-
while (!ok)
{
if (timeout > 0)
- ok = (read_with_timeout(fd,buffer,4,4,timeout) == 4);
+ ok = (read_with_timeout(fd,inbuf,4,4,timeout) == 4);
else
- ok = (read_data(fd,buffer,4) == 4);
+ ok = (read_data(fd,inbuf,4) == 4);
if (!ok)
return(-1);
- len = smb_len(buffer);
- msg_type = CVAL(buffer,0);
+ len = smb_len(inbuf);
+ msg_type = CVAL(inbuf,0);
if (msg_type == 0x85)
- {
- DEBUG(5,("Got keepalive packet\n"));
- ok = False;
- }
+ DEBUG(5,("Got keepalive packet\n"));
}
DEBUG(10,("got smb length of %d\n",len));
return(len);
}
+/****************************************************************************
+read 4 bytes of a smb packet and return the smb length of the packet
+store the result in the buffer. This version of the function will
+never return a session keepalive (length of zero).
+****************************************************************************/
+int read_smb_length(int fd,char *inbuf,int timeout)
+{
+ int len;
+
+ for(;;)
+ {
+ len = read_smb_length_return_keepalive(fd, inbuf, timeout);
+
+ if(len < 0)
+ return len;
+ /* Ignore session keepalives. */
+ if(CVAL(inbuf,0) != 0x85)
+ break;
+ }
+
+ return len;
+}
/****************************************************************************
- read an smb from a fd and return it's length
-The timeout is in milli seconds
+ read an smb from a fd. Note that the buffer *MUST* be of size
+ BUFFER_SIZE+SAFETY_MARGIN.
+ The timeout is in milli seconds.
+
+ This function will return on a
+ receipt of a session keepalive packet.
****************************************************************************/
-BOOL receive_smb(int fd,char *buffer,int timeout)
+BOOL receive_smb(int fd,char *buffer, int timeout)
{
int len,ret;
bzero(buffer,smb_size + 100);
- len = read_smb_length(fd,buffer,timeout);
- if (len == -1)
+ len = read_smb_length_return_keepalive(fd,buffer,timeout);
+ if (len < 0)
return(False);
if (len > BUFFER_SIZE) {
exit(1);
}
- ret = read_data(fd,buffer+4,len);
- if (ret != len) {
- smb_read_error = READ_ERROR;
- return False;
+ if(len > 0) {
+ ret = read_data(fd,buffer+4,len);
+ if (ret != len) {
+ smb_read_error = READ_ERROR;
+ return False;
+ }
}
-
return(True);
}
-
/****************************************************************************
- send an smb to a fd
+ read an smb from a fd ignoring all keepalive packets. Note that the buffer
+ *MUST* be of size BUFFER_SIZE+SAFETY_MARGIN.
+ The timeout is in milli seconds
+
+ This is exactly the same as receive_smb except that it never returns
+ a session keepalive packet (just as receive_smb used to do).
+ receive_smb was changed to return keepalives as the oplock processing means this call
+ should never go into a blocking read.
****************************************************************************/
-BOOL send_smb(int fd,char *buffer)
+
+BOOL client_receive_smb(int fd,char *buffer, int timeout)
{
- int len;
- int ret,nwritten=0;
- len = smb_len(buffer) + 4;
+ BOOL ret;
- while (nwritten < len)
- {
- ret = write_socket(fd,buffer+nwritten,len - nwritten);
- if (ret <= 0)
- {
+ for(;;)
+ {
+ ret = receive_smb(fd, buffer, timeout);
+
+ if(ret == False)
+ return ret;
+
+ /* Ignore session keepalive packets. */
+ if(CVAL(buffer,0) != 0x85)
+ break;
+ }
+ return ret;
+}
+
+/****************************************************************************
+ read a message from a udp fd.
+The timeout is in milli seconds
+****************************************************************************/
+BOOL receive_local_message(int fd, char *buffer, int buffer_len, int timeout)
+{
+ struct sockaddr_in from;
+ int fromlen = sizeof(from);
+ int32 msg_len = 0;
+
+ if(timeout != 0)
+ {
+ struct timeval to;
+ fd_set fds;
+ int selrtn;
+
+ FD_ZERO(&fds);
+ FD_SET(fd,&fds);
+
+ to.tv_sec = timeout / 1000;
+ to.tv_usec = (timeout % 1000) * 1000;
+
+ selrtn = sys_select(&fds,&to);
+
+ /* Check if error */
+ if(selrtn == -1)
+ {
+ /* something is wrong. Maybe the socket is dead? */
+ smb_read_error = READ_ERROR;
+ return False;
+ }
+
+ /* Did we timeout ? */
+ if (selrtn == 0)
+ {
+ smb_read_error = READ_TIMEOUT;
+ return False;
+ }
+ }
+
+ /*
+ * Read a loopback udp message.
+ */
+ msg_len = recvfrom(fd, &buffer[UDP_CMD_HEADER_LEN],
+ buffer_len - UDP_CMD_HEADER_LEN, 0,
+ (struct sockaddr *)&from, &fromlen);
+
+ if(msg_len < 0)
+ {
+ DEBUG(0,("receive_local_message. Error in recvfrom. (%s).\n",strerror(errno)));
+ return False;
+ }
+
+ /* Validate message length. */
+ if(msg_len > (buffer_len - UDP_CMD_HEADER_LEN))
+ {
+ DEBUG(0,("receive_local_message: invalid msg_len (%d) max can be %d\n",
+ msg_len,
+ buffer_len - UDP_CMD_HEADER_LEN));
+ return False;
+ }
+
+ /* Validate message from address (must be localhost). */
+ if(from.sin_addr.s_addr != htonl(INADDR_LOOPBACK))
+ {
+ DEBUG(0,("receive_local_message: invalid 'from' address \
+(was %x should be 127.0.0.1\n", from.sin_addr.s_addr));
+ return False;
+ }
+
+ /* Setup the message header */
+ SIVAL(buffer,UDP_CMD_LEN_OFFSET,msg_len);
+ SSVAL(buffer,UDP_CMD_PORT_OFFSET,ntohs(from.sin_port));
+
+ return True;
+}
+
+/****************************************************************************
+ structure to hold a linked list of local messages.
+ for processing.
+****************************************************************************/
+
+typedef struct _message_list {
+ struct _message_list *msg_next;
+ char *msg_buf;
+ int msg_len;
+} pending_message_list;
+
+static pending_message_list *smb_msg_head = NULL;
+
+/****************************************************************************
+ Function to push a linked list of local messages ready
+ for processing.
+****************************************************************************/
+
+static BOOL push_local_message(pending_message_list **pml, char *buf, int msg_len)
+{
+ pending_message_list *msg = (pending_message_list *)
+ malloc(sizeof(pending_message_list));
+
+ if(msg == NULL)
+ {
+ DEBUG(0,("push_message: malloc fail (1)\n"));
+ return False;
+ }
+
+ msg->msg_buf = (char *)malloc(msg_len);
+ if(msg->msg_buf == NULL)
+ {
+ DEBUG(0,("push_local_message: malloc fail (2)\n"));
+ free((char *)msg);
+ return False;
+ }
+
+ memcpy(msg->msg_buf, buf, msg_len);
+ msg->msg_len = msg_len;
+
+ msg->msg_next = *pml;
+ *pml = msg;
+
+ return True;
+}
+
+/****************************************************************************
+ Function to push a linked list of local smb messages ready
+ for processing.
+****************************************************************************/
+
+BOOL push_smb_message(char *buf, int msg_len)
+{
+ return push_local_message(&smb_msg_head, buf, msg_len);
+}
+
+/****************************************************************************
+ Do a select on an two fd's - with timeout.
+
+ If a local udp message has been pushed onto the
+ queue (this can only happen during oplock break
+ processing) return this first.
+
+ If a pending smb message has been pushed onto the
+ queue (this can only happen during oplock break
+ processing) return this next.
+
+ If the first smbfd is ready then read an smb from it.
+ if the second (loopback UDP) fd is ready then read a message
+ from it and setup the buffer header to identify the length
+ and from address.
+ Returns False on timeout or error.
+ Else returns True.
+
+The timeout is in milli seconds
+****************************************************************************/
+BOOL receive_message_or_smb(int smbfd, int oplock_fd,
+ char *buffer, int buffer_len,
+ int timeout, BOOL *got_smb)
+{
+ fd_set fds;
+ int selrtn;
+ struct timeval to;
+
+ *got_smb = False;
+
+ /*
+ * Check to see if we already have a message on the smb queue.
+ * If so - copy and return it.
+ */
+
+ if(smb_msg_head)
+ {
+ pending_message_list *msg = smb_msg_head;
+ memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len));
+ smb_msg_head = msg->msg_next;
+
+ /* Free the message we just copied. */
+ free((char *)msg->msg_buf);
+ free((char *)msg);
+ *got_smb = True;
+
+ DEBUG(5,("receive_message_or_smb: returning queued smb message.\n"));
+ return True;
+ }
+
+ FD_ZERO(&fds);
+ FD_SET(smbfd,&fds);
+ FD_SET(oplock_fd,&fds);
+
+ to.tv_sec = timeout / 1000;
+ to.tv_usec = (timeout % 1000) * 1000;
+
+ selrtn = sys_select(&fds,timeout>0?&to:NULL);
+
+ /* Check if error */
+ if(selrtn == -1) {
+ /* something is wrong. Maybe the socket is dead? */
+ smb_read_error = READ_ERROR;
+ return False;
+ }
+
+ /* Did we timeout ? */
+ if (selrtn == 0) {
+ smb_read_error = READ_TIMEOUT;
+ return False;
+ }
+
+ if (FD_ISSET(smbfd,&fds))
+ {
+ *got_smb = True;
+ return receive_smb(smbfd, buffer, 0);
+ }
+ else
+ {
+ return receive_local_message(oplock_fd, buffer, buffer_len, 0);
+ }
+}
+
+/****************************************************************************
+ send an smb to a fd
+****************************************************************************/
+BOOL send_smb(int fd,char *buffer)
+{
+ int len;
+ int ret,nwritten=0;
+ len = smb_len(buffer) + 4;
+
+ while (nwritten < len)
+ {
+ ret = write_socket(fd,buffer+nwritten,len - nwritten);
+ if (ret <= 0)
+ {
DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret));
close_sockets();
exit(1);
strcpy(name,"");
if (d < -50 || d > 50) return(0);
return(name_interpret(p,name));
-}
+}
-
/****************************************************************************
return the total storage length of a mangled name
****************************************************************************/
-int name_len(char *s)
-{
- char *s0=s;
- unsigned char c = *(unsigned char *)s;
- if ((c & 0xC0) == 0xC0)
+int name_len( char *s )
+ {
+ int len;
+
+ /* If the two high bits of the byte are set, return 2. */
+ if( 0xC0 == (*(unsigned char *)s & 0xC0) )
return(2);
- while (*s) s += (*s)+1;
- return(PTR_DIFF(s,s0)+1);
-}
+
+ /* Add up the length bytes. */
+ for( len = 1; (*s); s += (*s) + 1 )
+ {
+ len += *s + 1;
+ }
+
+ return( len );
+ } /* name_len */
/****************************************************************************
send a single packet to a port on another machine
ret = (sendto(out_fd,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
if (!ret)
- DEBUG(0,("Packet send to %s(%d) failed ERRNO=%d\n",
- inet_ntoa(ip),port,errno));
+ DEBUG(0,("Packet send to %s(%d) failed ERRNO=%s\n",
+ inet_ntoa(ip),port,strerror(errno)));
close(out_fd);
return(ret);
}
else
{
- *dest = (char *)malloc(l+1);
+ (*dest) = (char *)malloc(l+1);
+ if ((*dest) == NULL) {
+ DEBUG(0,("Out of memory in string_init\n"));
+ return False;
+ }
+
strcpy(*dest,src);
}
return(True);
if (strequal(p1,"*")) return(True);
- DEBUG(5,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
+ DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
if (trans2) {
- strcpy(ebase,p1);
- strcpy(sbase,p2);
+ fstrcpy(ebase,p1);
+ fstrcpy(sbase,p2);
} else {
if ((p=strrchr(p1,'.'))) {
*p = 0;
- strcpy(ebase,p1);
- strcpy(eext,p+1);
+ fstrcpy(ebase,p1);
+ fstrcpy(eext,p+1);
} else {
- strcpy(ebase,p1);
+ fstrcpy(ebase,p1);
eext[0] = 0;
}
if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
*p = 0;
- strcpy(sbase,p2);
- strcpy(sext,p+1);
+ fstrcpy(sbase,p2);
+ fstrcpy(sext,p+1);
} else {
- strcpy(sbase,p2);
- strcpy(sext,"");
+ fstrcpy(sbase,p2);
+ fstrcpy(sext,"");
}
}
matched = do_match(sbase,ebase,case_sig) &&
(trans2 || do_match(sext,eext,case_sig));
- DEBUG(5,("mask_match returning %d\n", matched));
+ DEBUG(8,("mask_match returning %d\n", matched));
return matched;
}
{
#ifndef NO_FORK_DEBUG
if (fork())
- exit(0);
+ _exit(0);
/* detach from the terminal */
#ifdef USE_SETSID
char *p = strchr(hostname,'.');
if (p) *p = 0;
- strcpy(my_name,hostname);
+ fstrcpy(my_name,hostname);
}
if (ip)
bzero((char *)&sock,sizeof(sock));
memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
-#if defined(__FreeBSD__) || defined(NETBSD) /* XXX not the right ifdef */
+#if defined(__FreeBSD__) || defined(NETBSD) || defined(__OpenBSD__) /* XXX not the right ifdef */
sock.sin_len = sizeof(sock);
#endif
sock.sin_port = htons( port );
{
if (port) {
if (port == SMB_PORT || port == NMB_PORT)
- DEBUG(dlevel,("bind failed on port %d socket_addr=%x (%s)\n",
- port,socket_addr,strerror(errno)));
+ DEBUG(dlevel,("bind failed on port %d socket_addr=%s (%s)\n",
+ port,inet_ntoa(sock.sin_addr),strerror(errno)));
close(res);
if (dlevel > 0 && port < 1000)
DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
return 0;
}
+ if(hp->h_addr == NULL) {
+ DEBUG(3,("Get_Hostbyname: host address is invalid for host %s.\n",str));
+ return 0;
+ }
putip((char *)&res,(char *)hp->h_addr);
}
/*******************************************************************
return the DNS name of the client
******************************************************************/
-char *client_name(void)
+char *client_name(int fd)
{
- extern int Client;
- struct sockaddr sa;
- struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
- int length = sizeof(sa);
- static pstring name_buf;
- struct hostent *hp;
+ struct sockaddr sa;
+ struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
+ int length = sizeof(sa);
+ static pstring name_buf;
+ struct hostent *hp;
+ static int last_fd=-1;
+
+ if (global_client_name_done && last_fd == fd)
+ return name_buf;
+
+ last_fd = fd;
+ global_client_name_done = False;
+
+ strcpy(name_buf,"UNKNOWN");
+
+ if (fd == -1) {
+ return name_buf;
+ }
+
+ if (getpeername(fd, &sa, &length) < 0) {
+ DEBUG(0,("getpeername failed\n"));
+ return name_buf;
+ }
+
+ /* Look up the remote host name. */
+ if ((hp = gethostbyaddr((char *) &sockin->sin_addr,
+ sizeof(sockin->sin_addr),
+ AF_INET)) == 0) {
+ DEBUG(1,("Gethostbyaddr failed for %s\n",client_addr(fd)));
+ StrnCpy(name_buf,client_addr(fd),sizeof(name_buf) - 1);
+ } else {
+ StrnCpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1);
+ if (!matchname(name_buf, sockin->sin_addr)) {
+ DEBUG(0,("Matchname failed on %s %s\n",name_buf,client_addr(fd)));
+ strcpy(name_buf,"UNKNOWN");
+ }
+ }
+ global_client_name_done = True;
+ return name_buf;
+}
+
+/*******************************************************************
+ return the IP addr of the client as a string
+ ******************************************************************/
+char *client_addr(int fd)
+{
+ struct sockaddr sa;
+ struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
+ int length = sizeof(sa);
+ static fstring addr_buf;
+ static int last_fd = -1;
+
+ if (global_client_addr_done && fd == last_fd)
+ return addr_buf;
+
+ last_fd = fd;
+ global_client_addr_done = False;
+
+ strcpy(addr_buf,"0.0.0.0");
+
+ if (fd == -1) {
+ return addr_buf;
+ }
+
+ if (getpeername(fd, &sa, &length) < 0) {
+ DEBUG(0,("getpeername failed\n"));
+ return addr_buf;
+ }
+
+ fstrcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr));
+
+ global_client_addr_done = True;
+ return addr_buf;
+}
- if (global_client_name_done)
- return name_buf;
+/*******************************************************************
+ Patch from jkf@soton.ac.uk
+ Split Luke's automount_server into YP lookup and string splitter
+ so can easily implement automount_path().
+ As we may end up doing both, cache the last YP result.
+*******************************************************************/
+
+#if (defined(NETGROUP) && defined(AUTOMOUNT))
+static char *automount_lookup(char *user_name)
+{
+ static fstring last_key = "";
+ static pstring last_value = "";
- strcpy(name_buf,"UNKNOWN");
+ int nis_error; /* returned by yp all functions */
+ char *nis_result; /* yp_match inits this */
+ int nis_result_len; /* and set this */
+ char *nis_domain; /* yp_get_default_domain inits this */
+ char *nis_map = (char *)lp_nis_home_map_name();
- if (getpeername(Client, &sa, &length) < 0) {
- DEBUG(0,("getpeername failed\n"));
- return name_buf;
+ if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
+ {
+ DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
+ return last_value;
}
- /* Look up the remote host name. */
- if ((hp = gethostbyaddr((char *) &sockin->sin_addr,
- sizeof(sockin->sin_addr),
- AF_INET)) == 0) {
- DEBUG(1,("Gethostbyaddr failed for %s\n",client_addr()));
- StrnCpy(name_buf,client_addr(),sizeof(name_buf) - 1);
- } else {
- StrnCpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1);
- if (!matchname(name_buf, sockin->sin_addr)) {
- DEBUG(0,("Matchname failed on %s %s\n",name_buf,client_addr()));
- strcpy(name_buf,"UNKNOWN");
+ DEBUG(5, ("NIS Domain: %s\n", nis_domain));
+
+ if (!strcmp(user_name, last_key))
+ {
+ nis_result = last_value;
+ nis_result_len = strlen(last_value);
+ nis_error = 0;
+ }
+ else
+ {
+ if ((nis_error = yp_match(nis_domain, nis_map,
+ user_name, strlen(user_name),
+ &nis_result, &nis_result_len)) != 0)
+ {
+ DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
+ yperr_string(nis_error), user_name, nis_map));
+ }
+ if (!nis_error && nis_result_len >= sizeof(pstring))
+ {
+ nis_result_len = sizeof(pstring)-1;
}
+ fstrcpy(last_key, user_name);
+ strncpy(last_value, nis_result, nis_result_len);
+ last_value[nis_result_len] = '\0';
}
- global_client_name_done = True;
- return name_buf;
+
+ DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
+ return last_value;
}
+#endif
/*******************************************************************
- return the IP addr of the client as a string
- ******************************************************************/
-char *client_addr(void)
+ Patch from jkf@soton.ac.uk
+ This is Luke's original function with the NIS lookup code
+ moved out to a separate function.
+*******************************************************************/
+
+char *automount_server(char *user_name)
{
- extern int Client;
- struct sockaddr sa;
- struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
- int length = sizeof(sa);
- static fstring addr_buf;
+ static pstring server_name;
- if (global_client_addr_done)
- return addr_buf;
+#if (defined(NETGROUP) && defined (AUTOMOUNT))
+ int home_server_len;
- strcpy(addr_buf,"0.0.0.0");
+ /* set to default of local machine */
+ pstrcpy(server_name, local_machine);
- if (getpeername(Client, &sa, &length) < 0) {
- DEBUG(0,("getpeername failed\n"));
- return addr_buf;
- }
+ if (lp_nis_home_map())
+ {
+ char *automount_value = automount_lookup(user_name);
+ home_server_len = strcspn(automount_value,":");
+ DEBUG(5, ("NIS lookup succeeded. Home server length: %d\n",home_server_len));
+ if (home_server_len > sizeof(pstring))
+ {
+ home_server_len = sizeof(pstring);
+ }
+ strncpy(server_name, automount_value, home_server_len);
+ server_name[home_server_len] = '\0';
+ }
+#else
+ /* use the local machine name instead of the auto-map server */
+ pstrcpy(server_name, local_machine);
+#endif
+
+ DEBUG(4,("Home server: %s\n", server_name));
+
+ return server_name;
+}
- strcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr));
+/*******************************************************************
+ Patch from jkf@soton.ac.uk
+ Added this to implement %p (NIS auto-map version of %H)
+*******************************************************************/
+
+char *automount_path(char *user_name)
+{
+ static pstring server_path;
+
+#if (defined(NETGROUP) && defined (AUTOMOUNT))
+ char *home_path_start;
- global_client_addr_done = True;
- return addr_buf;
+ /* set to default of no string */
+ server_path[0] = 0;
+
+ if (lp_nis_home_map())
+ {
+ char *automount_value = automount_lookup(user_name);
+ home_path_start = strchr(automount_value,':');
+ if (home_path_start != NULL)
+ {
+ DEBUG(5, ("NIS lookup succeeded. Home path is: %s\n",
+ home_path_start?(home_path_start+1):""));
+ strcpy(server_path, home_path_start+1);
+ }
+ }
+#else
+ /* use the passwd entry instead of the auto-map server entry */
+ /* pstrcpy() copes with get_home_dir() returning NULL */
+ pstrcpy(server_path, get_home_dir(user_name));
+#endif
+
+ DEBUG(4,("Home server path: %s\n", server_path));
+
+ return server_path;
}
+
/*******************************************************************
sub strings with useful parameters
Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
Paul Rippin <pr3245@nopc.eurostat.cec.be>
********************************************************************/
-void standard_sub_basic(char *string)
+void standard_sub_basic(char *str)
{
- char *s, *p;
- char pidstr[10];
- struct passwd *pass;
+ char *s, *p;
+ char pidstr[10];
+ struct passwd *pass;
+ char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user;
- for (s = string ; (p = strchr(s,'%')) != NULL ; s = p )
- {
- switch (*(p+1))
- {
- case 'G' : if ((pass = Get_Pwnam(sesssetup_user,False))!=NULL)
- string_sub(p,"%G",gidtoname(pass->pw_gid));
- else
- p += 2;
- break;
- case 'I' : string_sub(p,"%I",client_addr()); break;
- case 'L' : string_sub(p,"%L",local_machine); break;
- case 'M' : string_sub(p,"%M",client_name()); break;
- case 'R' : string_sub(p,"%R",remote_proto); break;
- case 'T' : string_sub(p,"%T",timestring()); break;
- case 'U' : string_sub(p,"%U",sesssetup_user); break;
- case 'a' : string_sub(p,"%a",remote_arch); break;
- case 'd' : sprintf(pidstr,"%d",(int)getpid());
- string_sub(p,"%d",pidstr);
- break;
- case 'h' : string_sub(p,"%h",myhostname); break;
- case 'm' : string_sub(p,"%m",remote_machine); break;
- case 'v' : string_sub(p,"%v",VERSION); break;
- case '\0' : p++; break; /* don't run off end if last character is % */
- default : p+=2; break;
- }
- }
- return;
+ for (s = str ; s && *s && (p = strchr(s,'%')); s = p )
+ {
+ switch (*(p+1))
+ {
+ case 'G' :
+ {
+ if ((pass = Get_Pwnam(sesssetup_user,False))!=NULL)
+ {
+ string_sub(p,"%G",gidtoname(pass->pw_gid));
+ }
+ else
+ {
+ p += 2;
+ }
+ break;
+ }
+ case 'N' : string_sub(p,"%N", automount_server(username)); break;
+ case 'I' : string_sub(p,"%I", client_addr(Client)); break;
+ case 'L' : string_sub(p,"%L", local_machine); break;
+ case 'M' : string_sub(p,"%M", client_name(Client)); break;
+ case 'R' : string_sub(p,"%R", remote_proto); break;
+ case 'T' : string_sub(p,"%T", timestring()); break;
+ case 'U' : string_sub(p,"%U", username); break;
+ case 'a' : string_sub(p,"%a", remote_arch); break;
+ case 'd' :
+ {
+ sprintf(pidstr,"%d",(int)getpid());
+ string_sub(p,"%d", pidstr);
+ break;
+ }
+ case 'h' : string_sub(p,"%h", myhostname); break;
+ case 'm' : string_sub(p,"%m", remote_machine); break;
+ case 'v' : string_sub(p,"%v", VERSION); break;
+ case '$' : /* Expand environment variables */
+ {
+ /* Contributed by Branko Cibej <branko.cibej@hermes.si> */
+ fstring envname;
+ char *envval;
+ char *q, *r;
+ int copylen;
+
+ if (*(p+2) != '(') { p+=2; break; }
+ if ((q = strchr(p,')')) == NULL)
+ {
+ DEBUG(0,("standard_sub_basic: Unterminated environment \
+variable [%s]\n", p));
+ p+=2; break;
+ }
+
+ r = p+3;
+ copylen = MIN((q-r),(sizeof(envname)-1));
+ strncpy(envname,r,copylen);
+ envname[copylen] = '\0';
+ if ((envval = getenv(envname)) == NULL)
+ {
+ DEBUG(0,("standard_sub_basic: Environment variable [%s] not set\n",
+ envname));
+ p+=2; break;
+ }
+ copylen = MIN((q+1-p),(sizeof(envname)-1));
+ strncpy(envname,p,copylen);
+ envname[copylen] = '\0';
+ string_sub(p,envname,envval);
+ break;
+ }
+ case '\0': p++; break; /* don't run off end if last character is % */
+ default : p+=2; break;
+ }
+ }
+ return;
}
/*******************************************************************
exit(0);
}
+
+ /*
+ * This next test is redundent and causes some systems (with
+ * broken isalnum() calls) problems.
+ * JRA.
+ */
+
+#if 0
if (!isalnum(*name2))
{
free(name2);
return(NULL);
}
+#endif /* 0 */
ret = sys_gethostbyname(name2);
if (ret != NULL)
****************************************************************************/
BOOL process_exists(int pid)
{
-#ifdef LINUX
- fstring s;
- sprintf(s,"/proc/%d",pid);
- return(directory_exist(s,NULL));
-#else
- {
- static BOOL tested=False;
- static BOOL ok=False;
- fstring s;
- if (!tested) {
- tested = True;
- sprintf(s,"/proc/%05d",(int)getpid());
- ok = file_exist(s,NULL);
- }
- if (ok) {
- sprintf(s,"/proc/%05d",pid);
- return(file_exist(s,NULL));
- }
- }
-
- /* CGH 8/16/96 - added ESRCH test */
- return(pid == getpid() || kill(pid,0) == 0 || errno != ESRCH);
-#endif
+ return(kill(pid,0) == 0 || errno != ESRCH);
}
********************************************************************/
void ajt_panic(void)
{
- system("/usr/bin/X11/xedit -display ljus:0 /tmp/ERROR_FAULT");
+ system("/usr/bin/X11/xedit -display solen:0 /tmp/ERROR_FAULT");
}
#endif
{
static pstring buf;
- strcpy(buf, dname);
+ pstrcpy(buf, dname);
unix_to_dos(buf, True);
dname = buf;
}
return(dname);
}
-/*
- * Utility function used to decide if the last component
- * of a path matches a (possibly wildcarded) entry in a namelist.
- */
+/*******************************************************************
+ Utility function used to decide if the last component
+ of a path matches a (possibly wildcarded) entry in a namelist.
+********************************************************************/
BOOL is_in_path(char *name, name_compare_entry *namelist)
{
pstring last_component;
char *p;
- DEBUG(5, ("is_in_path: %s\n", name));
+ DEBUG(8, ("is_in_path: %s\n", name));
/* if we have no list it's obviously not in the path */
if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL)))
{
- DEBUG(5,("is_in_path: no name list.\n"));
+ DEBUG(8,("is_in_path: no name list.\n"));
return False;
}
/* look for a wildcard match. */
if (mask_match(last_component, namelist->name, case_sensitive, False))
{
- DEBUG(5,("is_in_path: mask match succeeded\n"));
+ DEBUG(8,("is_in_path: mask match succeeded\n"));
return True;
}
}
if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
(!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0)))
{
- DEBUG(5,("is_in_path: match succeeded\n"));
+ DEBUG(8,("is_in_path: match succeeded\n"));
return True;
}
}
}
- DEBUG(5,("is_in_path: match not found\n"));
-
+ DEBUG(8,("is_in_path: match not found\n"));
+
return False;
}
-/*
- * Strip a '/' separated list into an array of
- * name_compare_enties structures suitable for
- * passing to is_in_path(). We do this for
- * speed so we can pre-parse all the names in the list
- * and don't do it for each call to is_in_path().
- * namelist is modified here and is assumed to be
- * a copy owned by the caller.
- * We also check if the entry contains a wildcard to
- * remove a potentially expensive call to mask_match
- * if possible.
- */
-
+/*******************************************************************
+ Strip a '/' separated list into an array of
+ name_compare_enties structures suitable for
+ passing to is_in_path(). We do this for
+ speed so we can pre-parse all the names in the list
+ and don't do it for each call to is_in_path().
+ namelist is modified here and is assumed to be
+ a copy owned by the caller.
+ We also check if the entry contains a wildcard to
+ remove a potentially expensive call to mask_match
+ if possible.
+********************************************************************/
+
void set_namearray(name_compare_entry **ppname_array, char *namelist)
{
char *name_end;
first to count the number of elements, the second
to split it.
*/
- while (*nameptr )
+ while(*nameptr)
{
if ( *nameptr == '/' )
- {
+ {
/* cope with multiple (useless) /s) */
nameptr++;
continue;
- }
+ }
/* find the next / */
name_end = strchr(nameptr, '/');
if(( (*ppname_array) = (name_compare_entry *)malloc(
(num_entries + 1) * sizeof(name_compare_entry))) == NULL)
- {
+ {
DEBUG(0,("set_namearray: malloc fail\n"));
return;
- }
+ }
/* Now copy out the names */
nameptr = namelist;
i = 0;
while(*nameptr)
- {
+ {
if ( *nameptr == '/' )
{
/* cope with multiple (useless) /s) */
if ((name_end = strchr(nameptr, '/')) != NULL)
{
*name_end = 0;
- }
+ }
/* oops - the last check for a / didn't find one. */
- if (name_end == NULL)
+ if(name_end == NULL)
break;
(*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
nameptr = name_end + 1;
i++;
}
-
+
(*ppname_array)[i].name = NULL;
return;
#endif
- DEBUG(5,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type));
+ DEBUG(8,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type));
lock.l_type = type;
lock.l_whence = SEEK_SET;
}
/* everything went OK */
- DEBUG(5,("Lock call successful\n"));
+ DEBUG(8,("Lock call successful\n"));
return(True);
#else
is the name specified one of my netbios names
returns true is it is equal, false otherwise
********************************************************************/
-BOOL is_myname(const char *s)
+BOOL is_myname(char *s)
{
int n;
BOOL ret = False;
DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
return(ret);
}
+
+/*******************************************************************
+set the horrid remote_arch string based on an enum.
+********************************************************************/
+void set_remote_arch(enum remote_arch_types type)
+{
+ ra_type = type;
+ switch( type )
+ {
+ case RA_WFWG:
+ strcpy(remote_arch, "WfWg");
+ return;
+ case RA_OS2:
+ strcpy(remote_arch, "OS2");
+ return;
+ case RA_WIN95:
+ strcpy(remote_arch, "Win95");
+ return;
+ case RA_WINNT:
+ strcpy(remote_arch, "WinNT");
+ return;
+ case RA_SAMBA:
+ strcpy(remote_arch,"Samba");
+ return;
+ default:
+ ra_type = RA_UNKNOWN;
+ strcpy(remote_arch, "UNKNOWN");
+ break;
+ }
+}
+
+/*******************************************************************
+ Get the remote_arch type.
+********************************************************************/
+enum remote_arch_types get_remote_arch()
+{
+ return ra_type;
+}
+
+
+/*******************************************************************
+skip past some unicode strings in a buffer
+********************************************************************/
+char *skip_unicode_string(char *buf,int n)
+{
+ while (n--)
+ {
+ while (*buf)
+ buf += 2;
+ buf += 2;
+ }
+ return(buf);
+}
+
+/*******************************************************************
+Return a ascii version of a unicode string
+Hack alert: uses fixed buffer(s) and only handles ascii strings
+********************************************************************/
+#define MAXUNI 1024
+char *unistrn2(uint16 *buf, int len)
+{
+ static char lbufs[8][MAXUNI];
+ static int nexti;
+ char *lbuf = lbufs[nexti];
+ char *p;
+
+ nexti = (nexti+1)%8;
+
+ DEBUG(10, ("unistrn2: "));
+
+ for (p = lbuf; *buf && p-lbuf < MAXUNI-2 && len > 0; len--, p++, buf++)
+ {
+ DEBUG(10, ("%4x ", *buf));
+ *p = *buf;
+ }
+
+ DEBUG(10,("\n"));
+
+ *p = 0;
+ return lbuf;
+}
+
+/*******************************************************************
+Return a ascii version of a unicode string
+Hack alert: uses fixed buffer(s) and only handles ascii strings
+********************************************************************/
+#define MAXUNI 1024
+char *unistr2(uint16 *buf)
+{
+ static char lbufs[8][MAXUNI];
+ static int nexti;
+ char *lbuf = lbufs[nexti];
+ char *p;
+
+ nexti = (nexti+1)%8;
+
+ DEBUG(10, ("unistr2: "));
+
+ for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf++)
+ {
+ DEBUG(10, ("%4x ", *buf));
+ *p = *buf;
+ }
+
+ DEBUG(10,("\n"));
+
+ *p = 0;
+ return lbuf;
+}
+
+/*******************************************************************
+create a null-terminated unicode string from a null-terminated ascii string.
+return number of unicode chars copied, excluding the null character.
+
+only handles ascii strings
+********************************************************************/
+#define MAXUNI 1024
+int struni2(uint16 *p, char *buf)
+{
+ int len = 0;
+
+ if (p == NULL) return 0;
+
+ DEBUG(10, ("struni2: "));
+
+ if (buf != NULL)
+ {
+ for (; *buf && len < MAXUNI-2; len++, p++, buf++)
+ {
+ DEBUG(10, ("%2x ", *buf));
+ *p = *buf;
+ }
+
+ DEBUG(10,("\n"));
+ }
+
+ *p = 0;
+
+ return len;
+}
+
+/*******************************************************************
+Return a ascii version of a unicode string
+Hack alert: uses fixed buffer(s) and only handles ascii strings
+********************************************************************/
+#define MAXUNI 1024
+char *unistr(char *buf)
+{
+ static char lbufs[8][MAXUNI];
+ static int nexti;
+ char *lbuf = lbufs[nexti];
+ char *p;
+
+ nexti = (nexti+1)%8;
+
+ for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf += 2)
+ {
+ *p = *buf;
+ }
+ *p = 0;
+ return lbuf;
+}
+
+/*******************************************************************
+strncpy for unicode strings
+********************************************************************/
+int unistrncpy(char *dst, char *src, int len)
+{
+ int num_wchars = 0;
+
+ while (*src && len > 0)
+ {
+ *dst++ = *src++;
+ *dst++ = *src++;
+ len--;
+ num_wchars++;
+ }
+ *dst++ = 0;
+ *dst++ = 0;
+
+ return num_wchars;
+}
+
+
+/*******************************************************************
+strcpy for unicode strings. returns length (in num of wide chars)
+********************************************************************/
+int unistrcpy(char *dst, char *src)
+{
+ int num_wchars = 0;
+
+ while (*src)
+ {
+ *dst++ = *src++;
+ *dst++ = *src++;
+ num_wchars++;
+ }
+ *dst++ = 0;
+ *dst++ = 0;
+
+ return num_wchars;
+}
+
+
+/*******************************************************************
+safe string copy into a fstring
+********************************************************************/
+void fstrcpy(char *dest, char *src)
+{
+ int maxlength = sizeof(fstring) - 1;
+ if (!dest) {
+ DEBUG(0,("ERROR: NULL dest in fstrcpy\n"));
+ return;
+ }
+
+ if (!src) {
+ *dest = 0;
+ return;
+ }
+
+ while (maxlength-- && *src)
+ *dest++ = *src++;
+ *dest = 0;
+ if (*src) {
+ DEBUG(0,("ERROR: string overflow by %d in fstrcpy\n",
+ strlen(src)));
+ }
+}
+
+/*******************************************************************
+safe string copy into a pstring
+********************************************************************/
+void pstrcpy(char *dest, char *src)
+{
+ int maxlength = sizeof(pstring) - 1;
+ if (!dest) {
+ DEBUG(0,("ERROR: NULL dest in pstrcpy\n"));
+ return;
+ }
+
+ if (!src) {
+ *dest = 0;
+ return;
+ }
+
+ while (maxlength-- && *src)
+ *dest++ = *src++;
+ *dest = 0;
+ if (*src) {
+ DEBUG(0,("ERROR: string overflow by %d in pstrcpy\n",
+ strlen(src)));
+ }
+}
+
+
+/*******************************************************************
+align a pointer to a multiple of 4 bytes
+********************************************************************/
+char *align4(char *q, char *base)
+{
+ if ((q - base) & 3)
+ {
+ q += 4 - ((q - base) & 3);
+ }
+ return q;
+}
+
+/*******************************************************************
+align a pointer to a multiple of 2 bytes
+********************************************************************/
+char *align2(char *q, char *base)
+{
+ if ((q - base) & 1)
+ {
+ q++;
+ }
+ return q;
+}
+
+/*******************************************************************
+align a pointer to a multiple of align_offset bytes. looks like it
+will work for offsets of 0, 2 and 4...
+********************************************************************/
+char *align_offset(char *q, char *base, int align_offset_len)
+{
+ int mod = ((q - base) & (align_offset_len-1));
+ if (align_offset_len != 0 && mod != 0)
+ {
+ q += align_offset_len - mod;
+ }
+ return q;
+}
+
+void print_asc(int level, unsigned char *buf,int len)
+{
+ int i;
+ for (i=0;i<len;i++)
+ DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
+}
+
+void dump_data(int level,char *buf1,int len)
+{
+ unsigned char *buf = (unsigned char *)buf1;
+ int i=0;
+ if (len<=0) return;
+
+ DEBUG(level,("[%03X] ",i));
+ for (i=0;i<len;) {
+ DEBUG(level,("%02X ",(int)buf[i]));
+ i++;
+ if (i%8 == 0) DEBUG(level,(" "));
+ if (i%16 == 0) {
+ print_asc(level,&buf[i-16],8); DEBUG(level,(" "));
+ print_asc(level,&buf[i-8],8); DEBUG(level,("\n"));
+ if (i<len) DEBUG(level,("[%03X] ",i));
+ }
+ }
+ if (i%16) {
+ int n;
+
+ n = 16 - (i%16);
+ DEBUG(level,(" "));
+ if (n>8) DEBUG(level,(" "));
+ while (n--) DEBUG(level,(" "));
+
+ n = MIN(8,i%16);
+ print_asc(level,&buf[i-(i%16)],n); DEBUG(level,(" "));
+ n = (i%16) - n;
+ if (n>0) print_asc(level,&buf[i-n],n);
+ DEBUG(level,("\n"));
+ }
+}
+
+char *tab_depth(int depth)
+{
+ static pstring spaces;
+ memset(spaces, ' ', depth * 4);
+ spaces[depth * 4] = 0;
+ return spaces;
+}
+
+/*****************************************************************
+ Convert a domain SID to an ascii string. (non-reentrant).
+*****************************************************************/
+
+/* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
+char *dom_sid_to_string(DOM_SID *sid)
+{
+ static pstring sidstr;
+ char subauth[16];
+ int i;
+ uint32 ia = (sid->id_auth[5]) +
+ (sid->id_auth[4] << 8 ) +
+ (sid->id_auth[3] << 16) +
+ (sid->id_auth[2] << 24);
+
+ sprintf(sidstr, "S-%d-%d", sid->sid_rev_num, ia);
+
+ for (i = 0; i < sid->num_auths; i++)
+ {
+ sprintf(subauth, "-%d", sid->sub_auths[i]);
+ strcat(sidstr, subauth);
+ }
+
+ DEBUG(7,("dom_sid_to_string returning %s\n", sidstr));
+ return sidstr;
+}