Fixed bugs in my YOST replacement code. Doing a trim_string
[kai/samba.git] / source3 / lib / util.c
index 2ac64d06487357e50f239461c212ddda3c993de7..a43de46c511cceefa96ae2a5075046e497dbfedf 100644 (file)
@@ -20,7 +20,6 @@
 */
 
 #include "includes.h"
-#include "loadparm.h"
 
 pstring scope = "";
 
@@ -39,20 +38,14 @@ FILE *dbf = NULL;
 /* the client file descriptor */
 int Client = -1;
 
-/* info on the client */
-struct from_host Client_info=
-{"UNKNOWN","0.0.0.0",NULL};
-
 /* the last IP received from */
 struct in_addr lastip;
 
 /* the last port received from */
 int lastport=0;
 
-/* my IP, the broadcast IP and the Netmask */
-struct in_addr myip;
-struct in_addr bcast_ip;
-struct in_addr Netmask;
+/* this is used by the chaining code */
+int chain_size = 0;
 
 int trans_num = 0;
 
@@ -61,11 +54,7 @@ int trans_num = 0;
 */
 int case_default = CASE_LOWER;
 
-
-/* size of reads during a direct file to file transfer */
-int ReadSize = 16*1024;
-
-pstring debugf = "/tmp/log.samba";
+pstring debugf = "";
 int syslog_level;
 
 /* the following control case operations - they are put here so the
@@ -83,7 +72,9 @@ fstring remote_proto="UNKNOWN";
 pstring myhostname="";
 pstring user_socket_options="";   
 pstring sesssetup_user="";
+pstring myname = "";
 
+int smb_read_error = 0;
 
 static char *filename_dos(char *path,char *buf);
 
@@ -128,6 +119,7 @@ void reopen_logs(void)
 
       if (!strcsequal(fname,debugf) || !dbf || !file_exist(debugf,NULL))
        {
+         int oldumask = umask(022);
          strcpy(debugf,fname);
          if (dbf) fclose(dbf);
          if (append_log)
@@ -135,6 +127,7 @@ void reopen_logs(void)
          else
            dbf = fopen(debugf,"w");
          if (dbf) setbuf(dbf,NULL);
+         umask(oldumask);
        }
     }
   else
@@ -182,10 +175,10 @@ write an debug message on the debugfile. This is called by the DEBUG
 macro
 ********************************************************************/
 #ifdef __STDC__
-int Debug1(char *format_str, ...)
+ int Debug1(char *format_str, ...)
 {
 #else
-int Debug1(va_alist)
+ int Debug1(va_alist)
 va_dcl
 {  
   char *format_str;
@@ -210,7 +203,9 @@ va_dcl
     {
       if (!dbf) 
        {
+         int oldumask = umask(022);
          dbf = fopen(debugf,"w");
+         umask(oldumask);
          if (dbf)
            setbuf(dbf,NULL);
          else
@@ -276,134 +271,19 @@ va_dcl
 }
 
 /****************************************************************************
-routine to do file locking
-****************************************************************************/
-BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type)
+  find a suitable temporary directory. The result should be copied immediately
+  as it may be overwritten by a subsequent call
+  ****************************************************************************/
+char *tmpdir(void)
 {
-#if HAVE_FCNTL_LOCK
-  struct flock lock;
-  int ret;
-
-#if 1
-  uint32 mask = 0xC0000000;
-
-  /* make sure the count is reasonable, we might kill the lockd otherwise */
-  count &= ~mask;
-
-  /* the offset is often strange - remove 2 of its bits if either of
-     the top two bits are set. Shift the top ones by two bits. This
-     still allows OLE2 apps to operate, but should stop lockd from
-     dieing */
-  if ((offset & mask) != 0)
-    offset = (offset & ~mask) | ((offset & mask) >> 2);
-#else
-  unsigned long mask = ((unsigned)1<<31);
-
-  /* interpret negative counts as large numbers */
-  if (count < 0)
-    count &= ~mask;
-
-  /* no negative offsets */
-  offset &= ~mask;
-
-  /* count + offset must be in range */
-  while ((offset < 0 || (offset + count < 0)) && mask)
-    {
-      offset &= ~mask;
-      mask = mask >> 1;
-    }
-#endif
-
-
-  DEBUG(5,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type));
-
-  lock.l_type = type;
-  lock.l_whence = SEEK_SET;
-  lock.l_start = (int)offset;
-  lock.l_len = (int)count;
-  lock.l_pid = 0;
-
-  errno = 0;
-
-  ret = fcntl(fd,op,&lock);
-
-  if (errno != 0)
-    DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
-
-  /* a lock query */
-  if (op == F_GETLK)
-    {
-      if ((ret != -1) &&
-         (lock.l_type != F_UNLCK) && 
-         (lock.l_pid != 0) && 
-         (lock.l_pid != getpid()))
-       {
-         DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid));
-         return(True);
-       }
-
-      /* it must be not locked or locked by me */
-      return(False);
-    }
-
-  /* a lock set or unset */
-  if (ret == -1)
-    {
-      DEBUG(3,("lock failed at offset %d count %d op %d type %d (%s)\n",
-              offset,count,op,type,strerror(errno)));
-
-      /* perhaps it doesn't support this sort of locking?? */
-      if (errno == EINVAL)
-       {
-         DEBUG(3,("locking not supported? returning True\n"));
-         return(True);
-       }
-
-      return(False);
-    }
-
-  /* everything went OK */
-  DEBUG(5,("Lock call successful\n"));
-
-  return(True);
-#else
-  return(False);
-#endif
-}
-
-/*******************************************************************
-lock a file - returning a open file descriptor or -1 on failure
-The timeout is in seconds. 0 means no timeout
-********************************************************************/
-int file_lock(char *name,int timeout)
-{  
-  int fd = open(name,O_RDWR|O_CREAT,0666);
-  time_t t=0;
-  if (fd < 0) return(-1);
-
-#if HAVE_FCNTL_LOCK
-  if (timeout) t = time(NULL);
-  while (!timeout || (time(NULL)-t < timeout)) {
-    if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)) return(fd);    
-    msleep(LOCK_RETRY_TIMEOUT);
+  char *p;
+  if ((p = getenv("TMPDIR"))) {
+    return p;
   }
-  return(-1);
-#else
-  return(fd);
-#endif
+  return "/tmp";
 }
 
-/*******************************************************************
-unlock a file locked by file_lock
-********************************************************************/
-void file_unlock(int fd)
-{
-  if (fd<0) return;
-#if HAVE_FCNTL_LOCK
-  fcntl_lock(fd,F_SETLK,0,1,F_UNLCK);
-#endif
-  close(fd);
-}
+
 
 /****************************************************************************
 determine if a file descriptor is in fact a socket
@@ -612,6 +492,12 @@ struct
 #endif
 #ifdef SO_RCVLOWAT
   {"SO_RCVLOWAT",       SOL_SOCKET,    SO_RCVLOWAT,     0,                 OPT_INT},
+#endif
+#ifdef SO_SNDTIMEO
+  {"SO_SNDTIMEO",       SOL_SOCKET,    SO_SNDTIMEO,     0,                 OPT_INT},
+#endif
+#ifdef SO_RCVTIMEO
+  {"SO_RCVTIMEO",       SOL_SOCKET,    SO_RCVTIMEO,     0,                 OPT_INT},
 #endif
   {NULL,0,0,0,0}};
 
@@ -727,7 +613,7 @@ char *StrCpy(char *dest,char *src)
 /****************************************************************************
 line strncpy but always null terminates. Make sure there is room!
 ****************************************************************************/
-char *StrnCpy(char *dest,const char *src,int n)
+char *StrnCpy(char *dest,char *src,int n)
 {
   char *d = dest;
   if (!dest) return(NULL);
@@ -910,25 +796,32 @@ char *attrib_string(int mode)
 /*******************************************************************
   case insensitive string compararison
 ********************************************************************/
-int StrCaseCmp(char *s, char *t)
+int StrCaseCmp(const char *s, const char *t)
 {
-  for (; tolower(*s) == tolower(*t); ++s, ++t)
-    if (!*s) return 0;
+  /* compare until we run out of string, either t or s, or find a difference */
+  while (*s && *t && tolower(*s) == tolower(*t))
+  {
+    s++; t++;
+  }
 
-  return tolower(*s) - tolower(*t);
+  return(tolower(*s) - tolower(*t));
 }
 
 /*******************************************************************
   case insensitive string compararison, length limited
 ********************************************************************/
-int StrnCaseCmp(char *s, char *t, int n)
+int StrnCaseCmp(const char *s, const char *t, int n)
 {
-  while (n-- && *s && *t) {
-    if (tolower(*s) != tolower(*t)) return(tolower(*s) - tolower(*t));
+  /* compare until we run out of string, either t or s, or chars */
+  while (n-- && *s && *t && tolower(*s) == tolower(*t))
+  {
     s++; t++;
   }
+
+  /* not run out of chars - strings are different lengths */
   if (n) return(tolower(*s) - tolower(*t));
 
+  /* identical up to where we run out of chars, and strings are same length */
   return(0);
 }
 
@@ -1071,9 +964,6 @@ void unix_format(char *fname)
 {
   pstring namecopy;
   string_replace(fname,'\\','/');
-#ifndef KANJI
-  dos2unix_format(fname, True);
-#endif /* KANJI */
 
   if (*fname == '/')
     {
@@ -1088,9 +978,6 @@ void unix_format(char *fname)
 ****************************************************************************/
 void dos_format(char *fname)
 {
-#ifndef KANJI
-  unix2dos_format(fname, True);
-#endif /* KANJI */
   string_replace(fname,'/','\\');
 }
 
@@ -1213,7 +1100,7 @@ return the SMB offset into an SMB buffer
 ********************************************************************/
 int smb_offset(char *p,char *buf)
 {
-  return(PTR_DIFF(p,buf+4));
+  return(PTR_DIFF(p,buf+4) + chain_size);
 }
 
 
@@ -1297,6 +1184,13 @@ void unix_clean_name(char *s)
   /* remove any double slashes */
   string_sub(s, "//","/");
 
+  /* Remove leading ./ characters */
+  if(strncmp(s, "./", 2) == 0) {
+    trim_string(s, "./", NULL);
+    if(*s == 0)
+      strcpy(s,"./");
+  }
+
   while ((p = strstr(s,"/../")) != NULL)
     {
       pstring s1;
@@ -1491,6 +1385,10 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
          DEBUG(3,("Illegal file name? (%s)\n",s));
          return(False);
        }
+
+      if (strlen(s) == 0)
+        strcpy(s,"./");
+
       return(True);
     }
   
@@ -1790,6 +1688,35 @@ void close_low_fds(void)
   }
 }
 
+/****************************************************************************
+Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
+else
+if SYSV use O_NDELAY
+if BSD use FNDELAY
+****************************************************************************/
+int set_blocking(int fd, int set)
+{
+  int val;
+#ifdef O_NONBLOCK
+#define FLAG_TO_SET O_NONBLOCK
+#else
+#ifdef SYSV
+#define FLAG_TO_SET O_NDELAY
+#else /* BSD */
+#define FLAG_TO_SET FNDELAY
+#endif
+#endif
+
+  if((val = fcntl(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);
+#undef FLAG_TO_SET
+}
+
 
 /****************************************************************************
 write to a socket
@@ -1820,11 +1747,10 @@ int read_udp_socket(int fd,char *buf,int len)
   bzero((char *)&sock,socklen);
   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));
-      return(0);
-    }
+  if (ret <= 0) {
+    DEBUG(2,("read socket failed. ERRNO=%d\n",errno));
+    return(0);
+  }
 
   lastip = *(struct in_addr *) &sock.sa_data[2];
   lastport = ntohs(((struct sockaddr_in *)&sock)->sin_port);
@@ -1832,103 +1758,44 @@ int read_udp_socket(int fd,char *buf,int len)
   return(ret);
 }
 
-/****************************************************************************
-Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
-else
-if SYSV use O_NDELAY
-if BSD use FNDELAY
-****************************************************************************/
-int set_blocking(int fd, BOOL set)
-{
-int val;
-#ifdef O_NONBLOCK
-#define FLAG_TO_SET O_NONBLOCK
-#else
-#ifdef SYSV
-#define FLAG_TO_SET O_NDELAY
-#else /* BSD */
-#define FLAG_TO_SET FNDELAY
-#endif
-#endif
-
-  if((val = fcntl(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);
-#undef FLAG_TO_SET
-}
-
-
-/****************************************************************************
-Calculate the difference in timeout values. Return 1 if val1 > val2,
-0 if val1 == val2, -1 if val1 < val2. Stores result in retval. retval
-may be == val1 or val2
-****************************************************************************/
-static int tval_sub( struct timeval *retval, struct timeval *val1, struct timeval *val2)
-{
-  int usecdiff = val1->tv_usec - val2->tv_usec;
-  int secdiff = val1->tv_sec - val2->tv_sec;
-  if(usecdiff < 0) {
-    usecdiff = 1000000 + usecdiff;
-    secdiff--;
-  }
-  retval->tv_sec = secdiff;
-  retval->tv_usec = usecdiff;
-  if(secdiff < 0)
-    return -1;
-  if(secdiff > 0)
-    return 1;
-  return (usecdiff < 0 ) ? -1 : ((usecdiff > 0 ) ? 1 : 0);
-}
-
 /****************************************************************************
 read data from a device with a timout in msec.
 mincount = if timeout, minimum to read before returning
 maxcount = number to be read.
 ****************************************************************************/
-int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out,BOOL exact)
+int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out)
 {
   fd_set fds;
   int selrtn;
   int readret;
   int nread = 0;
-  struct timeval timeout, tval1, tval2, tvaldiff;
-  int error_limit = 5;
+  struct timeval timeout;
 
   /* just checking .... */
   if (maxcnt <= 0) return(0);
 
-  if(time_out == -2)
-    time_out = DEFAULT_PIPE_TIMEOUT;
+  smb_read_error = 0;
 
   /* Blocking read */
-  if(time_out < 0) {
+  if (time_out <= 0) {
     if (mincnt == 0) mincnt = maxcnt;
 
-    while (nread < mincnt)
-      {
-       readret = read(fd, buf + nread, maxcnt - nread);
-       if (readret <= 0) return(nread);
-       nread += readret;
+    while (nread < mincnt) {
+      readret = read(fd, buf + nread, maxcnt - nread);
+      if (readret == 0) {
+       smb_read_error = READ_EOF;
+       return -1;
       }
+
+      if (readret == -1) {
+       smb_read_error = READ_ERROR;
+       return -1;
+      }
+      nread += readret;
+    }
     return(nread);
   }
   
-  /* Non blocking read */
-  if(time_out == 0) {
-    set_blocking(fd, False);
-    nread = read_data(fd, buf, mincnt);
-    if (nread < maxcnt)
-      nread += read(fd,buf+nread,maxcnt-nread);
-    if(nread == -1 && errno == EWOULDBLOCK)
-      nread = 0;
-    set_blocking(fd,True);
-    return nread;
-  }
-
   /* Most difficult - timeout read */
   /* If this is ever called on a disk file and 
         mincnt is greater then the filesize then
@@ -1939,71 +1806,40 @@ int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out,BOOL
   timeout.tv_sec = time_out / 1000;
   timeout.tv_usec = 1000 * (time_out % 1000);
 
-  /* As most UNIXes don't modify the value of timeout
-     when they return from select we need to get the timeofday (in usec)
-     now, and also after the select returns so we know
-     how much time has elapsed */
-
-  if (exact)
-    GetTimeOfDay( &tval1);
-  nread = 0; /* Number of bytes we have read */
-
-  for(;;) 
+  for (nread=0; nread<mincnt; ) 
     {      
       FD_ZERO(&fds);
       FD_SET(fd,&fds);
       
       selrtn = sys_select(&fds,&timeout);
-      
+
       /* Check if error */
       if(selrtn == -1) {
-       errno = EBADF;
+       /* something is wrong. Maybe the socket is dead? */
+       smb_read_error = READ_ERROR;
        return -1;
       }
       
       /* Did we timeout ? */
       if (selrtn == 0) {
-       if (nread < mincnt) return -1;
-       break; /* Yes */
+       smb_read_error = READ_TIMEOUT;
+       return -1;
       }
       
       readret = read(fd, buf+nread, maxcnt-nread);
-      if (readret == 0 && nread < mincnt) {
-       /* error_limit should not really be needed, but some systems
-          do strange things ...  I don't want to just continue
-          indefinately in case we get an infinite loop */
-       if (error_limit--) continue;
-       return(-1);
+      if (readret == 0) {
+       /* we got EOF on the file descriptor */
+       smb_read_error = READ_EOF;
+       return -1;
       }
 
-      if (readret < 0) {
-       /* force a particular error number for
-          portability */
-       DEBUG(5,("read gave error %s\n",strerror(errno)));
-       errno = EBADF;
+      if (readret == -1) {
+       /* the descriptor is probably dead */
+       smb_read_error = READ_ERROR;
        return -1;
       }
       
       nread += readret;
-      
-      /* If we have read more than mincnt then return */
-      if (nread >= mincnt)
-       break;
-
-      /* We need to do another select - but first reduce the
-        time_out by the amount of time already elapsed - if
-        this is less than zero then return */
-      if (exact) {
-       GetTimeOfDay(&tval2);
-       (void)tval_sub( &tvaldiff, &tval2, &tval1);
-      
-       if (tval_sub(&timeout, &timeout, &tvaldiff) <= 0) 
-         break; /* We timed out */
-      }
-      
-      /* Save the time of day as we need to do the select 
-        again (saves a system call) */
-      tval1 = tval2;
     }
 
   /* Return the number we got */
@@ -2070,16 +1906,19 @@ int read_data(int fd,char *buffer,int N)
   int  ret;
   int total=0;  
  
+  smb_read_error = 0;
+
   while (total < N)
     {
       ret = read(fd,buffer + total,N - total);
-
-      /* this is for portability */
-      if (ret < 0)
-       errno = EBADF;
-
-      if (ret <= 0)
-       return total;
+      if (ret == 0) {
+       smb_read_error = READ_EOF;
+       return 0;
+      }
+      if (ret == -1) {
+       smb_read_error = READ_ERROR;
+       return -1;
+      }
       total += ret;
     }
   return total;
@@ -2098,8 +1937,8 @@ int write_data(int fd,char *buffer,int N)
     {
       ret = write(fd,buffer + total,N - total);
 
-      if (ret <= 0)
-       return total;
+      if (ret == -1) return -1;
+      if (ret == 0) return total;
 
       total += ret;
     }
@@ -2107,148 +1946,34 @@ int write_data(int fd,char *buffer,int N)
 }
 
 
-/* variables used by the read prediction module */
-int rp_fd = -1;
-int rp_offset = 0;
-int rp_length = 0;
-int rp_alloced = 0;
-int rp_predict_fd = -1;
-int rp_predict_offset = 0;
-int rp_predict_length = 0;
-int rp_timeout = 5;
-time_t rp_time = 0;
-char *rp_buffer = NULL;
-BOOL predict_skip=False;
-time_t smb_last_time=(time_t)0;
-
 /****************************************************************************
-handle read prediction on a file
+transfer some data between two fd's
 ****************************************************************************/
-int read_predict(int fd,int offset,char *buf,char **ptr,int num)
+int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align)
 {
-  int ret = 0;
-  int possible = rp_length - (offset - rp_offset);
+  static char *buf=NULL;  
+  static int size=0;
+  char *buf1,*abuf;
+  int total = 0;
 
-  possible = MIN(possible,num);
+  DEBUG(4,("transfer_file %d  (head=%d) called\n",n,headlen));
 
-  /* give data if possible */
-  if (fd == rp_fd && 
-      offset >= rp_offset && 
-      possible>0 &&
-      smb_last_time-rp_time < rp_timeout)
-    {
-      ret = possible;
-      if (buf)
-       memcpy(buf,rp_buffer + (offset-rp_offset),possible);
-      else
-       *ptr = rp_buffer + (offset-rp_offset);
-      DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num));
-    }
+  if (size == 0) {
+    size = lp_readsize();
+    size = MAX(size,1024);
+  }
 
-  if (ret == num) {
-    predict_skip = True;
-  } else {
-    predict_skip = False;
+  while (!buf && size>0) {
+    buf = (char *)Realloc(buf,size+8);
+    if (!buf) size /= 2;
+  }
 
-    /* prepare the next prediction */
-    rp_predict_fd = fd;
-    rp_predict_offset = offset + num;
-    rp_predict_length = num;
+  if (!buf) {
+    DEBUG(0,("Can't allocate transfer buffer!\n"));
+    exit(1);
   }
 
-  if (ret < 0) ret = 0;
-
-  return(ret);
-}
-
-/****************************************************************************
-pre-read some data
-****************************************************************************/
-void do_read_prediction()
-{
-  if (predict_skip) return;
-
-  if (rp_predict_fd == -1) 
-    return;
-
-  rp_fd = rp_predict_fd;
-  rp_offset = rp_predict_offset;
-  rp_length = 0;
-
-  rp_predict_fd = -1;
-
-  rp_predict_length = MIN(rp_predict_length,2*ReadSize);
-  rp_predict_length = MAX(rp_predict_length,1024);
-  rp_offset = (rp_offset/1024)*1024;
-  rp_predict_length = (rp_predict_length/1024)*1024;
-
-  if (rp_predict_length > rp_alloced)
-    {
-      rp_buffer = Realloc(rp_buffer,rp_predict_length);
-      rp_alloced = rp_predict_length;
-      if (!rp_buffer)
-       {
-         DEBUG(0,("can't allocate read-prediction buffer\n"));
-         rp_predict_fd = -1;
-         rp_fd = -1;
-         rp_alloced = 0;
-         return;
-       }
-    }
-
-  if (lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) {
-    rp_fd = -1;
-    rp_predict_fd = -1;
-    return;
-  }
-
-  rp_length = read(rp_fd,rp_buffer,rp_predict_length);
-  rp_time = time(NULL);
-  if (rp_length < 0)
-    rp_length = 0;
-}
-
-/****************************************************************************
-invalidate read-prediction on a fd
-****************************************************************************/
-void invalidate_read_prediction(int fd)
-{
- if (rp_fd == fd) 
-   rp_fd = -1;
- if (rp_predict_fd == fd)
-   rp_predict_fd = -1;
-}
-
-
-/****************************************************************************
-transfer some data between two fd's
-****************************************************************************/
-int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align)
-{
-  static char *buf=NULL;  
-  char *buf1,*abuf;
-  static int size = 0;
-  int total = 0;
-
-  DEBUG(4,("transfer_file %d  (head=%d) called\n",n,headlen));
-
-  if ((size < ReadSize) && buf) {
-    free(buf);
-    buf = NULL;
-  }
-
-  size = MAX(ReadSize,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);
+  abuf = buf + (align%8);
 
   if (header)
     n += headlen;
@@ -2317,30 +2042,19 @@ int read_smb_length(int fd,char *inbuf,int timeout)
   while (!ok)
     {
       if (timeout > 0)
-       ok = (read_with_timeout(fd,buffer,4,4,timeout,False) == 4);
-      else     
+       ok = (read_with_timeout(fd,buffer,4,4,timeout) == 4);
+      else 
        ok = (read_data(fd,buffer,4) == 4);
 
       if (!ok)
-       {
-         if (timeout>0)
-           {
-             DEBUG(10,("select timeout (%d)\n", timeout));
-             return(-1);
-           }
-         else
-           {
-             DEBUG(6,("couldn't read from client\n"));
-             exit(1);
-           }
-       }
+       return(-1);
 
       len = smb_len(buffer);
       msg_type = CVAL(buffer,0);
 
       if (msg_type == 0x85) 
        {
-         DEBUG(5,( "Got keepalive packet\n"));
+         DEBUG(5,("Got keepalive packet\n"));
          ok = False;
        }
     }
@@ -2358,8 +2072,9 @@ The timeout is in milli seconds
 ****************************************************************************/
 BOOL receive_smb(int fd,char *buffer,int timeout)
 {
-  int len;
-  BOOL ok;
+  int len,ret;
+
+  smb_read_error = 0;
 
   bzero(buffer,smb_size + 100);
 
@@ -2368,18 +2083,16 @@ BOOL receive_smb(int fd,char *buffer,int timeout)
     return(False);
 
   if (len > BUFFER_SIZE) {
-    DEBUG(0,("Invalid packet length! (%d bytes)\n",len));
+    DEBUG(0,("Invalid packet length! (%d bytes).\n",len));
     if (len > BUFFER_SIZE + (SAFETY_MARGIN/2))
       exit(1);
   }
 
-  ok = (read_data(fd,buffer+4,len) == len);
-
-  if (!ok)
-    {
-      close_sockets();
-      exit(1);
-    }
+  ret = read_data(fd,buffer+4,len);
+  if (ret != len) {
+    smb_read_error = READ_ERROR;
+    return False;
+  }
 
   return(True);
 }
@@ -2802,216 +2515,6 @@ void become_daemon(void)
 #endif
 }
 
-/****************************************************************************
-calculate the default netmask for an address
-****************************************************************************/
-static void default_netmask(struct in_addr *inm, struct in_addr *iad)
-{
-  unsigned long ad = ntohl(iad->s_addr);
-  unsigned long nm;
-  /*
-  ** Guess a netmask based on the class of the IP address given.
-  */
-  if ( (ad & 0x80000000) == 0 ) {
-    /* class A address */
-    nm = 0xFF000000;
-  } else if ( (ad & 0xC0000000) == 0x80000000 ) {
-    /* class B address */
-    nm = 0xFFFF0000;
-  } else if ( (ad & 0xE0000000) == 0xC0000000 ) {
-    /* class C address */
-    nm = 0xFFFFFF00;
-  }  else {
-    /* class D or E; netmask doesn't make much sense - guess 4 bits */
-    nm =  0xFFFFFFF0;
-  }
-  inm->s_addr = htonl(nm);
-}
-
-/****************************************************************************
-  get the broadcast address for our address 
-(troyer@saifr00.ateng.az.honeywell.com)
-****************************************************************************/
-void get_broadcast(struct in_addr *if_ipaddr,
-                    struct in_addr *if_bcast,
-                    struct in_addr *if_nmask)
-{  
-  BOOL found = False;
-#ifndef NO_GET_BROADCAST
-  int sock = -1;               /* AF_INET raw socket desc */
-  char buff[1024];
-  struct ifreq *ifr=NULL;
-  int i;
-
-#if defined(EVEREST)
-  int n_interfaces;
-  struct ifconf ifc;
-  struct ifreq  *ifreqs;
-#elif defined(USE_IFREQ)
-  struct ifreq ifreq;
-  struct strioctl strioctl;
-  struct ifconf *ifc;
-#else
-  struct ifconf ifc;
-#endif
-#endif
-
-  /* get a default netmask and broadcast */
-  default_netmask(if_nmask, if_ipaddr);
-
-#ifndef NO_GET_BROADCAST  
-  /* Create a socket to the INET kernel. */
-#if USE_SOCKRAW
-  if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0)
-#else
-    if ((sock = socket(AF_INET, SOCK_DGRAM, 0 )) < 0)
-#endif
-      {
-        DEBUG(0,( "Unable to open socket to get broadcast address\n"));
-        return;
-      }
-  
-  /* Get a list of the configured interfaces */
-#ifdef EVEREST
-  /* This is part of SCO Openserver 5: The ioctls are no longer part
-     if the lower level STREAMS interface glue. They are now real
-     ioctl calls */
-
-  if (ioctl(sock, SIOCGIFANUM, &n_interfaces) < 0) {
-    DEBUG(0,( "SIOCGIFANUM: %s\n", strerror(errno)));
-  } else {
-    DEBUG(0,( "number of interfaces returned is: %d\n", n_interfaces));
-
-    ifc.ifc_len = sizeof(struct ifreq) * n_interfaces;
-    ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len);
-
-    if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
-      DEBUG(0, ( "SIOCGIFCONF: %s\n", strerror(errno)));
-    else {
-      ifr = ifc.ifc_req;
-
-      for (i = 0; i < n_interfaces; ++i) {
-       if (if_ipaddr->s_addr ==
-           ((struct sockaddr_in *) &ifr[i].ifr_addr)->sin_addr.s_addr) {
-         found = True;
-         break;
-       }
-      }
-    }
-  }
-#elif defined(USE_IFREQ)
-  ifc = (struct ifconf *)buff;
-  ifc->ifc_len = BUFSIZ - sizeof(struct ifconf);
-  strioctl.ic_cmd = SIOCGIFCONF;
-  strioctl.ic_dp  = (char *)ifc;
-  strioctl.ic_len = sizeof(buff);
-  if (ioctl(sock, I_STR, &strioctl) < 0) {
-    DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno)));
-  } else {
-    ifr = (struct ifreq *)ifc->ifc_req;  
-
-    /* Loop through interfaces, looking for given IP address */
-    for (i = ifc->ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
-      if (if_ipaddr->s_addr ==
-         (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
-       found = True;
-       break;
-      }
-    }
-  }
-#elif defined(__FreeBSD__) || defined(NETBSD)
-  ifc.ifc_len = sizeof(buff);
-  ifc.ifc_buf = buff;
-  if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
-    DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
-  } else {
-    ifr = ifc.ifc_req;
-    /* Loop through interfaces, looking for given IP address */
-    i = ifc.ifc_len;
-    while (i > 0) {
-      if (if_ipaddr->s_addr ==
-         (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
-       found = True;
-       break;
-      }
-      i -= ifr->ifr_addr.sa_len + IFNAMSIZ;
-      ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
-    }
-  }
-#else
-  ifc.ifc_len = sizeof(buff);
-  ifc.ifc_buf = buff;
-  if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
-    DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
-  } else {
-    ifr = ifc.ifc_req;
-  
-    /* Loop through interfaces, looking for given IP address */
-    for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
-#ifdef BSDI
-      if (ioctl(sock, SIOCGIFADDR, ifr) < 0) break;
-#endif
-      if (if_ipaddr->s_addr ==
-         (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
-       found = True;
-       break;
-      }
-    }
-  }
-#endif
-  
-  if (!found) {
-    DEBUG(0,("No interface found for address %s\n", inet_ntoa(*if_ipaddr)));
-  } else {
-    /* Get the netmask address from the kernel */
-#ifdef USE_IFREQ
-    ifreq = *ifr;
-  
-    strioctl.ic_cmd = SIOCGIFNETMASK;
-    strioctl.ic_dp  = (char *)&ifreq;
-    strioctl.ic_len = sizeof(struct ifreq);
-    if (ioctl(sock, I_STR, &strioctl) < 0)
-      DEBUG(0,("Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno)));
-    else
-      *if_nmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
-#else
-    if (ioctl(sock, SIOCGIFNETMASK, ifr) < 0)
-      DEBUG(0,("SIOCGIFNETMASK failed\n"));
-    else
-      *if_nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
-#endif
-
-    DEBUG(2,("Netmask for %s = %s\n", ifr->ifr_name,
-            inet_ntoa(*if_nmask)));
-  }
-
-  /* Close up shop */
-  (void) close(sock);
-  
-#endif
-
-  /* sanity check on the netmask */
-  {
-    unsigned long nm = ntohl(if_nmask->s_addr);
-    if ((nm >> 24) != 0xFF) {
-      DEBUG(0,("Impossible netmask %s - using defaults\n",inet_ntoa(*if_nmask)));
-      default_netmask(if_nmask, if_ipaddr);      
-    }
-  }
-
-  /* derive the broadcast assuming a 1's broadcast, as this is what
-     all MS operating systems do, we have to comply even if the unix
-     box is setup differently */
-  {
-    unsigned long ad = ntohl(if_ipaddr->s_addr);
-    unsigned long nm = ntohl(if_nmask->s_addr);
-    unsigned long bc = (ad & nm) | (0xffffffff & ~nm);
-    if_bcast->s_addr = htonl(bc);
-  }
-  
-  DEBUG(2,("Derived broadcast address %s\n", inet_ntoa(*if_bcast)));
-}  /* get_broadcast */
-
 
 /****************************************************************************
 put up a yes/no prompt
@@ -3162,7 +2665,7 @@ int byte_checksum(char *buf,int len)
 /****************************************************************************
 this is a version of setbuffer() for those machines that only have setvbuf
 ****************************************************************************/
-void setbuffer(FILE *f,char *buf,int bufsize)
+ void setbuffer(FILE *f,char *buf,int bufsize)
 {
   setvbuf(f,buf,_IOFBF,bufsize);
 }
@@ -3234,7 +2737,7 @@ void *Realloc(void *p,int size)
 /****************************************************************************
 duplicate a string
 ****************************************************************************/
-char *strdup(char *s)
+ char *strdup(char *s)
 {
   char *ret = NULL;
   if (!s) return(NULL);
@@ -3255,43 +2758,10 @@ void Abort(void )
   exit(2);
 }
 
-
-#ifdef REPLACE_STRLEN
-/****************************************************************************
-a replacement strlen() that returns int for solaris
-****************************************************************************/
-int Strlen(char *s)
-{
-  int ret=0;
-  if (!s) return(0);
-  while (*s++) ret++;
-  return(ret);
-}
-#endif
-
-
-#ifdef NO_FTRUNCATE
- /*******************************************************************
-ftruncate for operating systems that don't have it
-********************************************************************/
-int ftruncate(int f,long l)
-{
-      struct  flock   fl;
-
-      fl.l_whence = 0;
-      fl.l_len = 0;
-      fl.l_start = l;
-      fl.l_type = F_WRLCK;
-      return fcntl(f, F_FREESP, &fl);
-}
-#endif
-
-
-
 /****************************************************************************
 get my own name and IP
 ****************************************************************************/
-BOOL get_myname(char *myname,struct in_addr *ip)
+BOOL get_myname(char *my_name,struct in_addr *ip)
 {
   struct hostent *hp;
   pstring hostname;
@@ -3312,13 +2782,13 @@ BOOL get_myname(char *myname,struct in_addr *ip)
       return False;
     }
 
-  if (myname)
+  if (my_name)
     {
       /* split off any parts after an initial . */
       char *p = strchr(hostname,'.');
       if (p) *p = 0;
 
-      strcpy(myname,hostname);
+      strcpy(my_name,hostname);
     }
 
   if (ip)
@@ -3333,7 +2803,7 @@ true if two IP addresses are equal
 ****************************************************************************/
 BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
 {
-  unsigned long a1,a2;
+  uint32 a1,a2;
   a1 = ntohl(ip1.s_addr);
   a2 = ntohl(ip2.s_addr);
   return(a1 == a2);
@@ -3343,7 +2813,7 @@ BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
 /****************************************************************************
 open a socket of the specified type, port and address for incoming data
 ****************************************************************************/
-int open_socket_in(int type, int port, int dlevel)
+int open_socket_in(int type, int port, int dlevel,uint32 socket_addr)
 {
   struct hostent *hp;
   struct sockaddr_in sock;
@@ -3368,7 +2838,7 @@ int open_socket_in(int type, int port, int dlevel)
 #endif
   sock.sin_port = htons( port );
   sock.sin_family = hp->h_addrtype;
-  sock.sin_addr.s_addr = INADDR_ANY;
+  sock.sin_addr.s_addr = socket_addr;
   res = socket(hp->h_addrtype, type, 0);
   if (res == -1) 
     { DEBUG(0,("socket failed\n")); return -1; }
@@ -3382,16 +2852,16 @@ int open_socket_in(int type, int port, int dlevel)
   if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) 
     { 
       if (port) {
-       if (port == 139 || port == 137)
-         DEBUG(dlevel,("bind failed on port %d (%s)\n",
-                       port,strerror(errno))); 
+       if (port == SMB_PORT || port == NMB_PORT)
+         DEBUG(dlevel,("bind failed on port %d socket_addr=%x (%s)\n",
+                       port,socket_addr,strerror(errno))); 
        close(res); 
 
        if (dlevel > 0 && port < 1000)
          port = 7999;
 
        if (port >= 1000 && port < 9000)
-         return(open_socket_in(type,port+1,dlevel));
+         return(open_socket_in(type,port+1,dlevel,socket_addr));
       }
 
       return(-1); 
@@ -3405,10 +2875,12 @@ int open_socket_in(int type, int port, int dlevel)
 /****************************************************************************
   create an outgoing socket
   **************************************************************************/
-int open_socket_out(int type, struct in_addr *addr, int port )
+int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
 {
   struct sockaddr_in sock_out;
-  int res;
+  int res,ret;
+  int connect_loop = 250; /* 250 milliseconds */
+  int loops = (timeout * 1000) / connect_loop;
 
   /* create a socket to write to */
   res = socket(PF_INET, type, 0);
@@ -3423,15 +2895,42 @@ int open_socket_out(int type, struct in_addr *addr, int port )
   sock_out.sin_port = htons( port );
   sock_out.sin_family = PF_INET;
 
+  /* set it non-blocking */
+  set_blocking(res,0);
+
   DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port));
   
   /* and connect it to the destination */
-  if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))<0) {
-    DEBUG(0,("connect error: %s\n",strerror(errno))); 
-    close(res); 
-    return(-1);
+connect_again:
+  ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out));
+
+  if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY) && loops--) {
+    msleep(connect_loop);
+    goto connect_again;
+  }
+
+  if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY)) {
+      DEBUG(1,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port));
+      close(res);
+      return -1;
   }
 
+#ifdef EISCONN
+  if (ret < 0 && errno == EISCONN) {
+    errno = 0;
+    ret = 0;
+  }
+#endif
+
+  if (ret < 0) {
+    DEBUG(1,("error connecting to %s:%d (%s)\n",
+            inet_ntoa(*addr),port,strerror(errno)));
+    return -1;
+  }
+
+  /* set it blocking again */
+  set_blocking(res,1);
+
   return res;
 }
 
@@ -3480,19 +2979,26 @@ int interpret_security(char *str,int def)
 /****************************************************************************
 interpret an internet address or name into an IP address in 4 byte form
 ****************************************************************************/
-unsigned long interpret_addr(char *str)
+uint32 interpret_addr(char *str)
 {
   struct hostent *hp;
-  unsigned long res;
+  uint32 res;
+  int i;
+  BOOL pure_address = True;
 
   if (strcmp(str,"0.0.0.0") == 0) return(0);
   if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
 
+  for (i=0; pure_address && str[i]; i++)
+    if (!(isdigit(str[i]) || str[i] == '.')) 
+      pure_address = False;
+
   /* if it's in the form of an IP address then get the lib to interpret it */
-  if (isdigit(str[0])) {
+  if (pure_address) {
     res = inet_addr(str);
   } else {
-    /* otherwise assume it's a network name of some sort and use Get_Hostbyname */
+    /* otherwise assume it's a network name of some sort and use 
+       Get_Hostbyname */
     if ((hp = Get_Hostbyname(str)) == 0) {
       DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
       return 0;
@@ -3500,7 +3006,7 @@ unsigned long interpret_addr(char *str)
     putip((char *)&res,(char *)hp->h_addr);
   }
 
-  if (res == (unsigned long)-1) return(0);
+  if (res == (uint32)-1) return(0);
 
   return(res);
 }
@@ -3511,8 +3017,8 @@ unsigned long interpret_addr(char *str)
 struct in_addr *interpret_addr2(char *str)
 {
   static struct in_addr ret;
-  unsigned long a = interpret_addr(str);
-  putip((char *)&ret,(char *)&a);
+  uint32 a = interpret_addr(str);
+  ret.s_addr = a;
   return(&ret);
 }
 
@@ -3521,11 +3027,121 @@ struct in_addr *interpret_addr2(char *str)
   ******************************************************************/
 BOOL zero_ip(struct in_addr ip)
 {
-  unsigned long a;
+  uint32 a;
   putip((char *)&a,(char *)&ip);
   return(a == 0);
 }
 
+
+/* matchname - determine if host name matches IP address */
+static BOOL matchname(char *remotehost,struct in_addr  addr)
+{
+  struct hostent *hp;
+  int     i;
+  
+  if ((hp = Get_Hostbyname(remotehost)) == 0) {
+    DEBUG(0,("Get_Hostbyname(%s): lookup failure", remotehost));
+    return False;
+  } 
+
+  /*
+   * Make sure that gethostbyname() returns the "correct" host name.
+   * Unfortunately, gethostbyname("localhost") sometimes yields
+   * "localhost.domain". Since the latter host name comes from the
+   * local DNS, we just have to trust it (all bets are off if the local
+   * DNS is perverted). We always check the address list, though.
+   */
+  
+  if (strcasecmp(remotehost, hp->h_name)
+      && strcasecmp(remotehost, "localhost")) {
+    DEBUG(0,("host name/name mismatch: %s != %s",
+            remotehost, hp->h_name));
+    return False;
+  }
+       
+  /* Look up the host address in the address list we just got. */
+  for (i = 0; hp->h_addr_list[i]; i++) {
+    if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
+      return True;
+  }
+
+  /*
+   * The host name does not map to the original host address. Perhaps
+   * someone has compromised a name server. More likely someone botched
+   * it, but that could be dangerous, too.
+   */
+  
+  DEBUG(0,("host name/address mismatch: %s != %s",
+          inet_ntoa(addr), hp->h_name));
+  return False;
+}
+
+/* return the DNS name of the client */
+char *client_name(void)
+{
+  extern int Client;
+  struct sockaddr sa;
+  struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
+  int     length = sizeof(sa);
+  static pstring name_buf;
+  static BOOL done = False;
+  struct hostent *hp;
+
+  if (done) 
+    return name_buf;
+
+  done = True;
+  strcpy(name_buf,"UNKNOWN");
+
+  if (getpeername(Client, &sa, &length) < 0) {
+    DEBUG(0,("getpeername failed\n"));
+    done = False;
+    return name_buf;
+  }
+
+  /* Look up the remote host name. */
+  if ((hp = gethostbyaddr((char *) &sockin->sin_addr,
+                         sizeof(sockin->sin_addr),
+                         AF_INET)) == 0) {
+    DEBUG(1,("Gethostbyaddr failed for %s\n",client_addr()));
+    StrnCpy(name_buf,client_addr(),sizeof(name_buf) - 1);
+    done = False;
+  } else {
+    StrnCpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1);
+    if (!matchname(name_buf, sockin->sin_addr)) {
+      DEBUG(0,("Matchname failed on %s %s\n",name_buf,client_addr()));
+      strcpy(name_buf,"UNKNOWN");
+    }
+  }
+  return name_buf;
+}
+
+/* return the IP addr of the client as a string */
+char *client_addr(void)
+{
+  extern int Client;
+  struct sockaddr sa;
+  struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
+  int     length = sizeof(sa);
+  static fstring addr_buf;
+  static BOOL done = False;
+
+  if (done) 
+    return addr_buf;
+
+  done = True;
+  strcpy(addr_buf,"0.0.0.0");
+
+  if (getpeername(Client, &sa, &length) < 0) {
+    DEBUG(0,("getpeername failed\n"));
+    return addr_buf;
+  }
+
+  strcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr));
+
+  return addr_buf;
+}
+
 /*******************************************************************
 sub strings with useful parameters
 ********************************************************************/
@@ -3546,8 +3162,9 @@ void standard_sub_basic(char *s)
 
   if (!strchr(s,'%')) return;
 
-  string_sub(s,"%I",Client_info.addr);
-  string_sub(s,"%M",Client_info.name);
+  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;
@@ -3569,6 +3186,21 @@ void standard_sub_basic(char *s)
 }
 
 
+/*******************************************************************
+are two IPs on the same subnet?
+********************************************************************/
+BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
+{
+  uint32 net1,net2,nmask;
+
+  nmask = ntohl(mask.s_addr);
+  net1  = ntohl(ip1.s_addr);
+  net2  = ntohl(ip2.s_addr);
+            
+  return((net1 & nmask) == (net2 & nmask));
+}
+
+
 /*******************************************************************
 write a string in unicoode format
 ********************************************************************/
@@ -3585,34 +3217,6 @@ int PutUniCode(char *dst,char *src)
   return(ret);
 }
 
-
-pstring smbrun_path = SMBRUN;
-
-/****************************************************************************
-run a command via system() using smbrun
-****************************************************************************/
-int smbrun(char *cmd,char *outfile)
-{
-  int ret;
-  pstring syscmd;  
-
-  if (!file_exist(smbrun_path,NULL))
-    {
-      DEBUG(0,("SMBRUN ERROR: Can't find %s. Installation problem?\n",smbrun_path));
-      return(1);
-    }
-
-  sprintf(syscmd,"%s \"(%s 2>&1) > %s\"",
-         smbrun_path,cmd,
-         outfile?outfile:"/dev/null");
-
-  DEBUG(5,("smbrun - running %s ",syscmd));
-  ret = system(syscmd);
-  DEBUG(5,("gave %d\n",ret));
-  return(ret);
-}
-
-
 /****************************************************************************
 a wrapper for gethostbyname() that tries with all lower and all upper case 
 if the initial name fails
@@ -3690,11 +3294,8 @@ BOOL process_exists(int pid)
     }
   }
 
-  /* a best guess for non root access */
-  if (geteuid() != 0) return(True);
-
-  /* otherwise use kill */
-  return(pid == getpid() || kill(pid,0) == 0);
+  /* CGH 8/16/96 - added ESRCH test */
+  return(pid == getpid() || kill(pid,0) == 0 || errno != ESRCH);
 #endif
 }
 
@@ -3726,16 +3327,20 @@ char *gidtoname(int gid)
 /*******************************************************************
 block sigs
 ********************************************************************/
-void BlockSignals(BOOL block)
+void BlockSignals(BOOL block,int signum)
 {
 #ifdef USE_SIGBLOCK
-  int block_mask = (sigmask(SIGTERM)|sigmask(SIGQUIT)|sigmask(SIGSEGV)
-                   |sigmask(SIGCHLD)|sigmask(SIGQUIT)|sigmask(SIGBUS)|
-                   sigmask(SIGINT));
+  int block_mask = sigmask(signum);
+  static int oldmask = 0;
   if (block) 
-    sigblock(block_mask);
+    oldmask = sigblock(block_mask);
   else
-    sigunblock(block_mask);
+    sigsetmask(oldmask);
+#elif defined(USE_SIGPROCMASK)
+  sigset_t set;
+  sigemptyset(&set);
+  sigaddset(&set,signum);
+  sigprocmask(block?SIG_BLOCK:SIG_UNBLOCK,&set,NULL);
 #endif
 }
 
@@ -3745,8 +3350,7 @@ my own panic function - not suitable for general use
 ********************************************************************/
 void ajt_panic(void)
 {
-  pstring cmd = "/usr/bin/X11/xedit -display :0 /tmp/ERROR_FAULT &";
-  smbrun(cmd,NULL);
+  system("/usr/bin/X11/xedit -display ljus:0 /tmp/ERROR_FAULT");
 }
 #endif
 
@@ -3772,14 +3376,12 @@ char *readdirname(void *p)
 
   dname = ptr->d_name;
 
-#ifdef KANJI
   {
     static pstring buf;
     strcpy(buf, dname);
     unix_to_dos(buf, True);
     dname = buf;
   }
-#endif
 
 #ifdef NEXT2
   if (telldir(p) < 0) return(NULL);
@@ -3804,270 +3406,229 @@ char *readdirname(void *p)
 }
 
 
+BOOL is_vetoed_name(char *name)
+{
+  char *namelist = lp_veto_files();
+  char *nameptr = namelist;
+  char *name_end;
 
-#if (defined(SecureWare) && defined(SCO))
-/* This is needed due to needing the nap() function but we don't want
-   to include the Xenix libraries since that will break other things...
-   BTW: system call # 0x0c28 is the same as calling nap() */
-long nap(long milliseconds) {
-  return syscall(0x0c28, milliseconds);
-}
-#endif
-
-#ifdef NO_INITGROUPS
-#include <sys/types.h>
-#include <limits.h>
-#include <grp.h>
+  /* if we have no list it's obviously not vetoed */
+  if((nameptr == NULL ) || (*nameptr == '\0')) 
+    return 0;
 
-#ifndef NULL
-#define NULL (void *)0
-#endif
+  /* if the name doesn't exist in the list, it's obviously ok too */
+  if(strstr(namelist,name) == NULL ) 
+    return 0;
 
-/****************************************************************************
- some systems don't have an initgroups call 
-****************************************************************************/
-int initgroups(char *name,gid_t id)
-{
-#ifdef NO_SETGROUPS
-  /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
-  return(0);
-#else
-  gid_t  grouplst[NGROUPS_MAX];
-  int    i,j;
-  struct group *g;
-  char   *gr;
-
-  grouplst[0] = id;
-  i = 1;
-  while (i < NGROUPS_MAX && 
-        ((g = (struct group *)getgrent()) != (struct group *)NULL)) 
-    {
-      if (g->gr_gid == id)
-       continue;
-      j = 0;
-      gr = g->gr_mem[0];
-      while (gr && (*gr != (char)NULL)) {
-       if (strcmp(name,gr) == 0) {
-         grouplst[i] = g->gr_gid;
-         i++;
-         gr = (char *)NULL;
-         break;
-       }
-       gr = g->gr_mem[++j];
-      }
+  /* 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) 
+    {
+      if ( *nameptr == '/' ) 
+        {
+          nameptr++;
+          continue;
+        }
+      if(name_end = strchr(nameptr,'/')) 
+        {
+          *name_end = 0;
+        }
+      /* 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;
     }
-  endgrent();
-  return(setgroups(i,grouplst));
-#endif
+  return 0;
 }
-#endif
 
+BOOL is_vetoed_path(char *name)
+{
+  char *namelist = lp_veto_files();
+  char *nameptr = namelist;
+  char *sub;
+  char *name_end;
+  int len;
 
-#if WRAP_MALLOC
+  /* if we have no list it's obviously not vetoed */
+  if((nameptr == NULL ) || (*nameptr == '\0')) 
+    return 0;
 
-/* undo the wrapping temporarily */
-#undef malloc
-#undef realloc
-#undef free
 
-/****************************************************************************
-wrapper for malloc() to catch memory errors
-****************************************************************************/
-void *malloc_wrapped(int size,char *file,int line)
-{
-#ifdef xx_old_malloc
-  void *res = xx_old_malloc(size);
-#else
-  void *res = malloc(size);
-#endif
-  DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
-       file,line,
-       size,(unsigned int)res));
-  return(res);
+  /* 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) 
+    {
+      if ( *nameptr == '/' ) 
+        {
+          nameptr++;
+          continue;
+        }
+      if(name_end = strchr(nameptr,'/')) 
+        {
+          *name_end = 0;
+        }
+
+      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] == '/'))) 
+             {
+               return 1;
+             }
+           /* skip to the next component of the path */
+              sub =strchr(sub,'/');
+         }
+      if(name_end == NULL) 
+        return 0;
+      /* next segment please */
+      nameptr = name_end + 1;
+    }
+  return 0;
 }
 
 /****************************************************************************
-wrapper for realloc() to catch memory errors
+routine to do file locking
 ****************************************************************************/
-void *realloc_wrapped(void *ptr,int size,char *file,int line)
+BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type)
 {
-#ifdef xx_old_realloc
-  void *res = xx_old_realloc(ptr,size);
-#else
-  void *res = realloc(ptr,size);
-#endif
-  DEBUG(3,("Realloc\n"));
-  DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
-       file,line,
-       (unsigned int)ptr));
-  DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
-       file,line,
-       size,(unsigned int)res));
-  return(res);
-}
+#if HAVE_FCNTL_LOCK
+  struct flock lock;
+  int ret;
 
-/****************************************************************************
-wrapper for free() to catch memory errors
-****************************************************************************/
-void free_wrapped(void *ptr,char *file,int line)
-{
-#ifdef xx_old_free
-  xx_old_free(ptr);
-#else
-  free(ptr);
-#endif
-  DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
-       file,line,(unsigned int)ptr));
-  return;
-}
+#if 1
+  uint32 mask = 0xC0000000;
 
-/* and re-do the define for spots lower in this file */
-#define malloc(size) malloc_wrapped(size,__FILE__,__LINE__)
-#define realloc(ptr,size) realloc_wrapped(ptr,size,__FILE__,__LINE__)
-#define free(ptr) free_wrapped(ptr,__FILE__,__LINE__)
+  /* make sure the count is reasonable, we might kill the lockd otherwise */
+  count &= ~mask;
 
-#endif
+  /* the offset is often strange - remove 2 of its bits if either of
+     the top two bits are set. Shift the top ones by two bits. This
+     still allows OLE2 apps to operate, but should stop lockd from
+     dieing */
+  if ((offset & mask) != 0)
+    offset = (offset & ~mask) | ((offset & mask) >> 2);
+#else
+  uint32 mask = ((unsigned)1<<31);
 
-#ifdef REPLACE_STRSTR
-/****************************************************************************
-Mips version of strstr doesn't seem to work correctly.
-There is a #define in includes.h to redirect calls to this function.
-****************************************************************************/
-char *Strstr(char *s, char *p)
-{
-       int len = strlen(p);
+  /* interpret negative counts as large numbers */
+  if (count < 0)
+    count &= ~mask;
 
-       while ( *s != '\0' ) {
-               if ( strncmp(s, p, len) == 0 )
-               return s;
-               s++;
-       }
+  /* no negative offsets */
+  offset &= ~mask;
 
-       return NULL;
-}
-#endif /* REPLACE_STRSTR */
+  /* count + offset must be in range */
+  while ((offset < 0 || (offset + count < 0)) && mask)
+    {
+      offset &= ~mask;
+      mask = mask >> 1;
+    }
+#endif
 
 
-#ifdef REPLACE_MKTIME
-/*******************************************************************
-a mktime() replacement for those who don't have it - contributed by 
-C.A. Lademann <cal@zls.com>
-********************************************************************/
-#define  MINUTE  60
-#define  HOUR    60*MINUTE
-#define  DAY             24*HOUR
-#define  YEAR    365*DAY
-time_t Mktime(struct tm      *t)
-{
-  struct tm       *u;
-  time_t  epoch = 0;
-  int             mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
-  y, m, i;
-
-  if(t->tm_year < 70)
-    return((time_t)-1);
-
-  epoch = (t->tm_year - 70) * YEAR + 
-    (t->tm_year / 4 - 70 / 4 - t->tm_year / 100) * DAY;
-
-  y = t->tm_year;
-  m = 0;
-
-  for(i = 0; i < t->tm_mon; i++) {
-    epoch += mon [m] * DAY;
-    if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
-      epoch += DAY;
-    
-    if(++m > 11) {
-      m = 0;
-      y++;
-    }
-  }
+  DEBUG(5,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type));
 
-  epoch += (t->tm_mday - 1) * DAY;
-  epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
-  
-  if((u = localtime(&epoch)) != NULL) {
-    t->tm_sec = u->tm_sec;
-    t->tm_min = u->tm_min;
-    t->tm_hour = u->tm_hour;
-    t->tm_mday = u->tm_mday;
-    t->tm_mon = u->tm_mon;
-    t->tm_year = u->tm_year;
-    t->tm_wday = u->tm_wday;
-    t->tm_yday = u->tm_yday;
-    t->tm_isdst = u->tm_isdst;
-#ifndef NO_TM_NAME
-    memcpy(t->tm_name, u->tm_name, LTZNMAX);
-#endif
-  }
+  lock.l_type = type;
+  lock.l_whence = SEEK_SET;
+  lock.l_start = (int)offset;
+  lock.l_len = (int)count;
+  lock.l_pid = 0;
 
-  return(epoch);
-}
-#endif /* REPLACE_MKTIME */
+  errno = 0;
 
+  ret = fcntl(fd,op,&lock);
 
+  if (errno != 0)
+    DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
 
-#ifdef REPLACE_RENAME
-/* Rename a file. (from libiberty in GNU binutils)  */
-int
-rename (zfrom, zto)
-     const char *zfrom;
-     const char *zto;
-{
-  if (link (zfrom, zto) < 0)
+  /* a lock query */
+  if (op == F_GETLK)
     {
-      if (errno != EEXIST)
-       return -1;
-      if (unlink (zto) < 0
-         || link (zfrom, zto) < 0)
-       return -1;
+      if ((ret != -1) &&
+         (lock.l_type != F_UNLCK) && 
+         (lock.l_pid != 0) && 
+         (lock.l_pid != getpid()))
+       {
+         DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid));
+         return(True);
+       }
+
+      /* it must be not locked or locked by me */
+      return(False);
     }
-  return unlink (zfrom);
-}
-#endif
 
+  /* a lock set or unset */
+  if (ret == -1)
+    {
+      DEBUG(3,("lock failed at offset %d count %d op %d type %d (%s)\n",
+              offset,count,op,type,strerror(errno)));
 
-#ifdef REPLACE_INNETGR
-/*
- * Search for a match in a netgroup. This replaces it on broken systems.
- */
-int InNetGr(group, host, user, dom)
-        char *group, *host, *user, *dom;
-{
-  char *hst, *usr, *dm;
-  
-  setnetgrent(group);
-  while (getnetgrent(&hst, &usr, &dm))
-    if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
-       ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
-       ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
-      endnetgrent();
-      return (1);
+      /* perhaps it doesn't support this sort of locking?? */
+      if (errno == EINVAL)
+       {
+         DEBUG(3,("locking not supported? returning True\n"));
+         return(True);
+       }
+
+      return(False);
     }
-  endnetgrent();
-  return (0);
-}
-#endif
 
+  /* everything went OK */
+  DEBUG(5,("Lock call successful\n"));
+
+  return(True);
+#else
+  return(False);
+#endif
+}
 
-#if WRAP_MEMCPY
-#undef memcpy
 /*******************************************************************
-a wrapper around memcpy for diagnostic purposes
+lock a file - returning a open file descriptor or -1 on failure
+The timeout is in seconds. 0 means no timeout
 ********************************************************************/
-void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line)
-{
-  if (l>64 && (((int)d)%4) != (((int)s)%4))
-    DEBUG(4,("Misaligned memcpy(0x%X,0x%X,%d) at %s(%d)\n",d,s,l,fname,line));
-#ifdef xx_old_memcpy  
-  return(xx_old_memcpy(d,s,l));
+int file_lock(char *name,int timeout)
+{  
+  int fd = open(name,O_RDWR|O_CREAT,0666);
+  time_t t=0;
+  if (fd < 0) return(-1);
+
+#if HAVE_FCNTL_LOCK
+  if (timeout) t = time(NULL);
+  while (!timeout || (time(NULL)-t < timeout)) {
+    if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)) return(fd);    
+    msleep(LOCK_RETRY_TIMEOUT);
+  }
+  return(-1);
 #else
-  return(memcpy(d,s,l));
+  return(fd);
 #endif
 }
-#define memcpy(d,s,l) memcpy_wrapped(d,s,l,__FILE__,__LINE__)
-#endif
 
+/*******************************************************************
+unlock a file locked by file_lock
+********************************************************************/
+void file_unlock(int fd)
+{
+  if (fd<0) return;
+#if HAVE_FCNTL_LOCK
+  fcntl_lock(fd,F_SETLK,0,1,F_UNLCK);
+#endif
+  close(fd);
+}