Cleanups!
[kai/samba.git] / source3 / lib / util.c
index 0c0d3f70a7cfeed042051d59290b3f18113fa9f0..a23ef91a31e194a833aaec7dc09ecd385075c355 100644 (file)
@@ -1,8 +1,9 @@
 /* 
-   Unix SMB/Netbios implementation.
-   Version 1.9.
+   Unix SMB/CIFS implementation.
    Samba utility functions
    Copyright (C) Andrew Tridgell 1992-1998
+   Copyright (C) Jeremy Allison 2001
+   Copyright (C) Simo Sorce 2001
    
    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
 #endif /* WITH_NISPLUS_HOME */
 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
 
-#ifdef WITH_SSL
-#include <ssl.h>
-#undef Realloc  /* SSLeay defines this and samba has a function of this name */
-extern SSL  *ssl;
-extern int  sslFd;
-#endif  /* WITH_SSL */
-
-extern int DEBUGLEVEL;
-
 int Protocol = PROTOCOL_COREPLUS;
 
 /* a default finfo structure to ensure all fields are sensible */
@@ -92,27 +84,28 @@ char **my_netbios_names;
 
 
 /****************************************************************************
-  find a suitable temporary directory. The result should be copied immediately
-  as it may be overwritten by a subsequent call
-  ****************************************************************************/
+ Find a suitable temporary directory. The result should be copied immediately
+ as it may be overwritten by a subsequent call.
+****************************************************************************/
+
 char *tmpdir(void)
 {
   char *p;
-  if ((p = getenv("TMPDIR"))) {
+       if ((p = getenv("TMPDIR")))
     return p;
-  }
   return "/tmp";
 }
 
 /****************************************************************************
-determine whether we are in the specified group
+ Determine whether we are in the specified group.
 ****************************************************************************/
 
 BOOL in_group(gid_t group, gid_t current_gid, int ngroups, gid_t *groups)
 {
        int i;
 
-       if (group == current_gid) return(True);
+       if (group == current_gid)
+               return(True);
 
        for (i=0;i<ngroups;i++)
                if (group == groups[i])
@@ -121,14 +114,13 @@ BOOL in_group(gid_t group, gid_t current_gid, int ngroups, gid_t *groups)
        return(False);
 }
 
-
 /****************************************************************************
-like atoi but gets the value up to the separater character
+ Like atoi but gets the value up to the separator character.
 ****************************************************************************/
-char *Atoic(char *p, int *n, char *c)
+
+static char *Atoic(char *p, int *n, char *c)
 {
-       if (!isdigit((int)*p))
-       {
+       if (!isdigit((int)*p)) {
                DEBUG(5, ("Atoic: malformed number\n"));
                return NULL;
        }
@@ -136,11 +128,9 @@ char *Atoic(char *p, int *n, char *c)
        (*n) = atoi(p);
 
        while ((*p) && isdigit((int)*p))
-       {
                p++;
-       }
 
-       if (strchr(c, *p) == NULL)
+       if (strchr_m(c, *p) == NULL)
        {
                DEBUG(5, ("Atoic: no separator characters (%s) not found\n", c));
                return NULL;
@@ -150,27 +140,29 @@ char *Atoic(char *p, int *n, char *c)
 }
 
 /*************************************************************************
- reads a list of numbers
+ Reads a list of numbers.
  *************************************************************************/
+
 char *get_numlist(char *p, uint32 **num, int *count)
 {
        int val;
 
        if (num == NULL || count == NULL)
-       {
                return NULL;
-       }
 
        (*count) = 0;
        (*num  ) = NULL;
 
-       while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':')
-       {
-               (*num) = Realloc((*num), ((*count)+1) * sizeof(uint32));
-               if ((*num) == NULL)
+       while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':') {
+               uint32 *tn;
+               
+               tn = Realloc((*num), ((*count)+1) * sizeof(uint32));
+               if (tn == NULL)
                {
+                       SAFE_FREE(*num);
                        return NULL;
-               }
+               } else
+                       (*num) = tn;
                (*num)[(*count)] = val;
                (*count)++;
                p++;
@@ -179,40 +171,27 @@ char *get_numlist(char *p, uint32 **num, int *count)
        return p;
 }
 
-
 /*******************************************************************
-  check if a file exists - call vfs_file_exist for samba files
+ Check if a file exists - call vfs_file_exist for samba files.
 ********************************************************************/
-BOOL file_exist(char *fname,SMB_STRUCT_STAT *sbuf)
+
+BOOL file_exist(const char *fname,SMB_STRUCT_STAT *sbuf)
 {
   SMB_STRUCT_STAT st;
-  if (!sbuf) sbuf = &st;
+       if (!sbuf)
+               sbuf = &st;
   
   if (sys_stat(fname,sbuf) != 0) 
     return(False);
 
-  return(S_ISREG(sbuf->st_mode));
+       return((S_ISREG(sbuf->st_mode)) || (S_ISFIFO(sbuf->st_mode)));
 }
 
 /*******************************************************************
-  rename a unix file
+ Check a files mod time.
 ********************************************************************/
-int file_rename(char *from, char *to)
-{
-       int rcode = rename (from, to);
-
-       if (errno == EXDEV) 
-       {
-               /* Rename across filesystems needed. */
-               rcode = copy_reg (from, to);        
-       }
-       return rcode;
-}
 
-/*******************************************************************
-check a files mod time
-********************************************************************/
-time_t file_modtime(char *fname)
+time_t file_modtime(const char *fname)
 {
   SMB_STRUCT_STAT st;
   
@@ -223,8 +202,9 @@ time_t file_modtime(char *fname)
 }
 
 /*******************************************************************
-  check if a directory exists
+ Check if a directory exists.
 ********************************************************************/
+
 BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st)
 {
   SMB_STRUCT_STAT st2;
@@ -324,10 +304,10 @@ void smb_setlen(char *buf,int len)
 {
   _smb_setlen(buf,len);
 
-  CVAL(buf,4) = 0xFF;
-  CVAL(buf,5) = 'S';
-  CVAL(buf,6) = 'M';
-  CVAL(buf,7) = 'B';
+  SCVAL(buf,4,0xFF);
+  SCVAL(buf,5,'S');
+  SCVAL(buf,6,'M');
+  SCVAL(buf,7,'B');
 }
 
 /*******************************************************************
@@ -337,7 +317,7 @@ int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
 {
        if (zero)
                memset(buf + smb_size,'\0',num_words*2 + num_bytes);
-       CVAL(buf,smb_wct) = num_words;
+       SCVAL(buf,smb_wct,num_words);
        SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);  
        smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
        return (smb_size + num_words*2 + num_bytes);
@@ -346,20 +326,21 @@ int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
 /*******************************************************************
   setup only the byte count for a smb message
 ********************************************************************/
-void set_message_bcc(char *buf,int num_bytes)
+int set_message_bcc(char *buf,int num_bytes)
 {
        int num_words = CVAL(buf,smb_wct);
        SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);  
        smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
+       return (smb_size + num_words*2 + num_bytes);
 }
 
 /*******************************************************************
   setup only the byte count for a smb message, using the end of the
   message as a marker
 ********************************************************************/
-void set_message_end(void *outbuf,void *end_ptr)
+int set_message_end(void *outbuf,void *end_ptr)
 {
-       set_message_bcc((char *)outbuf,PTR_DIFF(end_ptr,smb_buf((char *)outbuf)));
+       return set_message_bcc((char *)outbuf,PTR_DIFF(end_ptr,smb_buf((char *)outbuf)));
 }
 
 /*******************************************************************
@@ -381,7 +362,7 @@ void dos_clean_name(char *s)
       *p = 0;
       pstrcpy(s1,p+3);
 
-      if ((p=strrchr(s,'\\')) != NULL)
+      if ((p=strrchr_m(s,'\\')) != NULL)
        *p = 0;
       else
        *s = 0;
@@ -419,7 +400,7 @@ void unix_clean_name(char *s)
       *p = 0;
       pstrcpy(s1,p+3);
 
-      if ((p=strrchr(s,'/')) != NULL)
+      if ((p=strrchr_m(s,'/')) != NULL)
        *p = 0;
       else
        *s = 0;
@@ -429,6 +410,60 @@ void unix_clean_name(char *s)
   trim_string(s,NULL,"/..");
 }
 
+/*******************************************************************
+convert '\' to '/'
+reduce a file name, removing or reducing /../ , /./ , // elements.
+remove also any trailing . and /
+return a new allocated string.
+********************************************************************/
+smb_ucs2_t *unix_clean_path(const smb_ucs2_t *s)
+{
+       smb_ucs2_t *ns;
+       smb_ucs2_t *p, *r, *t;
+
+       DEBUG(3, ("unix_clean_path\n")); /*  [%unicode]\n")); */
+       if(!s) return NULL;
+
+       /* convert '\' to '/' */
+       ns = strdup_w(s);
+       if (!ns) return NULL;
+       unix_format_w(ns);
+
+       /* remove all double slashes */
+       p = ns;
+       ns = all_string_sub_wa(p, "//", "/");
+       SAFE_FREE(p);
+       if (!ns) return NULL;
+
+       /* remove any /./ */
+       p = ns;
+       ns = all_string_sub_wa(p, "/./", "/");
+       SAFE_FREE(p);
+       if (!ns) return NULL;
+
+       /* reduce any /../ */
+       t = ns;
+       while (*t && (r = strstr_wa(t, "/.."))) {
+               t = &(r[3]);
+               if (*t == UCS2_CHAR('/') || *t == 0) {
+                       *r = 0;
+                       p = strrchr_w(ns, UCS2_CHAR('/'));
+                       if (!p) p = ns;
+                       if (*t == 0) *p = 0;
+                       else memmove(p, t, (strlen_w(t) + 1) * sizeof(smb_ucs2_t));
+                       t = p;
+               }
+       }
+
+       /* remove any leading ./ trailing /. */
+       trim_string_wa(ns, "./", "/.");
+
+       /* remove any leading and trailing / */
+       trim_string_wa(ns, "/", "/");
+
+       return ns;
+}
+
 /****************************************************************************
   make a dir struct
 ****************************************************************************/
@@ -443,25 +478,25 @@ void make_dir_struct(char *buf,char *mask,char *fname,SMB_OFF_T size,int mode,ti
     size = 0;
 
   memset(buf+1,' ',11);
-  if ((p = strchr(mask2,'.')) != NULL)
+  if ((p = strchr_m(mask2,'.')) != NULL)
     {
       *p = 0;
-      memcpy(buf+1,mask2,MIN(strlen(mask2),8));
-      memcpy(buf+9,p+1,MIN(strlen(p+1),3));
+      push_ascii(buf+1,mask2,8, 0);
+      push_ascii(buf+9,p+1,3, 0);
       *p = '.';
     }
   else
-    memcpy(buf+1,mask2,MIN(strlen(mask2),11));
+      push_ascii(buf+1,mask2,11, 0);
 
   memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
-  CVAL(buf,21) = mode;
+  SCVAL(buf,21,mode);
   put_dos_date(buf,22,date);
   SSVAL(buf,26,size & 0xFFFF);
   SSVAL(buf,28,(size >> 16)&0xFFFF);
-  StrnCpy(buf+30,fname,12);
+  push_ascii(buf+30,fname,12, 0);
   if (!case_sensitive)
     strupper(buf+30);
-  DEBUG(8,("put name [%s] into dir struct\n",buf+30));
+  DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
 }
 
 
@@ -511,122 +546,118 @@ int set_blocking(int fd, BOOL set)
 #endif
 #endif
 
-  if((val = fcntl(fd, F_GETFL, 0)) == -1)
+  if((val = sys_fcntl_long(fd, F_GETFL, 0)) == -1)
        return -1;
   if(set) /* Turn blocking on - ie. clear nonblock flag */
        val &= ~FLAG_TO_SET;
   else
     val |= FLAG_TO_SET;
-  return fcntl( fd, F_SETFL, val);
+  return sys_fcntl_long( fd, F_SETFL, val);
 #undef FLAG_TO_SET
 }
 
 /****************************************************************************
-transfer some data between two fd's
+ Transfer some data between two fd's.
 ****************************************************************************/
-SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n,char *header,int headlen,int align)
-{
-  static char *buf=NULL;  
-  static int size=0;
-  char *buf1,*abuf;
-  SMB_OFF_T total = 0;
 
-  DEBUG(4,("transfer_file n=%.0f  (head=%d) called\n",(double)n,headlen));
-
-  if (size == 0) {
-    size = lp_readsize();
-    size = MAX(size,1024);
-  }
-
-  while (!buf && size>0) {
-    buf = (char *)Realloc(buf,size+8);
-    if (!buf) size /= 2;
-  }
-
-  if (!buf) {
-    DEBUG(0,("Can't allocate transfer buffer!\n"));
-    exit(1);
-  }
-
-  abuf = buf + (align%8);
+#ifndef TRANSFER_BUF_SIZE
+#define TRANSFER_BUF_SIZE 65536
+#endif
 
-  if (header)
-    n += headlen;
+ssize_t transfer_file_internal(int infd, int outfd, size_t n, ssize_t (*read_fn)(int, void *, size_t),
+                                               ssize_t (*write_fn)(int, const void *, size_t))
+{
+       char *buf;
+       size_t total = 0;
+       ssize_t read_ret;
+       ssize_t write_ret;
+       size_t num_to_read_thistime;
+       size_t num_written = 0;
 
-  while (n > 0)
-  {
-    int s = (int)MIN(n,(SMB_OFF_T)size);
-    int ret,ret2=0;
+       if ((buf = malloc(TRANSFER_BUF_SIZE)) == NULL)
+               return -1;
 
-    ret = 0;
+       while (total < n) {
+               num_to_read_thistime = MIN((n - total), TRANSFER_BUF_SIZE);
 
-    if (header && (headlen >= MIN(s,1024))) {
-      buf1 = header;
-      s = headlen;
-      ret = headlen;
-      headlen = 0;
-      header = NULL;
-    } else {
-      buf1 = abuf;
-    }
+               read_ret = (*read_fn)(infd, buf, num_to_read_thistime);
+               if (read_ret == -1) {
+                       DEBUG(0,("transfer_file_internal: read failure. Error = %s\n", strerror(errno) ));
+                       SAFE_FREE(buf);
+                       return -1;
+               }
+               if (read_ret == 0)
+                       break;
 
-    if (header && headlen > 0)
-    {
-      ret = MIN(headlen,size);
-      memcpy(buf1,header,ret);
-      headlen -= ret;
-      header += ret;
-      if (headlen <= 0) header = NULL;
-    }
+               num_written = 0;
+               while (num_written < read_ret) {
+                       write_ret = (*write_fn)(outfd,buf + num_written, read_ret - num_written);
+                       if (write_ret == -1) {
+                               DEBUG(0,("transfer_file_internal: write failure. Error = %s\n", strerror(errno) ));
+                               SAFE_FREE(buf);
+                               return -1;
+                       }
+                       if (write_ret == 0)
+                               return (ssize_t)total;
+                       num_written += (size_t)write_ret;
+               }
 
-    if (s > ret)
-      ret += read(infd,buf1+ret,s-ret);
+               total += (size_t)read_ret;
+       }
 
-    if (ret > 0)
-    {
-      ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret);
-      if (ret2 > 0) total += ret2;
-      /* if we can't write then dump excess data */
-      if (ret2 != ret)
-        transfer_file(infd,-1,n-(ret+headlen),NULL,0,0);
-    }
-    if (ret <= 0 || ret2 != ret)
-      return(total);
-    n -= ret;
-  }
-  return(total);
+       SAFE_FREE(buf);
+       return (ssize_t)total;          
 }
 
+SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n)
+{
+       return (SMB_OFF_T)transfer_file_internal(infd, outfd, (size_t)n, sys_read, sys_write);
+}
 
 /*******************************************************************
-sleep for a specified number of milliseconds
+ Sleep for a specified number of milliseconds.
 ********************************************************************/
-void msleep(int t)
+
+void msleep(unsigned int t)
 {
-  int tdiff=0;
-  struct timeval tval,t1,t2;  
-  fd_set fds;
+       unsigned int tdiff=0;
+       struct timeval tval,t1,t2;  
+       fd_set fds;
 
-  GetTimeOfDay(&t1);
-  GetTimeOfDay(&t2);
+       GetTimeOfDay(&t1);
+       GetTimeOfDay(&t2);
   
-  while (tdiff < t) {
-    tval.tv_sec = (t-tdiff)/1000;
-    tval.tv_usec = 1000*((t-tdiff)%1000);
-    FD_ZERO(&fds);
-    errno = 0;
-    sys_select_intr(0,&fds,&tval);
+       while (tdiff < t) {
+               tval.tv_sec = (t-tdiff)/1000;
+               tval.tv_usec = 1000*((t-tdiff)%1000);
+
+               /* Never wait for more than 1 sec. */
+               if (tval.tv_sec > 1) {
+                       tval.tv_sec = 1; 
+                       tval.tv_usec = 0;
+               }
 
-    GetTimeOfDay(&t2);
-    tdiff = TvalDiff(&t1,&t2);
-  }
-}
+               FD_ZERO(&fds);
+               errno = 0;
+               sys_select_intr(0,&fds,NULL,NULL,&tval);
 
+               GetTimeOfDay(&t2);
+               if (t2.tv_sec < t1.tv_sec) {
+                       /* Someone adjusted time... */
+                       t1 = t2;
+               }
+
+               tdiff = TvalDiff(&t1,&t2);
+       }
+}
 
 /****************************************************************************
-become a daemon, discarding the controlling terminal
+ Become a daemon, discarding the controlling terminal.
 ****************************************************************************/
+
 void become_daemon(void)
 {
        if (sys_fork()) {
@@ -652,7 +683,7 @@ void become_daemon(void)
 
 
 /****************************************************************************
-put up a yes/no prompt
+ Put up a yes/no prompt
 ****************************************************************************/
 BOOL yesno(char *p)
 {
@@ -668,25 +699,16 @@ BOOL yesno(char *p)
   return(False);
 }
 
-#ifdef HPUX
 /****************************************************************************
-this is a version of setbuffer() for those machines that only have setvbuf
+ Expand a pointer to be a particular size.
 ****************************************************************************/
- void setbuffer(FILE *f,char *buf,int bufsize)
-{
-  setvbuf(f,buf,_IOFBF,bufsize);
-}
-#endif
 
-/****************************************************************************
-expand a pointer to be a particular size
-****************************************************************************/
 void *Realloc(void *p,size_t size)
 {
   void *ret=NULL;
 
   if (size == 0) {
-    if (p) free(p);
+    SAFE_FREE(p);
     DEBUG(5,("Realloc asked for 0 bytes\n"));
     return NULL;
   }
@@ -702,22 +724,21 @@ void *Realloc(void *p,size_t size)
   return(ret);
 }
 
-
 /****************************************************************************
-free memory, checks for NULL
+ Free memory, checks for NULL.
+use directly SAFE_FREE()
+exist only because we need to pass a function pointer somewhere --SSS
 ****************************************************************************/
+
 void safe_free(void *p)
 {
-       if (p != NULL)
-       {
-               free(p);
-       }
+       SAFE_FREE(p);
 }
 
-
 /****************************************************************************
-get my own name and IP
+ Get my own name and IP.
 ****************************************************************************/
+
 BOOL get_myname(char *my_name)
 {
        pstring hostname;
@@ -735,8 +756,10 @@ BOOL get_myname(char *my_name)
 
        if (my_name) {
                /* split off any parts after an initial . */
-               char *p = strchr(hostname,'.');
-               if (p) *p = 0;
+               char *p = strchr_m(hostname,'.');
+
+               if (p)
+                       *p = 0;
                
                fstrcpy(my_name,hostname);
        }
@@ -745,8 +768,9 @@ BOOL get_myname(char *my_name)
 }
 
 /****************************************************************************
-interpret a protocol description string, with a default
+ Interpret a protocol description string, with a default.
 ****************************************************************************/
+
 int interpret_protocol(char *str,int def)
 {
   if (strequal(str,"NT1"))
@@ -781,7 +805,7 @@ BOOL is_ipaddress(const char *str)
       pure_address = False;
 
   /* Check that a pure number is not misinterpreted as an IP */
-  pure_address = pure_address && (strchr(str, '.') != NULL);
+  pure_address = pure_address && (strchr_m(str, '.') != NULL);
 
   return pure_address;
 }
@@ -790,7 +814,7 @@ BOOL is_ipaddress(const char *str)
 interpret an internet address or name into an IP address in 4 byte form
 ****************************************************************************/
 
-uint32 interpret_addr(char *str)
+uint32 interpret_addr(const char *str)
 {
   struct hostent *hp;
   uint32 res;
@@ -823,7 +847,7 @@ uint32 interpret_addr(char *str)
 /*******************************************************************
   a convenient addition to interpret_addr()
   ******************************************************************/
-struct in_addr *interpret_addr2(char *str)
+struct in_addr *interpret_addr2(const char *str)
 {
   static struct in_addr ret;
   uint32 a = interpret_addr(str);
@@ -832,15 +856,31 @@ struct in_addr *interpret_addr2(char *str)
 }
 
 /*******************************************************************
 check if an IP is the 0.0.0.0
Check if an IP is the 0.0.0.0
   ******************************************************************/
-BOOL zero_ip(struct in_addr ip)
+BOOL is_zero_ip(struct in_addr ip)
 {
   uint32 a;
   putip((char *)&a,(char *)&ip);
   return(a == 0);
 }
 
+/*******************************************************************
+ Set an IP to 0.0.0.0
+ ******************************************************************/
+
+void zero_ip(struct in_addr *ip)
+{
+        static BOOL init;
+        static struct in_addr ipzero;
+
+        if (!init) {
+                ipzero = *interpret_addr2("0.0.0.0");
+                init = True;
+        }
+
+        *ip = ipzero;
+}
 
 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
 /******************************************************************
@@ -874,7 +914,7 @@ static void strip_mount_options( pstring *str)
 *******************************************************************/
 
 #ifdef WITH_NISPLUS_HOME
-char *automount_lookup(char *user_name)
+char *automount_lookup(const char *user_name)
 {
   static fstring last_key = "";
   static pstring last_value = "";
@@ -922,7 +962,7 @@ char *automount_lookup(char *user_name)
   return last_value;
 }
 #else /* WITH_NISPLUS_HOME */
-char *automount_lookup(char *user_name)
+char *automount_lookup(const char *user_name)
 {
   static fstring last_key = "";
   static pstring last_value = "";
@@ -1001,6 +1041,9 @@ check if a process exists. Does this work on all unixes?
 
 BOOL process_exists(pid_t pid)
 {
+       /* Doing kill with a non-positive pid causes messages to be
+        * sent to places we don't want. */
+       SMB_ASSERT(pid > 0);
        return(kill(pid,0) == 0 || errno != ESRCH);
 }
 
@@ -1014,11 +1057,9 @@ char *uidtoname(uid_t uid)
        static fstring name;
        struct passwd *pass;
 
-       if (winbind_uidtoname(name, uid))
-               return name;
-
        pass = sys_getpwuid(uid);
-       if (pass) return(pass->pw_name);
+       if (pass)
+               return(pass->pw_name);
        slprintf(name, sizeof(name) - 1, "%d",(int)uid);
        return(name);
 }
@@ -1033,17 +1074,15 @@ char *gidtoname(gid_t gid)
        static fstring name;
        struct group *grp;
 
-       if (winbind_gidtoname(name, gid))
-               return name;
-
        grp = getgrgid(gid);
-       if (grp) return(grp->gr_name);
+       if (grp)
+               return(grp->gr_name);
        slprintf(name,sizeof(name) - 1, "%d",(int)gid);
        return(name);
 }
 
 /*******************************************************************
- Convert a user name into a uid. If winbindd is present uses this.
+ Convert a user name into a uid. 
 ********************************************************************/
 
 uid_t nametouid(char *name)
@@ -1052,36 +1091,37 @@ uid_t nametouid(char *name)
        char *p;
        uid_t u;
 
-       u = (uid_t)strtol(name, &p, 0);
-       if (p != name) return u;
+       pass = getpwnam_alloc(name);
+       if (pass) {
+               u = pass->pw_uid;
+               passwd_free(&pass);
+               return u;
+       }
 
-       if (winbind_nametouid(&u, name))
+       u = (uid_t)strtol(name, &p, 0);
+       if ((p != name) && (*p == '\0'))
                return u;
 
-       pass = sys_getpwnam(name);
-       if (pass) return(pass->pw_uid);
        return (uid_t)-1;
 }
 
 /*******************************************************************
- Convert a name to a gid_t if possible. Return -1 if not a group. If winbindd
- is present does a shortcut lookup...
+ Convert a name to a gid_t if possible. Return -1 if not a group. 
 ********************************************************************/
 
-gid_t nametogid(char *name)
+gid_t nametogid(const char *name)
 {
        struct group *grp;
        char *p;
        gid_t g;
 
        g = (gid_t)strtol(name, &p, 0);
-       if (p != name) return g;
-
-       if (winbind_nametogid(&g, name))
+       if ((p != name) && (*p == '\0'))
                return g;
 
        grp = getgrnam(name);
-       if (grp) return(grp->gr_gid);
+       if (grp)
+               return(grp->gr_gid);
        return (gid_t)-1;
 }
 
@@ -1155,7 +1195,7 @@ BOOL is_in_path(char *name, name_compare_entry *namelist)
   }
 
   /* Get the last component of the unix name. */
-  p = strrchr(name, '/');
+  p = strrchr_m(name, '/');
   strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
   last_component[sizeof(last_component)-1] = '\0'; 
 
@@ -1222,7 +1262,7 @@ void set_namearray(name_compare_entry **ppname_array, char *namelist)
           continue;
         }
       /* find the next / */
-      name_end = strchr(nameptr, '/');
+      name_end = strchr_m(nameptr, '/');
 
       /* oops - the last check for a / didn't find one. */
       if (name_end == NULL)
@@ -1255,7 +1295,7 @@ void set_namearray(name_compare_entry **ppname_array, char *namelist)
           continue;
       }
       /* find the next / */
-      if ((name_end = strchr(nameptr, '/')) != NULL) 
+      if ((name_end = strchr_m(nameptr, '/')) != NULL) 
       {
           *name_end = 0;
          }
@@ -1287,13 +1327,11 @@ routine to free a namearray.
 
 void free_namearray(name_compare_entry *name_array)
 {
-  if(name_array == 0)
+  if(name_array == NULL)
     return;
 
-  if(name_array->name != NULL)
-    free(name_array->name);
-
-  free((char *)name_array);
+  SAFE_FREE(name_array->name);
+  SAFE_FREE(name_array);
 }
 
 /****************************************************************************
@@ -1314,11 +1352,9 @@ BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
   lock.l_len = count;
   lock.l_pid = 0;
 
-  errno = 0;
-
-  ret = fcntl(fd,op,&lock);
+  ret = sys_fcntl_ptr(fd,op,&lock);
 
-  if (errno != 0)
+  if (ret == -1 && errno != 0)
     DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
 
   /* a lock query */
@@ -1352,62 +1388,118 @@ BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
 }
 
 /*******************************************************************
-is the name specified one of my netbios names
-returns true is it is equal, false otherwise
+ Is the name specified one of my netbios names.
+ Returns true if it is equal, false otherwise.
 ********************************************************************/
+
 BOOL is_myname(char *s)
 {
-  int n;
-  BOOL ret = False;
+       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);
+       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);
+}
+
+/********************************************************************
+ Return only the first IP address of our configured interfaces
+ as a string
+ *******************************************************************/
+
+const char* get_my_primary_ip (void)
+{
+       static fstring ip_string;
+       int n;
+       struct iface_struct nics[MAX_INTERFACES];
+
+       if ((n=get_interfaces(nics, MAX_INTERFACES)) <= 0)
+               return NULL;
+
+       fstrcpy(ip_string, inet_ntoa(nics[0].ip));
+       return ip_string;
+}
+
+BOOL is_myname_or_ipaddr(char *s)
+{
+       char **ptr;
+       
+       /* optimize for the common case */
+       if (strequal(s, global_myname)) 
+               return True;
+
+       /* maybe its an IP address? */
+       if (is_ipaddress(s)) {
+               struct iface_struct nics[MAX_INTERFACES];
+               int i, n;
+               uint32 ip;
+               
+               ip = interpret_addr(s);
+               if ((ip==0) || (ip==0xffffffff))
+                       return False;
+                       
+               n = get_interfaces(nics, MAX_INTERFACES);
+               for (i=0; i<n; i++) {
+                       if (ip == nics[i].ip.s_addr)
+                               return True;
+               }
+       }       
+
+       /* check for an alias */
+       ptr = lp_netbios_aliases();
+       for ( ; *ptr; ptr++ ) {
+               if (StrCaseCmp(s, *ptr) == 0)
+                       return True;
+       }
+       
+       /* no match */
+       return False;
 }
 
 /*******************************************************************
-set the horrid remote_arch string based on an enum.
+ Set the horrid remote_arch string based on an enum.
 ********************************************************************/
+
 void set_remote_arch(enum remote_arch_types type)
 {
-  extern fstring remote_arch;
-  ra_type = type;
-  switch( type )
-  {
-  case RA_WFWG:
-    fstrcpy(remote_arch, "WfWg");
-    return;
-  case RA_OS2:
-    fstrcpy(remote_arch, "OS2");
-    return;
-  case RA_WIN95:
-    fstrcpy(remote_arch, "Win95");
-    return;
-  case RA_WINNT:
-    fstrcpy(remote_arch, "WinNT");
-    return;
-  case RA_WIN2K:
-    fstrcpy(remote_arch, "Win2K");
-    return;
-  case RA_SAMBA:
-    fstrcpy(remote_arch,"Samba");
-    return;
-  default:
-    ra_type = RA_UNKNOWN;
-    fstrcpy(remote_arch, "UNKNOWN");
-    break;
-  }
+       extern fstring remote_arch;
+       ra_type = type;
+       switch( type ) {
+       case RA_WFWG:
+               fstrcpy(remote_arch, "WfWg");
+               return;
+       case RA_OS2:
+               fstrcpy(remote_arch, "OS2");
+               return;
+       case RA_WIN95:
+               fstrcpy(remote_arch, "Win95");
+               return;
+       case RA_WINNT:
+               fstrcpy(remote_arch, "WinNT");
+               return;
+       case RA_WIN2K:
+               fstrcpy(remote_arch, "Win2K");
+               return;
+       case RA_SAMBA:
+               fstrcpy(remote_arch,"Samba");
+               return;
+       default:
+               ra_type = RA_UNKNOWN;
+               fstrcpy(remote_arch, "UNKNOWN");
+               break;
+       }
 }
 
 /*******************************************************************
  Get the remote_arch type.
 ********************************************************************/
+
 enum remote_arch_types get_remote_arch(void)
 {
-  return ra_type;
+       return ra_type;
 }
 
 
@@ -1415,42 +1507,35 @@ void out_ascii(FILE *f, unsigned char *buf,int len)
 {
        int i;
        for (i=0;i<len;i++)
-       {
                fprintf(f, "%c", isprint(buf[i])?buf[i]:'.');
-       }
 }
 
 void out_data(FILE *f,char *buf1,int len, int per_line)
 {
        unsigned char *buf = (unsigned char *)buf1;
        int i=0;
-       if (len<=0)
-       {
+       if (len<=0) {
                return;
        }
 
        fprintf(f, "[%03X] ",i);
-       for (i=0;i<len;)
-       {
+       for (i=0;i<len;) {
                fprintf(f, "%02X ",(int)buf[i]);
                i++;
                if (i%(per_line/2) == 0) fprintf(f, " ");
-               if (i%per_line == 0)
-               {      
+               if (i%per_line == 0) {      
                        out_ascii(f,&buf[i-per_line  ],per_line/2); fprintf(f, " ");
                        out_ascii(f,&buf[i-per_line/2],per_line/2); fprintf(f, "\n");
                        if (i<len) fprintf(f, "[%03X] ",i);
                }
        }
-       if ((i%per_line) != 0)
-       {
+       if ((i%per_line) != 0) {
                int n;
 
                n = per_line - (i%per_line);
                fprintf(f, " ");
                if (n>(per_line/2)) fprintf(f, " ");
-               while (n--)
-               {
+               while (n--) {
                        fprintf(f, "   ");
                }
                n = MIN(per_line/2,i%per_line);
@@ -1461,16 +1546,16 @@ void out_data(FILE *f,char *buf1,int len, int per_line)
        }
 }
 
-void print_asc(int level, unsigned char *buf,int len)
+void print_asc(int level, const unsigned char *buf,int len)
 {
        int i;
        for (i=0;i<len;i++)
                DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
 }
 
-void dump_data(int level,char *buf1,int len)
+void dump_data(int level, const char *buf1,int len)
 {
-  unsigned char *buf = (unsigned char *)buf1;
+  const unsigned char *buf = (const unsigned char *)buf1;
   int i=0;
   if (len<=0) return;
 
@@ -1542,7 +1627,7 @@ zero a memory area then free it. Used to catch bugs faster
 void zero_free(void *p, size_t size)
 {
        memset(p, 0, size);
-       free(p);
+       SAFE_FREE(p);
 }
 
 
@@ -1658,7 +1743,7 @@ BOOL reg_split_key(char *full_keyname, uint32 *reg_type, char *key_name)
                return False;
        }
        
-       if (next_token(NULL, tmp, "\n\r", sizeof(tmp)))
+       if (next_token(&full_keyname, tmp, "\n\r", sizeof(tmp)))
        {
                fstrcpy(key_name, tmp);
        }
@@ -1689,10 +1774,65 @@ int smb_mkstemp(char *template)
 #endif
 }
 
+/*****************************************************************
+ malloc that aborts with smb_panic on fail or zero size.
+ *****************************************************************/  
+
+void *smb_xmalloc(size_t size)
+{
+       void *p;
+       if (size == 0)
+               smb_panic("smb_xmalloc: called with zero size.\n");
+       if ((p = malloc(size)) == NULL)
+               smb_panic("smb_xmalloc: malloc fail.\n");
+       return p;
+}
+
+/**
+ Memdup with smb_panic on fail.
+**/
+void *smb_xmemdup(const void *p, size_t size)
+{
+       void *p2;
+       p2 = smb_xmalloc(size);
+       memcpy(p2, p, size);
+       return p2;
+}
+
+/**
+ strdup that aborts on malloc fail.
+**/
+char *smb_xstrdup(const char *s)
+{
+       char *s1 = strdup(s);
+       if (!s1)
+               smb_panic("smb_xstrdup: malloc fail\n");
+       return s1;
+}
+
+/*
+  vasprintf that aborts on malloc fail
+*/
+int smb_xvasprintf(char **ptr, const char *format, va_list ap)
+{
+       int n;
+       va_list ap2;
+#if defined(HAVE_VA_COPY)
+       __va_copy(ap2, ap);
+#else
+       ap2 = ap;
+#endif
+       n = vasprintf(ptr, format, ap2);
+       if (n == -1 || ! *ptr) {
+               smb_panic("smb_xvasprintf: out of memory");
+       }
+       return n;
+}
+
 /*****************************************************************
 like strdup but for memory
  *****************************************************************/  
-void *memdup(void *p, size_t size)
+void *memdup(const void *p, size_t size)
 {
        void *p2;
        if (size == 0) return NULL;
@@ -1735,6 +1875,41 @@ char *lock_path(char *name)
        return fname;
 }
 
+/*****************************************************************
+a useful function for returning a path in the Samba pid directory
+ *****************************************************************/
+char *pid_path(char *name)
+{
+       static pstring fname;
+
+       pstrcpy(fname,lp_piddir());
+       trim_string(fname,"","/");
+
+       if (!directory_exist(fname,NULL)) {
+               mkdir(fname,0755);
+       }
+
+       pstrcat(fname,"/");
+       pstrcat(fname,name);
+
+       return fname;
+}
+
+
+/**
+ * @brief Returns an absolute path to a file in the Samba lib directory.
+ *
+ * @param name File to find, relative to LIBDIR.
+ *
+ * @retval Pointer to a static #pstring containing the full path.
+ **/
+char *lib_path(char *name)
+{
+       static pstring fname;
+       snprintf(fname, sizeof(fname), "%s/%s", dyn_LIBDIR, name);
+       return fname;
+}
+
 /*******************************************************************
  Given a filename - get its directory name
  NB: Returned in static storage.  Caveats:
@@ -1752,7 +1927,7 @@ char *parent_dirname(const char *path)
                return(NULL);
 
        pstrcpy(dirpath, path);
-       p = strrchr(dirpath, '/');  /* Find final '/', if any */
+       p = strrchr_m(dirpath, '/');  /* Find final '/', if any */
        if (!p) {
                pstrcpy(dirpath, ".");    /* No final "/", so dir is "." */
        } else {
@@ -1783,6 +1958,23 @@ BOOL ms_has_wild(char *s)
        return False;
 }
 
+BOOL ms_has_wild_w(const smb_ucs2_t *s)
+{
+       smb_ucs2_t c;
+       if (!s) return False;
+       while ((c = *s++)) {
+               switch (c) {
+               case UCS2_CHAR('*'):
+               case UCS2_CHAR('?'):
+               case UCS2_CHAR('<'):
+               case UCS2_CHAR('>'):
+               case UCS2_CHAR('"'):
+                       return True;
+               }
+       }
+       return False;
+}
+
 /*******************************************************************
  a wrapper that handles case sensitivity and the special handling
    of the ".." name
@@ -1790,21 +1982,146 @@ BOOL ms_has_wild(char *s)
 BOOL mask_match(char *string, char *pattern, BOOL is_case_sensitive)
 {
        fstring p2, s2;
+
        if (strcmp(string,"..") == 0) string = ".";
        if (strcmp(pattern,".") == 0) return False;
        
        if (is_case_sensitive) {
-               return ms_fnmatch(pattern, string) == 0;
+               return ms_fnmatch(pattern, string, Protocol) == 0;
        }
 
        fstrcpy(p2, pattern);
        fstrcpy(s2, string);
        strlower(p2); 
        strlower(s2);
-       return ms_fnmatch(p2, s2) == 0;
+       return ms_fnmatch(p2, s2, Protocol) == 0;
 }
 
+/*********************************************************
+ Recursive routine that is called by unix_wild_match.
+*********************************************************/
+
+static BOOL unix_do_match(char *regexp, char *str)
+{
+       char *p;
 
+       for( p = regexp; *p && *str; ) {
+
+               switch(*p) {
+                       case '?':
+                               str++;
+                               p++;
+                               break;
+
+                       case '*':
+
+                               /*
+                                * Look for a character matching 
+                                * the one after the '*'.
+                                */
+                               p++;
+                               if(!*p)
+                                       return True; /* Automatic match */
+                               while(*str) {
+
+                                       while(*str && (*p != *str))
+                                               str++;
+
+                                       /*
+                                        * Patch from weidel@multichart.de. In the case of the regexp
+                                        * '*XX*' we want to ensure there are at least 2 'X' characters
+                                        * in the string after the '*' for a match to be made.
+                                        */
+
+                                       {
+                                               int matchcount=0;
+
+                                               /*
+                                                * Eat all the characters that match, but count how many there were.
+                                                */
+
+                                               while(*str && (*p == *str)) {
+                                                       str++;
+                                                       matchcount++;
+                                               }
+
+                                               /*
+                                                * Now check that if the regexp had n identical characters that
+                                                * matchcount had at least that many matches.
+                                                */
+
+                                               while ( *(p+1) && (*(p+1) == *p)) {
+                                                       p++;
+                                                       matchcount--;
+                                               }
+
+                                               if ( matchcount <= 0 )
+                                                       return False;
+                                       }
+
+                                       str--; /* We've eaten the match char after the '*' */
+
+                                       if(unix_do_match(p, str))
+                                               return True;
+
+                                       if(!*str)
+                                               return False;
+                                       else
+                                               str++;
+                               }
+                               return False;
+
+                       default:
+                               if(*str != *p)
+                                       return False;
+                               str++;
+                               p++;
+                               break;
+               }
+       }
+
+       if(!*p && !*str)
+               return True;
+
+       if (!*p && str[0] == '.' && str[1] == 0)
+               return(True);
+  
+       if (!*str && *p == '?') {
+               while (*p == '?')
+                       p++;
+               return(!*p);
+       }
+
+       if(!*str && (*p == '*' && p[1] == '\0'))
+               return True;
+
+       return False;
+}
+
+/*******************************************************************
+ Simple case insensitive interface to a UNIX wildcard matcher.
+*******************************************************************/
+
+BOOL unix_wild_match(char *pattern, char *string)
+{
+       pstring p2, s2;
+       char *p;
+
+       pstrcpy(p2, pattern);
+       pstrcpy(s2, string);
+       strlower(p2);
+       strlower(s2);
+
+       /* Remove any *? and ** from the pattern as they are meaningless */
+       for(p = p2; *p; p++)
+               while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
+                       pstrcpy( &p[1], &p[2]);
+       if (strequal(p2,"*"))
+               return True;
+
+       return unix_do_match(p2, s2) == 0;      
+}
 
 #ifdef __INSURE__
 
@@ -1818,7 +2135,9 @@ int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
        static int (*fn)();
        int ret;
        char pidstr[10];
-       pstring cmd = "/usr/X11R6/bin/xterm -display :0 -T Panic -n Panic -e /bin/sh -c 'cat /tmp/ierrs.*.%d ; gdb /proc/%d/exe %d'";
+       /* you can get /usr/bin/backtrace from 
+           http://samba.org/ftp/unpacked/junkcode/backtrace */
+       pstring cmd = "/usr/bin/backtrace %d";
 
        slprintf(pidstr, sizeof(pidstr)-1, "%d", sys_getpid());
        pstring_sub(cmd, "%d", pidstr);
@@ -1827,6 +2146,11 @@ int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
                static void *h;
                h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
                fn = dlsym(h, "_Insure_trap_error");
+
+               if (!h || h == _Insure_trap_error) {
+                       h = dlopen("/usr/local/parasoft/lib.linux2/libinsure.so", RTLD_LAZY);
+                       fn = dlsym(h, "_Insure_trap_error");
+               }               
        }
 
        ret = fn(a1, a2, a3, a4, a5, a6);