credentials.c:
[kai/samba.git] / source3 / lib / util.c
index 9982d105adc727fcffd92af273daf8769aa6c8e3..701f32455413a6ea7dc02d049078354b6d620c04 100644 (file)
@@ -68,6 +68,7 @@ BOOL case_mangle;
 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="";   
@@ -91,7 +92,11 @@ void setup_logging(char *pname,BOOL interactive)
   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) {
@@ -679,48 +684,61 @@ static int name_interpret(char *in,char *out)
 
 /****************************************************************************
 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
@@ -755,12 +773,17 @@ time_t file_modtime(char *fname)
 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;
 }
 
 /*******************************************************************
@@ -797,45 +820,145 @@ char *attrib_string(int mode)
 /*******************************************************************
   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)
+  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)
+  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(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);
@@ -846,7 +969,7 @@ BOOL strequal(const char *s1, const char *s2)
 /*******************************************************************
   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);
@@ -872,23 +995,36 @@ BOOL strcsequal(char *s1,char *s2)
 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 */
     }
+  }
 }
 
 /*******************************************************************
@@ -897,23 +1033,36 @@ void strlower(char *s)
 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
     }
+  }
 }
 
 /*******************************************************************
@@ -945,23 +1094,30 @@ BOOL strisnormal(char *s)
 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 */
     }
+  }
 }
 
 /****************************************************************************
@@ -974,7 +1130,7 @@ void unix_format(char *fname)
 
   if (*fname == '/')
     {
-      strcpy(namecopy,fname);
+      pstrcpy(namecopy,fname);
       strcpy(fname,".");
       strcat(fname,namecopy);
     }  
@@ -1041,8 +1197,8 @@ void show_msg(char *buf)
       if (j == 7) DEBUG(10, ("  "));
     }
 
-    DEBUG(10,("\n"));  
-  }
+  DEBUG(10,("\n"));  
+}
 }
 
 /*******************************************************************
@@ -1185,7 +1341,7 @@ void dos_clean_name(char *s)
       pstring s1;
 
       *p = 0;
-      strcpy(s1,p+3);
+      pstrcpy(s1,p+3);
 
       if ((p=strrchr(s,'\\')) != NULL)
        *p = 0;
@@ -1223,7 +1379,7 @@ void unix_clean_name(char *s)
       pstring s1;
 
       *p = 0;
-      strcpy(s1,p+3);
+      pstrcpy(s1,p+3);
 
       if ((p=strrchr(s,'/')) != NULL)
        *p = 0;
@@ -1250,24 +1406,10 @@ int ChDir(char *path)
   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)
 
@@ -1294,7 +1436,7 @@ char *GetWd(char *str)
   *s = 0;
 
   if (!use_getwd_cache)
-    return(Dumb_GetWd(str));
+    return(sys_getwd(str));
 
   /* init the cache */
   if (!getwd_cache_init)
@@ -1313,7 +1455,7 @@ char *GetWd(char *str)
   if (stat(".",&st) == -1) 
     {
       DEBUG(0,("Very strange, couldn't stat \".\"\n"));
-      return(Dumb_GetWd(str));
+      return(sys_getwd(str));
     }
 
 
@@ -1357,9 +1499,9 @@ char *GetWd(char *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);
     }
 
@@ -1424,7 +1566,7 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
   /* remove any double slashes */
   string_sub(s,"//","/");
 
-  strcpy(basename,s);
+  pstrcpy(basename,s);
   p = strrchr(basename,'/');
 
   if (!p)
@@ -1494,12 +1636,12 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
     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);
@@ -1523,10 +1665,10 @@ static void expand_one(char *Mask,int len)
       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);      
     }
 }
 
@@ -1550,20 +1692,20 @@ void expand_mask(char *Mask,BOOL doext)
 
   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;
        }
     }
@@ -1581,7 +1723,7 @@ void expand_mask(char *Mask,BOOL doext)
   if (*mext)
     expand_one(mext,3);
 
-  strcpy(Mask,dirpart);
+  pstrcpy(Mask,dirpart);
   if (*dirpart || absolute) strcat(Mask,"\\");
   strcat(Mask,mbeg);
   strcat(Mask,".");
@@ -1597,21 +1739,30 @@ does a string have any uppercase chars in it?
 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);
 }
 
@@ -1621,21 +1772,38 @@ does a string have any lowercase chars in it?
 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);
 }
 
@@ -1645,12 +1813,33 @@ find the number of chars in a string
 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);
 }
 
@@ -1663,7 +1852,7 @@ void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode
   char *p;
   pstring mask2;
 
-  strcpy(mask2,mask);
+  pstrcpy(mask2,mask);
 
   if ((mode & aDIR) != 0)
     size = 0;
@@ -1775,7 +1964,7 @@ int read_udp_socket(int fd,char *buf,int len)
   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);
   }
 
@@ -2094,10 +2283,11 @@ int read_smb_length(int fd,char *inbuf,int timeout)
 
 
 /****************************************************************************
-  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;
 
@@ -2124,6 +2314,202 @@ BOOL receive_smb(int fd,char *buffer,int timeout)
   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 
@@ -2182,21 +2568,27 @@ int name_extract(char *buf,int ofs,char *name)
   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
@@ -2232,8 +2624,8 @@ BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
   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);
@@ -2311,7 +2703,12 @@ BOOL string_init(char **dest,char *src)
     }
   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);
@@ -2480,35 +2877,35 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
 
   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;
 }
@@ -2817,7 +3214,7 @@ BOOL get_myname(char *my_name,struct in_addr *ip)
       char *p = strchr(hostname,'.');
       if (p) *p = 0;
 
-      strcpy(my_name,hostname);
+      fstrcpy(my_name,hostname);
     }
 
   if (ip)
@@ -3035,6 +3432,10 @@ uint32 interpret_addr(char *str)
       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);
   }
 
@@ -3185,7 +3586,7 @@ char *client_addr(void)
     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;
@@ -3196,16 +3597,16 @@ 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];
+    char pidstr[10];
   struct passwd *pass;
 
-  for (s = string ; (p = strchr(s,'%')) != NULL ; s = p )
+  for (s = str ; (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
@@ -3442,7 +3843,7 @@ char *readdirname(void *p)
 
   {
     static pstring buf;
-    strcpy(buf, dname);
+    pstrcpy(buf, dname);
     unix_to_dos(buf, True);
     dname = buf;
   }
@@ -3450,22 +3851,22 @@ char *readdirname(void *p)
   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;
   }
 
@@ -3481,7 +3882,7 @@ BOOL is_in_path(char *name, name_compare_entry *namelist)
       /* 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;
       }
     }
@@ -3490,29 +3891,29 @@ BOOL is_in_path(char *name, name_compare_entry *namelist)
       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;
@@ -3529,14 +3930,14 @@ void set_namearray(name_compare_entry **ppname_array, char *namelist)
      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, '/');
 
@@ -3554,16 +3955,16 @@ void set_namearray(name_compare_entry **ppname_array, char *namelist)
 
   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) */
@@ -3574,10 +3975,10 @@ void set_namearray(name_compare_entry **ppname_array, char *namelist)
       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) ||
@@ -3592,7 +3993,7 @@ void set_namearray(name_compare_entry **ppname_array, char *namelist)
       nameptr = name_end + 1;
       i++;
     }
-
+  
   (*ppname_array)[i].name = NULL;
 
   return;
@@ -3653,7 +4054,7 @@ BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type)
 #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;
@@ -3701,7 +4102,7 @@ BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type)
     }
 
   /* everything went OK */
-  DEBUG(5,("Lock call successful\n"));
+  DEBUG(8,("Lock call successful\n"));
 
   return(True);
 #else
@@ -3747,7 +4148,7 @@ void file_unlock(int fd)
 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;
@@ -3759,3 +4160,228 @@ BOOL is_myname(const char *s)
   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;
+}
+