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
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);
****************************************************************************/
void reopen_logs(void)
{
- extern FILE *dbf;
pstring fname;
if (DEBUGLEVEL > 0)
asynchronous upper to lower mapping.
*/
#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. */
asynchronous upper to lower mapping.
*/
#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 !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 !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 !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. */
#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,"//","/");
- pstrcpy(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);
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 !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. */
int count=0;
#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. */
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=%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));
{
#ifndef NO_FORK_DEBUG
if (fork())
- exit(0);
+ _exit(0);
/* detach from the terminal */
#ifdef USE_SETSID
/*******************************************************************
return the DNS name of the client
******************************************************************/
-char *client_name(void)
-{
- 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;
+char *client_name(int fd)
+{
+ 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;
+}
- if (global_client_name_done)
- 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;
- strcpy(name_buf,"UNKNOWN");
+ if (global_client_addr_done && fd == last_fd)
+ return addr_buf;
- if (Client == -1) {
- return name_buf;
- }
+ last_fd = fd;
+ global_client_addr_done = False;
- if (getpeername(Client, &sa, &length) < 0) {
- DEBUG(0,("getpeername failed\n"));
- return name_buf;
- }
+ strcpy(addr_buf,"0.0.0.0");
- /* 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");
- }
- }
- global_client_name_done = True;
- return name_buf;
+ 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;
}
/*******************************************************************
- return the IP addr of the client as a string
- ******************************************************************/
-char *client_addr(void)
-{
- extern int Client;
- struct sockaddr sa;
- struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
- int length = sizeof(sa);
- static fstring addr_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 (global_client_addr_done)
- return addr_buf;
+#if (defined(NETGROUP) && defined(AUTOMOUNT))
+static char *automount_lookup(char *user_name)
+{
+ static fstring last_key = "";
+ static pstring last_value = "";
- strcpy(addr_buf,"0.0.0.0");
+ 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 (Client == -1) {
- return addr_buf;
+ if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
+ {
+ DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
+ return last_value;
}
- if (getpeername(Client, &sa, &length) < 0) {
- DEBUG(0,("getpeername failed\n"));
- return addr_buf;
- }
+ DEBUG(5, ("NIS Domain: %s\n", nis_domain));
- fstrcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr));
+ 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_addr_done = True;
- return addr_buf;
+ DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
+ return last_value;
}
+#endif
+
+/*******************************************************************
+ 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)
{
static pstring server_name;
#if (defined(NETGROUP) && defined (AUTOMOUNT))
- 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();
int home_server_len;
/* set to default of local machine */
pstrcpy(server_name, local_machine);
- if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
- {
- DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
- }
-
- DEBUG(5, ("NIS Domain: %s\n", nis_domain));
-
- if ((nis_error = yp_match(nis_domain, nis_map,
- user_name, strlen(user_name),
- &nis_result, &nis_result_len)) != 0)
+ if (lp_nis_home_map())
{
- DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
- }
-
- if (!nis_error && lp_nis_home_map())
- {
- home_server_len = strcspn(nis_result,":");
+ 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, nis_result, home_server_len);
+ strncpy(server_name, automount_value, home_server_len);
server_name[home_server_len] = '\0';
}
#else
return server_name;
}
+/*******************************************************************
+ 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;
+
+ /* 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
break;
}
case 'N' : string_sub(p,"%N", automount_server(username)); break;
- case 'I' : string_sub(p,"%I", client_addr()); 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()); 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 '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;
}
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)
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;
+}