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 myname = "";
fstring myworkgroup = "";
+char **my_netbios_names;
int smb_read_error = 0;
-static char *filename_dos(char *path,char *buf);
-
static BOOL stdout_logging = False;
+static char *filename_dos(char *path,char *buf);
/*******************************************************************
get ready for syslog stuff
if (!interactive) {
char *p = strrchr(pname,'/');
if (p) pname = p+1;
+#ifdef LOG_DAEMON
openlog(pname, LOG_PID, LOG_DAEMON);
+#else /* LOG_DAEMON - for old systems that have no facility codes. */
+ openlog(pname, LOG_PID);
+#endif /* LOG_DAEMON */
}
#endif
if (interactive) {
/****************************************************************************
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';
}
- *out = 0;
- return(name_len(Out));
-}
+ 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;
+ }
+ }
+
+ return( name_len(Out) );
+ } /* name_mangle */
/*******************************************************************
check if a file exists
BOOL directory_exist(char *dname,struct stat *st)
{
struct stat st2;
+ BOOL ret;
+
if (!st) st = &st2;
if (sys_stat(dname,st) != 0)
return(False);
- return(S_ISDIR(st->st_mode));
+ ret = S_ISDIR(st->st_mode);
+ if(!ret)
+ errno = ENOTDIR;
+ return ret;
}
/*******************************************************************
/*******************************************************************
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 */
- while (*s && *t && tolower(*s) == tolower(*t))
+ /* We *must* use toupper rather than tolower here due to the
+ asynchronous upper to lower mapping.
+ */
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ 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(tolower(*s) - tolower(*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 */
- while (n-- && *s && *t && tolower(*s) == tolower(*t))
+ /* We *must* use toupper rather than tolower here due to the
+ asynchronous upper to lower mapping.
+ */
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ 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++;
+ }
- /* not run out of chars - strings are different lengths */
- if (n) return(tolower(*s) - tolower(*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(char *s1,char *s2)
+BOOL strequal(char *s1, char *s2)
{
if (s1 == s2) return(True);
if (!s1 || !s2) return(False);
void strlower(char *s)
{
while (*s)
+ {
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ 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)
+ 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)
+ 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;
DEBUG(5,("smb_bcc=%d\n",bcc));
if (DEBUGLEVEL < 10)
return;
- for (i=0;i<MIN(bcc,128);i++)
- DEBUG(10,("%X ",CVAL(smb_buf(buf),i)));
+ 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, (" "));
+ }
+
DEBUG(10,("\n"));
}
+}
/*******************************************************************
return the length of an smb packet
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)
-{
-#ifdef USE_GETCWD
- return ((char *)getcwd(s,sizeof(pstring)));
-#else
- return ((char *)getwd(s));
-#endif
-}
-
-
/* 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);
}
/* remove any double slashes */
string_sub(s,"//","/");
- strcpy(basename,s);
+ pstrcpy(basename,s);
p = strrchr(basename,'/');
if (!p)
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)
+ 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)
+ 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)
+ 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;
if SYSV use O_NDELAY
if BSD use FNDELAY
****************************************************************************/
-int set_blocking(int fd, int set)
+int set_blocking(int fd, BOOL set)
{
int val;
#ifdef O_NONBLOCK
bzero((char *)&lastip,sizeof(lastip));
ret = recvfrom(fd,buf,len,0,&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);
}
/****************************************************************************
- read an smb from a fd and return it's length
+ read an smb from a fd. Note that the buffer *MUST* be of size
+ BUFFER_SIZE+SAFETY_MARGIN.
The timeout is in milli seconds
****************************************************************************/
-BOOL receive_smb(int fd,char *buffer,int timeout)
+BOOL receive_smb(int fd,char *buffer, int timeout)
{
int len,ret;
return(True);
}
+/****************************************************************************
+ 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 udp messages.
+ for processing.
+****************************************************************************/
+
+typedef struct _udp_message_list {
+ struct _udp_message_list *msg_next;
+ char *msg_buf;
+ int msg_len;
+} udp_message_list;
+
+static udp_message_list *udp_msg_head = NULL;
+
+/****************************************************************************
+ Function to push a linked list of local udp messages ready
+ for processing.
+****************************************************************************/
+BOOL push_local_message(char *buf, int msg_len)
+{
+ udp_message_list *msg = (udp_message_list *)malloc(sizeof(udp_message_list));
+
+ if(msg == NULL)
+ {
+ DEBUG(0,("push_local_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 = udp_msg_head;
+ udp_msg_head = msg;
+
+ return True;
+}
+
+/****************************************************************************
+ 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 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 udp queue.
+ * If so - copy and return it.
+ */
+
+ if(udp_msg_head)
+ {
+ udp_message_list *msg = udp_msg_head;
+ memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len));
+ udp_msg_head = msg->msg_next;
+
+ /* Free the message we just copied. */
+ free((char *)msg->msg_buf);
+ free((char *)msg);
+ 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
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;
}
/* detach from the terminal */
#ifdef USE_SETSID
setsid();
-#else
+#else /* USE_SETSID */
#ifdef TIOCNOTTY
{
int i = open("/dev/tty", O_RDWR);
close(i);
}
}
-#endif
-#endif
-#endif
+#endif /* TIOCNOTTY */
+#endif /* USE_SETSID */
+ /* Close fd's 0,1,2. Needed if started by rsh */
+ close_low_fds();
+#endif /* NO_FORK_DEBUG */
}
char *p = strchr(hostname,'.');
if (p) *p = 0;
- strcpy(my_name,hostname);
+ fstrcpy(my_name,hostname);
}
if (ip)
sock_out.sin_family = PF_INET;
/* set it non-blocking */
- set_blocking(res,0);
+ set_blocking(res,False);
DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port));
}
/* set it blocking again */
- set_blocking(res,1);
+ set_blocking(res,True);
return res;
}
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 addr_buf;
}
- strcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr));
+ fstrcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr));
global_client_addr_done = True;
return addr_buf;
/*******************************************************************
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 *s)
-{
- if (!strchr(s,'%')) return;
-
- string_sub(s,"%R",remote_proto);
- string_sub(s,"%a",remote_arch);
- string_sub(s,"%m",remote_machine);
- string_sub(s,"%L",local_machine);
-
- if (!strchr(s,'%')) return;
-
- string_sub(s,"%v",VERSION);
- string_sub(s,"%h",myhostname);
- string_sub(s,"%U",sesssetup_user);
-
- if (!strchr(s,'%')) return;
-
- string_sub(s,"%I",client_addr());
- if (strstr(s,"%M"))
- string_sub(s,"%M",client_name());
- string_sub(s,"%T",timestring());
-
- if (!strchr(s,'%')) return;
-
+void standard_sub_basic(char *str)
{
+ char *s, *p;
char pidstr[10];
- sprintf(pidstr,"%d",(int)getpid());
- string_sub(s,"%d",pidstr);
- }
-
- if (!strchr(s,'%')) return;
+ struct passwd *pass;
+ for (s = str ; (p = strchr(s,'%')) != NULL ; s = p )
{
- struct passwd *pass = Get_Pwnam(sesssetup_user,False);
- if (pass) {
- string_sub(s,"%G",gidtoname(pass->pw_gid));
+ 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;
}
-
/*******************************************************************
are two IPs on the same subnet?
********************************************************************/
dname = ptr->d_name;
- {
- static pstring buf;
- strcpy(buf, dname);
- unix_to_dos(buf, True);
- dname = buf;
- }
-
#ifdef NEXT2
if (telldir(p) < 0) return(NULL);
#endif
broken_readdir = True;
}
if (broken_readdir)
- return(dname-2);
+ dname = dname - 2;
}
#endif
+ {
+ static pstring buf;
+ 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.
+********************************************************************/
-BOOL is_vetoed_name(int snum, char *name)
+BOOL is_in_path(char *name, name_compare_entry *namelist)
{
- char *namelist = lp_veto_files(snum);
- char *nameptr = namelist;
- char *name_end;
+ pstring last_component;
+ char *p;
- /* if we have no list it's obviously not vetoed */
- if((nameptr == NULL ) || (*nameptr == '\0'))
- return 0;
+ DEBUG(8, ("is_in_path: %s\n", name));
- /* if the name doesn't exist in the list, it's obviously ok too */
- if(strstr(namelist,name) == NULL )
- return 0;
+ /* if we have no list it's obviously not in the path */
+ if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL)))
+ {
+ DEBUG(8,("is_in_path: no name list.\n"));
+ return False;
+ }
- /* now, we need to find the names one by one and check them
- they can contain spaces and all sorts of stuff so we
- separate them with of all things '/' which can never be in a filename
- I could use "" but then I have to break them all out
- maybe such a routine exists somewhere?
- */
- while(*nameptr)
+ /* Get the last component of the unix name. */
+ p = strrchr(name, '/');
+ strncpy(last_component, p ? p : name, sizeof(last_component)-1);
+ last_component[sizeof(last_component)-1] = '\0';
+
+ for(; namelist->name != NULL; namelist++)
+ {
+ if(namelist->is_wild)
{
- if ( *nameptr == '/' )
- {
- nameptr++;
- continue;
- }
- if((name_end = strchr(nameptr,'/'))!=NULL)
+ /* look for a wildcard match. */
+ if (mask_match(last_component, namelist->name, case_sensitive, False))
+ {
+ DEBUG(8,("is_in_path: mask match succeeded\n"));
+ return True;
+ }
+ }
+ else
+ {
+ if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
+ (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0)))
{
- *name_end = 0;
+ DEBUG(8,("is_in_path: match succeeded\n"));
+ return True;
}
- /* a match! it's veto'd */
- if(strcmp(name,nameptr) == 0)
- return 1;
- if(name_end == NULL)
- return 0;
- /* next segment please */
- nameptr = name_end + 1;
}
- return 0;
+ }
+ DEBUG(8,("is_in_path: match not found\n"));
+
+ return False;
}
-static BOOL is_in_path(char *name, char *namelist)
+/*******************************************************************
+ 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 *nameptr = namelist;
- char *sub;
char *name_end;
- int len;
+ char *nameptr = namelist;
+ int num_entries = 0;
+ int i;
- /* if we have no list it's obviously not vetoed */
- if((nameptr == NULL ) || (*nameptr == '\0'))
- return 0;
+ (*ppname_array) = NULL;
+ if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0')))
+ return;
- /* now, we need to find the names one by one and check them
- they can contain spaces and all sorts of stuff so we
- separate them with of all things '/' which can never be in a filename
- I could use "" but then I have to break them all out
- maybe such a routine exists somewhere?
- */
+ /* We need to make two passes over the string. The
+ first to count the number of elements, the second
+ to split it.
+ */
while(*nameptr)
{
if ( *nameptr == '/' )
{
+ /* cope with multiple (useless) /s) */
nameptr++;
continue;
}
- if((name_end = strchr(nameptr,'/'))!=NULL)
+ /* find the next / */
+ name_end = strchr(nameptr, '/');
+
+ /* oops - the last check for a / didn't find one. */
+ if (name_end == NULL)
+ break;
+
+ /* next segment please */
+ nameptr = name_end + 1;
+ num_entries++;
+ }
+
+ if(num_entries == 0)
+ return;
+
+ if(( (*ppname_array) = (name_compare_entry *)malloc(
+ (num_entries + 1) * sizeof(name_compare_entry))) == NULL)
{
- *name_end = 0;
+ DEBUG(0,("set_namearray: malloc fail\n"));
+ return;
}
- len = strlen(nameptr);
- sub = name;
- /* If the name doesn't exist in the path, try the next name.. */
- while( sub && ((sub = strstr(sub,nameptr)) != NULL))
- {
- /* Is it a whole component? */
- if(((sub == name) || (sub[-1] == '/'))
- && ((sub[len] == '\0') || (sub[len] == '/')))
+ /* Now copy out the names */
+ nameptr = namelist;
+ i = 0;
+ while(*nameptr)
{
- return 1;
- }
- /* skip to the next component of the path */
- sub =strchr(sub,'/');
+ if ( *nameptr == '/' )
+ {
+ /* cope with multiple (useless) /s) */
+ nameptr++;
+ continue;
+ }
+ /* find the next / */
+ if ((name_end = strchr(nameptr, '/')) != NULL)
+ {
+ *name_end = 0;
}
+
+ /* oops - the last check for a / didn't find one. */
if(name_end == NULL)
- return 0;
+ break;
+
+ (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
+ (strchr( nameptr, '*')!=NULL));
+ if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
+ {
+ DEBUG(0,("set_namearray: malloc fail (1)\n"));
+ return;
+ }
+
/* next segment please */
nameptr = name_end + 1;
+ i++;
}
- return 0;
-}
+
+ (*ppname_array)[i].name = NULL;
-/****************************************************************************
-used to make files hidden, but still accessible
-****************************************************************************/
-BOOL is_hidden_path(int cnum, char *path)
-{
- return is_in_path(path, lp_hide_files(cnum));
+ return;
}
/****************************************************************************
-used to make files _completely_ inaccessible
+routine to free a namearray.
****************************************************************************/
-BOOL is_vetoed_path(int cnum, char *path)
+
+void free_namearray(name_compare_entry *name_array)
{
- return is_in_path(path, lp_veto_files(cnum));
+ if(name_array == 0)
+ return;
+
+ if(name_array->name != NULL)
+ free(name_array->name);
+
+ free((char *)name_array);
}
/****************************************************************************
#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
close(fd);
}
+/*******************************************************************
+is the name specified one of my netbios names
+returns true is it is equal, false otherwise
+********************************************************************/
+BOOL is_myname(char *s)
+{
+ int n;
+ BOOL ret = False;
+
+ for (n=0; my_netbios_names[n]; n++) {
+ if (strequal(my_netbios_names[n], s))
+ ret=True;
+ }
+ 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 *unistr2(uint16 *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++)
+ {
+ *p = *buf;
+ }
+ *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 *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)
+{
+ if (align_offset_len != 0 && ((q - base) & (align_offset_len-1)))
+ {
+ q += align_offset_len - ((q - base) & (align_offset_len));
+ }
+ return q;
+}