static int
wait_on_socket (int sock)
{
  struct pollfd fds[1];
  fds[0].fd = sock;
  fds[0].events = POLLIN | POLLERR | POLLHUP;
  int n = __poll (fds, 1, 5 * 1000);
  if (n == -1 && __builtin_expect (errno == EINTR, 0))
    {
      /* Handle the case where the poll() call is interrupted by a
	 signal.  We cannot just use TEMP_FAILURE_RETRY since it might
	 lead to infinite loops.  */
      struct timeval now;
      (void) __gettimeofday (&now, NULL);
      long int end = (now.tv_sec + 5) * 1000 + (now.tv_usec + 500) / 1000;
      while (1)
	{
	  long int timeout = end - (now.tv_sec * 1000
				    + (now.tv_usec + 500) / 1000);
	  n = __poll (fds, 1, timeout);
	  if (n != -1 || errno != EINTR)
	    break;
	  (void) __gettimeofday (&now, NULL);
	}
    }

  return n;
}
예제 #2
0
파일: logwtmp.c 프로젝트: Boshin/workspace
void
logwtmp (const char *line, const char *name, const char *host)
{
  struct utmp ut;

  /* Set information in new entry.  */
  memset (&ut, 0, sizeof (ut));
#if _HAVE_UT_PID - 0
  ut.ut_pid = getpid ();
#endif
#if _HAVE_UT_TYPE - 0
  ut.ut_type = name[0] ? USER_PROCESS : DEAD_PROCESS;
#endif
  strncpy (ut.ut_line, line, sizeof ut.ut_line);
  strncpy (ut.ut_name, name, sizeof ut.ut_name);
#if _HAVE_UT_HOST - 0
  strncpy (ut.ut_host, host, sizeof ut.ut_host);
#endif

#if _HAVE_UT_TV - 0
  struct timeval tv;
  __gettimeofday (&tv, NULL);
  ut.ut_tv.tv_sec = tv.tv_sec;
  ut.ut_tv.tv_usec = tv.tv_usec;
#else
  ut.ut_time = time (NULL);
#endif

  updwtmp (_PATH_WTMP, &ut);
}
/* Store the CPU time used by this process and all its
   dead children (and their dead children) in BUFFER.
   Return the elapsed real time, or (clock_t) -1 for errors.
   All times are in CLK_TCKths of a second.  */
clock_t
__times (struct tms *tms)
{
  struct task_basic_info bi;
  struct task_thread_times_info tti;
  mach_msg_type_number_t count;
  union { time_value_t tvt; struct timeval tv; } now;
  error_t err;

  count = TASK_BASIC_INFO_COUNT;
  err = __task_info (__mach_task_self (), TASK_BASIC_INFO,
		     (task_info_t) &bi, &count);
  if (err)
    return __hurd_fail (err);

  count = TASK_THREAD_TIMES_INFO_COUNT;
  err = __task_info (__mach_task_self (), TASK_THREAD_TIMES_INFO,
		     (task_info_t) &tti, &count);
  if (err)
    return __hurd_fail (err);

  tms->tms_utime = (clock_from_time_value (&bi.user_time)
		    + clock_from_time_value (&tti.user_time));
  tms->tms_stime = (clock_from_time_value (&bi.system_time)
		    + clock_from_time_value (&tti.system_time));

  /* XXX This can't be implemented until getrusage(RUSAGE_CHILDREN) can be.  */
  tms->tms_cutime = tms->tms_cstime = 0;

  if (__gettimeofday (&now.tv, NULL) < 0)
    return -1;

  return (clock_from_time_value (&now.tvt)
	  - clock_from_time_value (&bi.creation_time));
}
예제 #4
0
/* Sleep USECONDS microseconds, or until a previously set timer goes off.  */
int
usleep (useconds_t useconds)
{
  mach_port_t recv;
  struct timeval before, after;

  recv = __mach_reply_port ();

  if (__gettimeofday (&before, NULL) < 0)
    return -1;
  (void) __mach_msg (NULL, MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT,
		     0, 0, recv, (useconds + 999) / 1000, MACH_PORT_NULL);
  __mach_port_destroy (mach_task_self (), recv);
  if (__gettimeofday (&after, NULL) < 0)
    return -1;

  return 0;
}
예제 #5
0
int
__libc_nanosleep (const struct timespec *requested_time,
	     struct timespec *remaining)
{
  mach_port_t recv;
  struct timeval before, after;

  if (requested_time->tv_sec < 0
      || requested_time->tv_nsec < 0
      || requested_time->tv_nsec >= 1000000000)
    {
      errno = EINVAL;
      return -1;
    }

  const mach_msg_timeout_t ms
    = requested_time->tv_sec * 1000
    + (requested_time->tv_nsec + 999999) / 1000000;

  recv = __mach_reply_port ();

  if (remaining && __gettimeofday (&before, NULL) < 0)
    return -1;
  error_t err = __mach_msg (NULL, MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT,
			    0, 0, recv, ms, MACH_PORT_NULL);
  __mach_port_destroy (mach_task_self (), recv);
  if (err == EMACH_RCV_INTERRUPTED)
    {
      if (remaining && __gettimeofday (&after, NULL) >= 0)
	{
	  struct timeval req_time, elapsed, rem;
	  TIMESPEC_TO_TIMEVAL (&req_time, requested_time);
	  timersub (&after, &before, &elapsed);
	  timersub (&req_time, &elapsed, &rem);
	  TIMEVAL_TO_TIMESPEC (&rem, remaining);
	}

      errno = EINTR;
      return -1;
    }

  return 0;
}
예제 #6
0
void __guard_setup(void)
{
	size_t size;

	if (__guard != 0UL)
		return;

	/* Start with the "terminator canary". */
	__guard = 0xFF0A0D00UL;

#ifndef __SSP_QUICK_CANARY__
# ifdef __SSP_USE_ERANDOM__
	{
		int mib[3];
		/* Random is another depth in Linux, hence an array of 3. */
		mib[0] = CTL_KERN;
		mib[1] = KERN_RANDOM;
		mib[2] = RANDOM_ERANDOM;

		size = sizeof(unsigned long);
		if (__sysctl(mib, 3, &__guard, &size, NULL, 0) != (-1))
			if (__guard != 0UL)
				return;
	}
# endif /* ifdef __SSP_USE_ERANDOM__ */
	/* 
	 * Attempt to open kernel pseudo random device if one exists before 
	 * opening urandom to avoid system entropy depletion.
	 */
	{
		int fd;

# ifdef __SSP_USE_ERANDOM__
		if ((fd = __libc_open("/dev/erandom", O_RDONLY)) == (-1))
# endif
			fd = __libc_open("/dev/urandom", O_RDONLY);
		if (fd != (-1)) {
			size = __libc_read(fd, (char *) &__guard, sizeof(__guard));
			__libc_close(fd);
			if (size == sizeof(__guard))
				return;
		}
	}
#endif /* ifndef __SSP_QUICK_CANARY__ */

	/* Everything failed? Or we are using a weakened model of the 
	 * terminator canary */
	{
		struct timeval tv;
		__gettimeofday(&tv, NULL);
		__guard ^= tv.tv_usec ^ tv.tv_sec;
	}
}
예제 #7
0
파일: ftime.c 프로젝트: RobbenBasten/glibc
int
ftime (struct timeb *timebuf)
{
  struct timeval tv;
  struct timezone tz;

  if (__gettimeofday (&tv, &tz) < 0)
    return -1;

  timebuf->time = tv.tv_sec;
  timebuf->millitm = (tv.tv_usec + 500) / 1000;
  if (timebuf->millitm == 1000)
    {
      ++timebuf->time;
      timebuf->millitm = 0;
    }
  timebuf->timezone = tz.tz_minuteswest;
  timebuf->dstflag = tz.tz_dsttime;
  return 0;
}
예제 #8
0
파일: auth_des.c 프로젝트: bminor/glibc
/*
 * Synchronize with the server at the given address, that is,
 * adjust timep to reflect the delta between our clocks
 */
static bool_t
synchronize (struct sockaddr *syncaddr, struct rpc_timeval *timep)
{
  struct timeval mytime;
  struct rpc_timeval timeout;

  timeout.tv_sec = RTIME_TIMEOUT;
  timeout.tv_usec = 0;
  if (rtime ((struct sockaddr_in *) syncaddr, timep, &timeout) < 0)
    return FALSE;

  __gettimeofday (&mytime, (struct timezone *) NULL);
  timep->tv_sec -= mytime.tv_sec;
  if (mytime.tv_usec > timep->tv_usec)
    {
      timep->tv_sec -= 1;
      timep->tv_usec += MILLION;
    }
  timep->tv_usec -= mytime.tv_usec;
  return TRUE;
}
예제 #9
0
/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
   wake-up when the clone terminates.  The memory location contains the
   thread ID while the clone is running and is reset to zero by the kernel
   afterwards.  The kernel up to version 3.16.3 does not use the private futex
   operations for futex wake-up when the clone terminates.  */
int
__lll_timedwait_tid (int *tidp, const struct timespec *abstime)
{
  int tid;

  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
    return EINVAL;

  /* Repeat until thread terminated.  */
  while ((tid = *tidp) != 0)
    {
      struct timeval tv;
      struct timespec rt;

      /* Get the current time.  */
      (void) __gettimeofday (&tv, NULL);

      /* Compute relative timeout.  */
      rt.tv_sec = abstime->tv_sec - tv.tv_sec;
      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
      if (rt.tv_nsec < 0)
        {
          rt.tv_nsec += 1000000000;
          --rt.tv_sec;
        }

      /* Already timed out?  */
      if (rt.tv_sec < 0)
        return ETIMEDOUT;

      /* If *tidp == tid, wait until thread terminates or the wait times out.
         The kernel up to version 3.16.3 does not use the private futex
         operations for futex wake-up when the clone terminates.
      */
      if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT)
        return ETIMEDOUT;
    }

  return 0;
}
예제 #10
0
unsigned long
_create_xid (void)
{
  long int res;

  __libc_lock_lock (createxid_lock);

  if (!is_initialized)
    {
      struct timeval now;

      __gettimeofday (&now, (struct timezone *) 0);
      __srand48_r (now.tv_sec ^ now.tv_usec, &__rpc_lrand48_data);
      is_initialized = 1;
    }

  lrand48_r (&__rpc_lrand48_data, &res);

  __libc_lock_unlock (createxid_lock);

  return res;
}
예제 #11
0
int
__lll_timedlock_wait (int *futex, const struct timespec *abstime)
{
  /* Reject invalid timeouts.  */
  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
    return EINVAL;

  do
    {
      struct timeval tv;
      struct timespec rt;

      /* Get the current time.  */
      (void) __gettimeofday (&tv, NULL);

      /* Compute relative timeout.  */
      rt.tv_sec = abstime->tv_sec - tv.tv_sec;
      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
      if (rt.tv_nsec < 0)
	{
	  rt.tv_nsec += 1000000000;
	  --rt.tv_sec;
	}

      /* Already timed out?  */
      if (rt.tv_sec < 0)
	return ETIMEDOUT;

      /* Wait.  */
      int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
      if (oldval != 0)
	lll_futex_timed_wait (futex, 2, &rt);
    }
  while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);

  return 0;
}
예제 #12
0
int
__lll_timedwait_tid (int *tidp, const struct timespec *abstime)
{
  int tid;

  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
    return EINVAL;

  /* Repeat until thread terminated.  */
  while ((tid = *tidp) != 0)
    {
      struct timeval tv;
      struct timespec rt;

      /* Get the current time.  */
      (void) __gettimeofday (&tv, NULL);

      /* Compute relative timeout.  */
      rt.tv_sec = abstime->tv_sec - tv.tv_sec;
      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
      if (rt.tv_nsec < 0)
	{
	  rt.tv_nsec += 1000000000;
	  --rt.tv_sec;
	}

      /* Already timed out?  */
      if (rt.tv_sec < 0)
	return ETIMEDOUT;

      /* Wait until thread terminates.  */
      if (lll_futex_timed_wait (tidp, tid, &rt) == -ETIMEDOUT)
	return ETIMEDOUT;
    }

  return 0;
}
예제 #13
0
static void *
handle_fildes_io (void *arg)
{
  pthread_t self = pthread_self ();
  struct sched_param param;
  struct requestlist *runp = (struct requestlist *) arg;
  aiocb_union *aiocbp;
  int policy;
  int fildes;

  pthread_getschedparam (self, &policy, &param);

  do
    {
      /* If runp is NULL, then we were created to service the work queue
	 in general, not to handle any particular request. In that case we
	 skip the "do work" stuff on the first pass, and go directly to the
	 "get work off the work queue" part of this loop, which is near the
	 end. */
      if (runp == NULL)
	pthread_mutex_lock (&__aio_requests_mutex);
      else
	{
	  /* Hopefully this request is marked as running.  */
	  assert (runp->running == allocated);

	  /* Update our variables.  */
	  aiocbp = runp->aiocbp;
	  fildes = aiocbp->aiocb.aio_fildes;

	  /* Change the priority to the requested value (if necessary).  */
	  if (aiocbp->aiocb.__abs_prio != param.sched_priority
	      || aiocbp->aiocb.__policy != policy)
	    {
	      param.sched_priority = aiocbp->aiocb.__abs_prio;
	      policy = aiocbp->aiocb.__policy;
	      pthread_setschedparam (self, policy, &param);
	    }

	  /* Process request pointed to by RUNP.  We must not be disturbed
	     by signals.  */
	  if ((aiocbp->aiocb.aio_lio_opcode & 127) == LIO_READ)
	    {
	      if (sizeof (off_t) != sizeof (off64_t)
		  && aiocbp->aiocb.aio_lio_opcode & 128)
		aiocbp->aiocb.__return_value =
		  TEMP_FAILURE_RETRY (__pread64 (fildes, (void *)
						 aiocbp->aiocb64.aio_buf,
						 aiocbp->aiocb64.aio_nbytes,
						 aiocbp->aiocb64.aio_offset));
	      else
		aiocbp->aiocb.__return_value =
		  TEMP_FAILURE_RETRY (__libc_pread (fildes,
						    (void *)
						    aiocbp->aiocb.aio_buf,
						    aiocbp->aiocb.aio_nbytes,
						    aiocbp->aiocb.aio_offset));

	      if (aiocbp->aiocb.__return_value == -1 && errno == ESPIPE)
		/* The Linux kernel is different from others.  It returns
		   ESPIPE if using pread on a socket.  Other platforms
		   simply ignore the offset parameter and behave like
		   read.  */
		aiocbp->aiocb.__return_value =
		  TEMP_FAILURE_RETRY (read (fildes,
					    (void *) aiocbp->aiocb64.aio_buf,
					    aiocbp->aiocb64.aio_nbytes));
	    }
	  else if ((aiocbp->aiocb.aio_lio_opcode & 127) == LIO_WRITE)
	    {
	      if (sizeof (off_t) != sizeof (off64_t)
		  && aiocbp->aiocb.aio_lio_opcode & 128)
		aiocbp->aiocb.__return_value =
		  TEMP_FAILURE_RETRY (__pwrite64 (fildes, (const void *)
						  aiocbp->aiocb64.aio_buf,
						  aiocbp->aiocb64.aio_nbytes,
						  aiocbp->aiocb64.aio_offset));
	      else
		aiocbp->aiocb.__return_value =
		  TEMP_FAILURE_RETRY (__libc_pwrite (fildes, (const void *)
					      aiocbp->aiocb.aio_buf,
					      aiocbp->aiocb.aio_nbytes,
					      aiocbp->aiocb.aio_offset));

	      if (aiocbp->aiocb.__return_value == -1 && errno == ESPIPE)
		/* The Linux kernel is different from others.  It returns
		   ESPIPE if using pwrite on a socket.  Other platforms
		   simply ignore the offset parameter and behave like
		   write.  */
		aiocbp->aiocb.__return_value =
		  TEMP_FAILURE_RETRY (write (fildes,
					     (void *) aiocbp->aiocb64.aio_buf,
					     aiocbp->aiocb64.aio_nbytes));
	    }
	  else if (aiocbp->aiocb.aio_lio_opcode == LIO_DSYNC)
	    aiocbp->aiocb.__return_value =
	      TEMP_FAILURE_RETRY (fdatasync (fildes));
	  else if (aiocbp->aiocb.aio_lio_opcode == LIO_SYNC)
	    aiocbp->aiocb.__return_value =
	      TEMP_FAILURE_RETRY (fsync (fildes));
	  else
	    {
	      /* This is an invalid opcode.  */
	      aiocbp->aiocb.__return_value = -1;
	      __set_errno (EINVAL);
	    }

	  /* Get the mutex.  */
	  pthread_mutex_lock (&__aio_requests_mutex);

	  if (aiocbp->aiocb.__return_value == -1)
	    aiocbp->aiocb.__error_code = errno;
	  else
	    aiocbp->aiocb.__error_code = 0;

	  /* Send the signal to notify about finished processing of the
	     request.  */
	  __aio_notify (runp);

	  /* For debugging purposes we reset the running flag of the
	     finished request.  */
	  assert (runp->running == allocated);
	  runp->running = done;

	  /* Now dequeue the current request.  */
	  __aio_remove_request (NULL, runp, 0);
	  if (runp->next_prio != NULL)
	    add_request_to_runlist (runp->next_prio);

	  /* Free the old element.  */
	  __aio_free_request (runp);
	}

      runp = runlist;

      /* If the runlist is empty, then we sleep for a while, waiting for
	 something to arrive in it. */
      if (runp == NULL && optim.aio_idle_time >= 0)
	{
	  struct timeval now;
	  struct timespec wakeup_time;

	  ++idle_thread_count;
	  __gettimeofday (&now, NULL);
	  wakeup_time.tv_sec = now.tv_sec + optim.aio_idle_time;
	  wakeup_time.tv_nsec = now.tv_usec * 1000;
	  if (wakeup_time.tv_nsec >= 1000000000)
	    {
	      wakeup_time.tv_nsec -= 1000000000;
	      ++wakeup_time.tv_sec;
	    }
	  pthread_cond_timedwait (&__aio_new_request_notification,
				  &__aio_requests_mutex,
				  &wakeup_time);
	  --idle_thread_count;
	  runp = runlist;
	}

      if (runp == NULL)
	--nthreads;
      else
	{
	  assert (runp->running == yes);
	  runp->running = allocated;
	  runlist = runp->next_run;

	  /* If we have a request to process, and there's still another in
	     the run list, then we need to either wake up or create a new
	     thread to service the request that is still in the run list. */
	  if (runlist != NULL)
	    {
	      /* There are at least two items in the work queue to work on.
		 If there are other idle threads, then we should wake them
		 up for these other work elements; otherwise, we should try
		 to create a new thread. */
	      if (idle_thread_count > 0)
		pthread_cond_signal (&__aio_new_request_notification);
	      else if (nthreads < optim.aio_threads)
		{
		  pthread_t thid;
		  pthread_attr_t attr;

		  /* Make sure the thread is created detached.  */
		  pthread_attr_init (&attr);
		  pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);

		  /* Now try to start a thread. If we fail, no big deal,
		     because we know that there is at least one thread (us)
		     that is working on AIO operations. */
		  if (pthread_create (&thid, &attr, handle_fildes_io, NULL)
		      == 0)
		    ++nthreads;
		}
	    }
	}

      /* Release the mutex.  */
      pthread_mutex_unlock (&__aio_requests_mutex);
    }
  while (runp != NULL);

  return NULL;
}
예제 #14
0
파일: tempname.c 프로젝트: DonCN/haiku
/* Generate a temporary file name based on TMPL.  TMPL must match the
   rules for mk[s]temp (i.e. end in "XXXXXX").  The name constructed
   does not exist at the time of the call to __gen_tempname.  TMPL is
   overwritten with the result.

   KIND may be one of:
   __GT_NOCREATE:	simply verify that the name does not exist
			at the time of the call.
   __GT_FILE:		create the file using open(O_CREAT|O_EXCL)
			and return a read-write fd.  The file is mode 0600.
   __GT_BIGFILE:	same as __GT_FILE but use open64().
   __GT_DIR:		create a directory, which will be mode 0700.

   We use a clever algorithm to get hard-to-predict names. */
int
__gen_tempname (char *tmpl, int kind)
{
  int len;
  char *XXXXXX;
  static uint64_t value;
  uint64_t random_time_bits;
  unsigned int count;
  int fd = -1;
  int save_errno = errno;
  struct_stat64 st;

  /* A lower bound on the number of temporary files to attempt to
     generate.  The maximum total number of temporary file names that
     can exist for a given template is 62**6.  It should never be
     necessary to try all these combinations.  Instead if a reasonable
     number of names is tried (we define reasonable as 62**3) fail to
     give the system administrator the chance to remove the problems.  */
  unsigned int attempts_min = 62 * 62 * 62;

  /* The number of times to attempt to generate a temporary file.  To
     conform to POSIX, this must be no smaller than TMP_MAX.  */
  unsigned int attempts = attempts_min < TMP_MAX ? TMP_MAX : attempts_min;

  len = strlen (tmpl);
  if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
    {
      __set_errno (EINVAL);
      return -1;
    }

  /* This is where the Xs start.  */
  XXXXXX = &tmpl[len - 6];

  /* Get some more or less random data.  */
#ifdef RANDOM_BITS
  RANDOM_BITS (random_time_bits);
#else
# if HAVE_GETTIMEOFDAY || _LIBC
  {
    struct timeval tv;
    __gettimeofday (&tv, NULL);
    random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec;
  }
# else
  random_time_bits = time (NULL);
# endif
#endif
  value += random_time_bits ^ __getpid ();

  for (count = 0; count < attempts; value += 7777, ++count)
    {
      uint64_t v = value;

      /* Fill in the random bits.  */
      XXXXXX[0] = letters[v % 62];
      v /= 62;
      XXXXXX[1] = letters[v % 62];
      v /= 62;
      XXXXXX[2] = letters[v % 62];
      v /= 62;
      XXXXXX[3] = letters[v % 62];
      v /= 62;
      XXXXXX[4] = letters[v % 62];
      v /= 62;
      XXXXXX[5] = letters[v % 62];

      switch (kind)
	{
	case __GT_FILE:
	  fd = __open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
	  break;

	case __GT_BIGFILE:
	  fd = __open64 (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
	  break;

	case __GT_DIR:
	  fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
	  break;

	case __GT_NOCREATE:
	  /* This case is backward from the other three.  __gen_tempname
	     succeeds if __xstat fails because the name does not exist.
	     Note the continue to bypass the common logic at the bottom
	     of the loop.  */
	  if (__lxstat64 (_STAT_VER, tmpl, &st) < 0)
	    {
	      if (errno == ENOENT)
		{
		  __set_errno (save_errno);
		  return 0;
		}
	      else
		/* Give up now. */
		return -1;
	    }
	  continue;

	default:
	  assert (! "invalid KIND in __gen_tempname");
	}

      if (fd >= 0)
	{
	  __set_errno (save_errno);
	  return fd;
	}
      else if (errno != EEXIST)
	return -1;
    }

  /* We got out of the loop because we ran out of combinations to try.  */
  __set_errno (EEXIST);
  return -1;
}
예제 #15
0
파일: auth_des.c 프로젝트: bminor/glibc
/*
 * 2. Marshal
 */
static bool_t
authdes_marshal (AUTH *auth, XDR *xdrs)
{
  struct ad_private *ad = AUTH_PRIVATE (auth);
  struct authdes_cred *cred = &ad->ad_cred;
  struct authdes_verf *verf = &ad->ad_verf;
  des_block cryptbuf[2];
  des_block ivec;
  int status;
  int len;
  register int32_t *ixdr;
  struct timeval tval;

  /*
   * Figure out the "time", accounting for any time difference
   * with the server if necessary.
   */
  __gettimeofday (&tval, (struct timezone *) NULL);
  ad->ad_timestamp.tv_sec = tval.tv_sec + ad->ad_timediff.tv_sec;
  ad->ad_timestamp.tv_usec = tval.tv_usec + ad->ad_timediff.tv_usec;
  if (ad->ad_timestamp.tv_usec >= MILLION)
    {
      ad->ad_timestamp.tv_usec -= MILLION;
      ad->ad_timestamp.tv_sec += 1;
    }

  /*
   * XDR the timestamp and possibly some other things, then
   * encrypt them.
   * XXX We have a real Year 2038 problem here.
   */
  ixdr = (int32_t *) cryptbuf;
  IXDR_PUT_INT32 (ixdr, ad->ad_timestamp.tv_sec);
  IXDR_PUT_INT32 (ixdr, ad->ad_timestamp.tv_usec);
  if (ad->ad_cred.adc_namekind == ADN_FULLNAME)
    {
      IXDR_PUT_U_INT32 (ixdr, ad->ad_window);
      IXDR_PUT_U_INT32 (ixdr, ad->ad_window - 1);
      ivec.key.high = ivec.key.low = 0;
      status = cbc_crypt ((char *) &auth->ah_key, (char *) cryptbuf,
	      2 * sizeof (des_block), DES_ENCRYPT | DES_HW, (char *) &ivec);
    }
  else
    status = ecb_crypt ((char *) &auth->ah_key, (char *) cryptbuf,
			sizeof (des_block), DES_ENCRYPT | DES_HW);

  if (DES_FAILED (status))
    {
      debug ("authdes_marshal: DES encryption failure");
      return FALSE;
    }
  ad->ad_verf.adv_xtimestamp = cryptbuf[0];
  if (ad->ad_cred.adc_namekind == ADN_FULLNAME)
    {
      ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high;
      ad->ad_verf.adv_winverf = cryptbuf[1].key.low;
    }
  else
    {
      ad->ad_cred.adc_nickname = ad->ad_nickname;
      ad->ad_verf.adv_winverf = 0;
    }

  /*
   * Serialize the credential and verifier into opaque
   * authentication data.
   */
  if (ad->ad_cred.adc_namekind == ADN_FULLNAME)
    len = ((1 + 1 + 2 + 1) * BYTES_PER_XDR_UNIT + ad->ad_fullnamelen);
  else
    len = (1 + 1) * BYTES_PER_XDR_UNIT;

  if ((ixdr = xdr_inline (xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL)
    {
      IXDR_PUT_INT32 (ixdr, AUTH_DES);
      IXDR_PUT_U_INT32 (ixdr, len);
    }
  else
    {
      ATTEMPT (xdr_putint32 (xdrs, &auth->ah_cred.oa_flavor));
      ATTEMPT (xdr_putint32 (xdrs, &len));
    }
  ATTEMPT (xdr_authdes_cred (xdrs, cred));

  len = (2 + 1) * BYTES_PER_XDR_UNIT;
  if ((ixdr = xdr_inline (xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL)
    {
      IXDR_PUT_INT32 (ixdr, AUTH_DES);
      IXDR_PUT_U_INT32 (ixdr, len);
    }
  else
    {
      ATTEMPT (xdr_putint32 (xdrs, &auth->ah_verf.oa_flavor));
      ATTEMPT (xdr_putint32 (xdrs, &len));
    }
  ATTEMPT (xdr_authdes_verf (xdrs, verf));

  return TRUE;
}
예제 #16
0
/* call the real libc function */
static int real_gettimeofday(struct timeval *tv, ...)
{
    extern int __gettimeofday(struct timeval *, ...);
    return __gettimeofday(tv, NULL);
}
예제 #17
0
/* Generate a temporary file name based on TMPL.  TMPL must match the
   rules for mk[s]temp (i.e. end in "XXXXXX").  The name constructed
   does not exist at the time of the call to __gen_tempname.  TMPL is
   overwritten with the result.

   KIND may be one of:
   __GT_NOCREATE:	simply verify that the name does not exist
			at the time of the call.
   __GT_FILE:		create the file using open(O_CREAT|O_EXCL)
			and return a read-write fd.  The file is mode 0600.
   __GT_BIGFILE:	same as __GT_FILE but use open64().
   __GT_DIR:		create a directory, which will be mode 0700.

   We use a clever algorithm to get hard-to-predict names. */
int
__gen_tempname (char *tmpl, int kind)
{
  int len;
  char *XXXXXX;
  static uint64_t value;
  uint64_t random_time_bits;
  int count, fd = -1;
  int save_errno = errno;
  struct_stat64 st;

  len = strlen (tmpl);
  if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
    {
      __set_errno (EINVAL);
      return -1;
    }

  /* This is where the Xs start.  */
  XXXXXX = &tmpl[len - 6];

  /* Get some more or less random data.  */
#ifdef RANDOM_BITS
  RANDOM_BITS (random_time_bits);
#else
# if HAVE_GETTIMEOFDAY || _LIBC
  {
    struct timeval tv;
    __gettimeofday (&tv, NULL);
    random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec;
  }
# else
  random_time_bits = time (NULL);
# endif
#endif
  value += random_time_bits ^ __getpid ();

  for (count = 0; count < TMP_MAX; value += 7777, ++count)
    {
      uint64_t v = value;

      /* Fill in the random bits.  */
      XXXXXX[0] = letters[v % 62];
      v /= 62;
      XXXXXX[1] = letters[v % 62];
      v /= 62;
      XXXXXX[2] = letters[v % 62];
      v /= 62;
      XXXXXX[3] = letters[v % 62];
      v /= 62;
      XXXXXX[4] = letters[v % 62];
      v /= 62;
      XXXXXX[5] = letters[v % 62];

      switch (kind)
	{
	case __GT_FILE:
	  fd = __open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
	  break;

	case __GT_BIGFILE:
	  fd = __open64 (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
	  break;

	case __GT_DIR:
	  fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
	  break;

	case __GT_NOCREATE:
	  /* This case is backward from the other three.  __gen_tempname
	     succeeds if __xstat fails because the name does not exist.
	     Note the continue to bypass the common logic at the bottom
	     of the loop.  */
	  if (__lxstat64 (_STAT_VER, tmpl, &st) < 0)
	    {
	      if (errno == ENOENT)
		{
		  __set_errno (save_errno);
		  return 0;
		}
	      else
		/* Give up now. */
		return -1;
	    }
	  continue;

	default:
	  assert (! "invalid KIND in __gen_tempname");
	}

      if (fd >= 0)
	{
	  __set_errno (save_errno);
	  return fd;
	}
      else if (errno != EEXIST)
	return -1;
    }

  /* We got out of the loop because we ran out of combinations to try.  */
  __set_errno (EEXIST);
  return -1;
}
예제 #18
0
int
__try_tempname (char *tmpl, int suffixlen, void *args,
                int (*tryfunc) (char *, void *))
{
  int len;
  char *XXXXXX;
  static uint64_t value;
  uint64_t random_time_bits;
  unsigned int count;
  int fd = -1;
  int save_errno = errno;

  /* A lower bound on the number of temporary files to attempt to
     generate.  The maximum total number of temporary file names that
     can exist for a given template is 62**6.  It should never be
     necessary to try all of these combinations.  Instead if a reasonable
     number of names is tried (we define reasonable as 62**3) fail to
     give the system administrator the chance to remove the problems.  */
#define ATTEMPTS_MIN (62 * 62 * 62)

  /* The number of times to attempt to generate a temporary file.  To
     conform to POSIX, this must be no smaller than TMP_MAX.  */
#if ATTEMPTS_MIN < TMP_MAX
  unsigned int attempts = TMP_MAX;
#else
  unsigned int attempts = ATTEMPTS_MIN;
#endif

  len = strlen (tmpl);
  if (len < 6 + suffixlen || memcmp (&tmpl[len - 6 - suffixlen], "XXXXXX", 6))
    {
      __set_errno (EINVAL);
      return -1;
    }

  /* This is where the Xs start.  */
  XXXXXX = &tmpl[len - 6 - suffixlen];

  /* Get some more or less random data.  */
#ifdef RANDOM_BITS
  RANDOM_BITS (random_time_bits);
#else
  {
    struct timeval tv;
    __gettimeofday (&tv, NULL);
    random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec;
  }
#endif
  value += random_time_bits ^ __getpid ();

  for (count = 0; count < attempts; value += 7777, ++count)
    {
      uint64_t v = value;

      /* Fill in the random bits.  */
      XXXXXX[0] = letters[v % 62];
      v /= 62;
      XXXXXX[1] = letters[v % 62];
      v /= 62;
      XXXXXX[2] = letters[v % 62];
      v /= 62;
      XXXXXX[3] = letters[v % 62];
      v /= 62;
      XXXXXX[4] = letters[v % 62];
      v /= 62;
      XXXXXX[5] = letters[v % 62];

      fd = tryfunc (tmpl, args);
      if (fd >= 0)
        {
          __set_errno (save_errno);
          return fd;
        }
      else if (errno != EEXIST)
        return -1;
    }

  /* We got out of the loop because we ran out of combinations to try.  */
  __set_errno (EEXIST);
  return -1;
}
int
__pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime)
{
  sigset_t unblock, initial_mask;
  int was_signalled = 0;
  sigjmp_buf jmpbuf;

  if (atomic_decrement(&self->p_resume_count) == 0) {
    /* Set up a longjmp handler for the restart signal, unblock
       the signal and sleep. */

    if (sigsetjmp(jmpbuf, 1) == 0) {
      THREAD_SETMEM(self, p_signal_jmp, &jmpbuf);
      THREAD_SETMEM(self, p_signal, 0);
      /* Unblock the restart signal */
      sigemptyset(&unblock);
      sigaddset(&unblock, __pthread_sig_restart);
      sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);

      while (1) {
	struct timeval now;
	struct timespec reltime;

	/* Compute a time offset relative to now.  */
	__gettimeofday (&now, NULL);
	reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;
	reltime.tv_sec = abstime->tv_sec - now.tv_sec;
	if (reltime.tv_nsec < 0) {
	  reltime.tv_nsec += 1000000000;
	  reltime.tv_sec -= 1;
	}

	/* Sleep for the required duration. If woken by a signal,
	   resume waiting as required by Single Unix Specification.  */
	if (reltime.tv_sec < 0 || __libc_nanosleep(&reltime, NULL) == 0)
	  break;
      }

      /* Block the restart signal again */
      sigprocmask(SIG_SETMASK, &initial_mask, NULL);
      was_signalled = 0;
    } else {
      was_signalled = 1;
    }
    THREAD_SETMEM(self, p_signal_jmp, NULL);
  }

  /* Now was_signalled is true if we exited the above code
     due to the delivery of a restart signal.  In that case,
     we know we have been dequeued and resumed and that the
     resume count is balanced.  Otherwise, there are some
     cases to consider. First, try to bump up the resume count
     back to zero. If it goes to 1, it means restart() was
     invoked on this thread. The signal must be consumed
     and the count bumped down and everything is cool. We
     can return a 1 to the caller.
     Otherwise, no restart was delivered yet, so a potential
     race exists; we return a 0 to the caller which must deal
     with this race in an appropriate way; for example by
     atomically removing the thread from consideration for a
     wakeup---if such a thing fails, it means a restart is
     being delivered. */

  if (!was_signalled) {
    if (atomic_increment(&self->p_resume_count) != -1) {
      __pthread_wait_for_restart_signal(self);
      atomic_decrement(&self->p_resume_count); /* should be zero now! */
      /* woke spontaneously and consumed restart signal */
      return 1;
    }
    /* woke spontaneously but did not consume restart---caller must resolve */
    return 0;
  }
  /* woken due to restart signal */
  return 1;
}
예제 #20
0
파일: gai_suspend.c 프로젝트: bminor/glibc
int
gai_suspend (const struct gaicb *const list[], int ent,
	     const struct timespec *timeout)
{
  struct waitlist waitlist[ent];
  struct requestlist *requestlist[ent];
#ifndef DONT_NEED_GAI_MISC_COND
  pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
#endif
  int cnt;
  unsigned int cntr = 1;
  int none = 1;
  int result;

  /* Request the mutex.  */
  pthread_mutex_lock (&__gai_requests_mutex);

  /* There is not yet a finished request.  Signal the request that
     we are working for it.  */
  for (cnt = 0; cnt < ent; ++cnt)
    if (list[cnt] != NULL && list[cnt]->__return == EAI_INPROGRESS)
      {
	requestlist[cnt] = __gai_find_request (list[cnt]);

	if (requestlist[cnt] != NULL)
	  {
#ifndef DONT_NEED_GAI_MISC_COND
	    waitlist[cnt].cond = &cond;
#endif
	    waitlist[cnt].next = requestlist[cnt]->waiting;
	    waitlist[cnt].counterp = &cntr;
	    waitlist[cnt].sigevp = NULL;
	    waitlist[cnt].caller_pid = 0;	/* Not needed.  */
	    requestlist[cnt]->waiting = &waitlist[cnt];
	    none = 0;
	  }
      }

  if (none)
    {
      if (cnt < ent)
	/* There is an entry which is finished.  */
	result = 0;
      else
	result = EAI_ALLDONE;
    }
  else
    {
      /* There is no request done but some are still being worked on.  */
      int oldstate;

      /* Since `pthread_cond_wait'/`pthread_cond_timedwait' are cancelation
	 points we must be careful.  We added entries to the waiting lists
	 which we must remove.  So defer cancelation for now.  */
      pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate);

#ifdef DONT_NEED_GAI_MISC_COND
      result = 0;
      GAI_MISC_WAIT (result, cntr, timeout, 1);
#else
      if (timeout == NULL)
	result = pthread_cond_wait (&cond, &__gai_requests_mutex);
      else
	{
	  /* We have to convert the relative timeout value into an
	     absolute time value with pthread_cond_timedwait expects.  */
	  struct timeval now;
	  struct timespec abstime;

	  __gettimeofday (&now, NULL);
	  abstime.tv_nsec = timeout->tv_nsec + now.tv_usec * 1000;
	  abstime.tv_sec = timeout->tv_sec + now.tv_sec;
	  if (abstime.tv_nsec >= 1000000000)
	    {
	      abstime.tv_nsec -= 1000000000;
	      abstime.tv_sec += 1;
	    }

	  result = pthread_cond_timedwait (&cond, &__gai_requests_mutex,
					   &abstime);
	}
#endif

      /* Now remove the entry in the waiting list for all requests
	 which didn't terminate.  */
      for (cnt = 0; cnt < ent; ++cnt)
	if (list[cnt] != NULL && list[cnt]->__return == EAI_INPROGRESS
	    && requestlist[cnt] != NULL)
	  {
	    struct waitlist **listp = &requestlist[cnt]->waiting;

	    /* There is the chance that we cannot find our entry anymore.
	       This could happen if the request terminated and restarted
	       again.  */
	    while (*listp != NULL && *listp != &waitlist[cnt])
	      listp = &(*listp)->next;

	    if (*listp != NULL)
	      *listp = (*listp)->next;
	  }

      /* Now it's time to restore the cancelation state.  */
      pthread_setcancelstate (oldstate, NULL);

#ifndef DONT_NEED_GAI_MISC_COND
      /* Release the conditional variable.  */
      if (pthread_cond_destroy (&cond) != 0)
	/* This must never happen.  */
	abort ();
#endif

      if (result != 0)
	{
	  /* An error occurred.  Possibly it's EINTR.  We have to translate
	     the timeout error report of `pthread_cond_timedwait' to the
	     form expected from `gai_suspend'.  */
	  if (__glibc_likely (result == ETIMEDOUT))
	    result = EAI_AGAIN;
	  else if (result == EINTR)
	    result = EAI_INTR;
	  else
	    result = EAI_SYSTEM;
	}
    }

  /* Release the mutex.  */
  pthread_mutex_unlock (&__gai_requests_mutex);

  return result;
}
예제 #21
0
/*
 * Suspend waiting for a condition variable.
 * Note: we have to keep a list of condition variables which are using
 * this same mutex variable so we can detect invalid 'destroy' sequences.
 * If isconforming < 0, we skip the _pthread_testcancel(), but keep the
 * remaining conforming behavior..
 */
__private_extern__ int
_pthread_cond_wait(pthread_cond_t *ocond, 
			pthread_mutex_t *omutex,
			const struct timespec *abstime,
			int isRelative,
			int isconforming)
{
	int res;
	_pthread_cond *cond = (_pthread_cond *)ocond;
	_pthread_mutex *mutex = (_pthread_mutex *)omutex;
	struct timespec then = { 0, 0 };
	uint32_t mtxgen, mtxugen, flags=0, updateval;
	uint32_t lcntval, ucntval, scntval;
	uint32_t nlval, ulval, savebits;
	volatile uint32_t *c_lseqcnt, *c_useqcnt, *c_sseqcnt;
	uint64_t oldval64, newval64, mugen, cvlsgen;
	uint32_t *npmtx = NULL;

extern void _pthread_testcancel(pthread_t thread, int isconforming);

	res = _pthread_cond_check_init(cond, NULL);
	if (res != 0) {
		return res;
	}

	if (isconforming) {
		if (mutex->sig != _PTHREAD_MUTEX_SIG && (mutex->sig & _PTHREAD_MUTEX_SIG_init_MASK) != _PTHREAD_MUTEX_SIG_CMP) {
			return EINVAL;
		}
		if (isconforming > 0) {
			_pthread_testcancel(pthread_self(), 1);
		}
	}

	/* send relative time to kernel */
	if (abstime) {
		if (isRelative == 0) {
			struct timespec now;
			struct timeval tv;
			__gettimeofday(&tv, NULL);
			TIMEVAL_TO_TIMESPEC(&tv, &now);

			/* Compute relative time to sleep */
			then.tv_nsec = abstime->tv_nsec - now.tv_nsec;
			then.tv_sec = abstime->tv_sec - now.tv_sec;
			if (then.tv_nsec < 0) {
				then.tv_nsec += NSEC_PER_SEC;
				then.tv_sec--;
			}
			if (then.tv_sec < 0 || (then.tv_sec == 0 && then.tv_nsec == 0)) {
				return ETIMEDOUT;
			}
			if (isconforming &&
			    (abstime->tv_sec < 0 ||
			     abstime->tv_nsec < 0 ||
			     abstime->tv_nsec >= NSEC_PER_SEC)) {
				return EINVAL;
			}
		} else {
			then.tv_sec = abstime->tv_sec;
			then.tv_nsec = abstime->tv_nsec;
			if ((then.tv_sec == 0) && (then.tv_nsec == 0)) {
				return ETIMEDOUT;
			}
		}
		if (isconforming && (then.tv_sec < 0 || then.tv_nsec < 0)) {
			return EINVAL;
		}
		if (then.tv_nsec >= NSEC_PER_SEC) {
			return EINVAL;
		}
	}

	if (cond->busy != NULL && cond->busy != mutex) {
		return EINVAL;
	}

	COND_GETSEQ_ADDR(cond, &c_lseqcnt, &c_useqcnt, &c_sseqcnt);

	do {
		lcntval = *c_lseqcnt;
		ucntval = *c_useqcnt;
		scntval = *c_sseqcnt;

		oldval64 = (((uint64_t)scntval) << 32);
		oldval64 |= lcntval;

		/* remove c and p bits on S word */
		savebits = scntval & PTH_RWS_CV_BITSALL;
		ulval = (scntval & PTHRW_COUNT_MASK);
		nlval = lcntval + PTHRW_INC;
		newval64 = (((uint64_t)ulval) << 32);
		newval64 |= nlval;
	} while (OSAtomicCompareAndSwap64Barrier(oldval64, newval64, (volatile int64_t *)c_lseqcnt) != TRUE);

	cond->busy = mutex;

	res = __mtx_droplock(mutex, &flags, &npmtx, &mtxgen, &mtxugen);

	/* TBD: cases are for normal (non owner for recursive mutex; error checking)*/
	if (res != 0) {
		return EINVAL;
	}
	if ((flags & _PTHREAD_MTX_OPT_NOTIFY) == 0) {
		npmtx = NULL;
		mugen = 0;
	} else {
		mugen = ((uint64_t)mtxugen << 32) | mtxgen;
	}
	flags &= ~_PTHREAD_MTX_OPT_MUTEX;	/* reset the mutex bit as this is cvar */

	cvlsgen = ((uint64_t)(ulval | savebits)<< 32) | nlval;

	// SUSv3 requires pthread_cond_wait to be a cancellation point
	if (isconforming) {
		pthread_cleanup_push(_pthread_cond_cleanup, (void *)cond);
		updateval = __psynch_cvwait(ocond, cvlsgen, ucntval, (pthread_mutex_t *)npmtx, mugen, flags, (int64_t)then.tv_sec, (int32_t)then.tv_nsec);
		_pthread_testcancel(pthread_self(), isconforming);
		pthread_cleanup_pop(0);
	} else {
		updateval = __psynch_cvwait(ocond, cvlsgen, ucntval, (pthread_mutex_t *)npmtx, mugen, flags, (int64_t)then.tv_sec, (int32_t)then.tv_nsec);
	}

	if (updateval == (uint32_t)-1) {
		int err = errno;
		switch (err & 0xff) {
			case ETIMEDOUT:
				res = ETIMEDOUT;
				break;
			case EINTR:
				// spurious wakeup (unless canceled)
				res = 0;
				break;
			default:
				res = EINVAL;
				break;
		}

		// add unlock ref to show one less waiter
		_pthread_cond_updateval(cond, err, 0);
	} else if (updateval != 0) {
		// Successful wait
		// The return due to prepost and might have bit states
		// update S and return for prepo if needed
		_pthread_cond_updateval(cond, 0, updateval);
	}

	pthread_mutex_lock(omutex);

	return res;
}
예제 #22
0
/* This function has to be reachable by res_data.c but not publically. */
int
__res_vinit(res_state statp, int preinit) {
	register FILE *fp;
	register char *cp, **pp;
	register int n;
	char buf[BUFSIZ];
	int nserv = 0;    /* number of nameserver records read from file */
#ifdef _LIBC
	int nservall = 0; /* number of NS records read, nserv IPv4 only */
#endif
	int haveenv = 0;
	int havesearch = 0;
#ifdef RESOLVSORT
	int nsort = 0;
	char *net;
#endif
#ifndef RFC1535
	int dots;
#endif

	if (!preinit) {
		statp->retrans = RES_TIMEOUT;
		statp->retry = RES_DFLRETRY;
		statp->options = RES_DEFAULT;
		statp->id = res_randomid();
	}

#ifdef USELOOPBACK
	statp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
#else
	statp->nsaddr.sin_addr.s_addr = INADDR_ANY;
#endif
	statp->nsaddr.sin_family = AF_INET;
	statp->nsaddr.sin_port = htons(NAMESERVER_PORT);
	statp->nscount = 1;
	statp->ndots = 1;
	statp->pfcode = 0;
	statp->_vcsock = -1;
	statp->_flags = 0;
	statp->qhook = NULL;
	statp->rhook = NULL;
	statp->_u._ext.nsinit = 0;
	statp->_u._ext.nscount = 0;
#ifdef _LIBC
	statp->_u._ext.nscount6 = 0;
	for (n = 0; n < MAXNS; n++)
	    statp->_u._ext.nsaddrs[n] = NULL;
#endif

	/* Allow user to override the local domain definition */
	if ((cp = getenv("LOCALDOMAIN")) != NULL) {
		(void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
		statp->defdname[sizeof(statp->defdname) - 1] = '\0';
		haveenv++;

		/*
		 * Set search list to be blank-separated strings
		 * from rest of env value.  Permits users of LOCALDOMAIN
		 * to still have a search list, and anyone to set the
		 * one that they want to use as an individual (even more
		 * important now that the rfc1535 stuff restricts searches)
		 */
		cp = statp->defdname;
		pp = statp->dnsrch;
		*pp++ = cp;
		for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
			if (*cp == '\n')	/* silly backwards compat */
				break;
			else if (*cp == ' ' || *cp == '\t') {
				*cp = 0;
				n = 1;
			} else if (n) {
				*pp++ = cp;
				n = 0;
				havesearch = 1;
			}
		}
		/* null terminate last domain if there are excess */
		while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
			cp++;
		*cp = '\0';
		*pp++ = 0;
	}

#define	MATCH(line, name) \
	(!strncmp(line, name, sizeof(name) - 1) && \
	(line[sizeof(name) - 1] == ' ' || \
	 line[sizeof(name) - 1] == '\t'))

	if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
		/* No threads use this stream.  */
		__fsetlocking (fp, FSETLOCKING_BYCALLER);
	    /* read the config file */
	    while (fgets_unlocked(buf, sizeof(buf), fp) != NULL) {
		/* skip comments */
		if (*buf == ';' || *buf == '#')
			continue;
		/* read default domain name */
		if (MATCH(buf, "domain")) {
		    if (haveenv)	/* skip if have from environ */
			    continue;
		    cp = buf + sizeof("domain") - 1;
		    while (*cp == ' ' || *cp == '\t')
			    cp++;
		    if ((*cp == '\0') || (*cp == '\n'))
			    continue;
		    strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
		    statp->defdname[sizeof(statp->defdname) - 1] = '\0';
		    if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
			    *cp = '\0';
		    havesearch = 0;
		    continue;
		}
		/* set search list */
		if (MATCH(buf, "search")) {
		    if (haveenv)	/* skip if have from environ */
			    continue;
		    cp = buf + sizeof("search") - 1;
		    while (*cp == ' ' || *cp == '\t')
			    cp++;
		    if ((*cp == '\0') || (*cp == '\n'))
			    continue;
		    strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
		    statp->defdname[sizeof(statp->defdname) - 1] = '\0';
		    if ((cp = strchr(statp->defdname, '\n')) != NULL)
			    *cp = '\0';
		    /*
		     * Set search list to be blank-separated strings
		     * on rest of line.
		     */
		    cp = statp->defdname;
		    pp = statp->dnsrch;
		    *pp++ = cp;
		    for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
			    if (*cp == ' ' || *cp == '\t') {
				    *cp = 0;
				    n = 1;
			    } else if (n) {
				    *pp++ = cp;
				    n = 0;
			    }
		    }
		    /* null terminate last domain if there are excess */
		    while (*cp != '\0' && *cp != ' ' && *cp != '\t')
			    cp++;
		    *cp = '\0';
		    *pp++ = 0;
		    havesearch = 1;
		    continue;
		}
		/* read nameservers to query */
#ifdef _LIBC
		if (MATCH(buf, "nameserver") && nservall < MAXNS) {
#else
		if (MATCH(buf, "nameserver") && nserv < MAXNS) {
#endif
		    struct in_addr a;

		    cp = buf + sizeof("nameserver") - 1;
		    while (*cp == ' ' || *cp == '\t')
			cp++;
		    if ((*cp != '\0') && (*cp != '\n')
			&& __inet_aton(cp, &a)) {
			statp->nsaddr_list[nserv].sin_addr = a;
			statp->nsaddr_list[nserv].sin_family = AF_INET;
			statp->nsaddr_list[nserv].sin_port =
				htons(NAMESERVER_PORT);
			nserv++;
#ifdef _LIBC
			nservall++;
                    } else {
                        struct in6_addr a6;
                        char *el;

                        if ((el = strchr(cp, '\n')) != NULL)
                            *el = '\0';
                        if ((*cp != '\0') &&
                            (inet_pton(AF_INET6, cp, &a6) > 0)) {
                            struct sockaddr_in6 *sa6;

                            sa6 = malloc(sizeof(*sa6));
                            if (sa6 != NULL) {
                                sa6->sin6_addr = a6;
                                sa6->sin6_family = AF_INET6;
                                sa6->sin6_port = htons(NAMESERVER_PORT);
				statp->_u._ext.nsaddrs[nservall] = sa6;
				statp->_u._ext.nstimes[nservall] = RES_MAXTIME;
				statp->_u._ext.nssocks[nservall] = -1;
                                nservall++;
                            }
                        }
#endif
		    }
		    continue;
		}
#ifdef RESOLVSORT
		if (MATCH(buf, "sortlist")) {
		    struct in_addr a;

		    cp = buf + sizeof("sortlist") - 1;
		    while (nsort < MAXRESOLVSORT) {
			while (*cp == ' ' || *cp == '\t')
			    cp++;
			if (*cp == '\0' || *cp == '\n' || *cp == ';')
			    break;
			net = cp;
			while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
			       isascii(*cp) && !isspace(*cp))
				cp++;
			n = *cp;
			*cp = 0;
			if (__inet_aton(net, &a)) {
			    statp->sort_list[nsort].addr = a;
			    if (ISSORTMASK(n)) {
				*cp++ = n;
				net = cp;
				while (*cp && *cp != ';' &&
					isascii(*cp) && !isspace(*cp))
				    cp++;
				n = *cp;
				*cp = 0;
				if (__inet_aton(net, &a)) {
				    statp->sort_list[nsort].mask = a.s_addr;
				} else {
				    statp->sort_list[nsort].mask =
					net_mask(statp->sort_list[nsort].addr);
				}
			    } else {
				statp->sort_list[nsort].mask =
				    net_mask(statp->sort_list[nsort].addr);
			    }
			    nsort++;
			}
			*cp = n;
		    }
		    continue;
		}
#endif
		if (MATCH(buf, "options")) {
		    res_setoptions(statp, buf + sizeof("options") - 1, "conf");
		    continue;
		}
	    }
	    if (nserv > 1)
		statp->nscount = nserv;
#ifdef _LIBC
	    if (nservall - nserv > 0)
		statp->_u._ext.nscount6 = nservall - nserv;
#endif
#ifdef RESOLVSORT
	    statp->nsort = nsort;
#endif
	    (void) fclose(fp);
	}
	if (statp->defdname[0] == 0 &&
	    __gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
	    (cp = strchr(buf, '.')) != NULL)
		strcpy(statp->defdname, cp + 1);

	/* find components of local domain that might be searched */
	if (havesearch == 0) {
		pp = statp->dnsrch;
		*pp++ = statp->defdname;
		*pp = NULL;

#ifndef RFC1535
		dots = 0;
		for (cp = statp->defdname; *cp; cp++)
			dots += (*cp == '.');

		cp = statp->defdname;
		while (pp < statp->dnsrch + MAXDFLSRCH) {
			if (dots < LOCALDOMAINPARTS)
				break;
			cp = __rawmemchr(cp, '.') + 1;    /* we know there is one */
			*pp++ = cp;
			dots--;
		}
		*pp = NULL;
#ifdef DEBUG
		if (statp->options & RES_DEBUG) {
			printf(";; res_init()... default dnsrch list:\n");
			for (pp = statp->dnsrch; *pp; pp++)
				printf(";;\t%s\n", *pp);
			printf(";;\t..END..\n");
		}
#endif
#endif /* !RFC1535 */
	}

	if ((cp = getenv("RES_OPTIONS")) != NULL)
		res_setoptions(statp, cp, "env");
	statp->options |= RES_INIT;
	return (0);
}

static void
internal_function
res_setoptions(res_state statp, const char *options, const char *source) {
	const char *cp = options;
	int i;

#ifdef DEBUG
	if (statp->options & RES_DEBUG)
		printf(";; res_setoptions(\"%s\", \"%s\")...\n",
		       options, source);
#endif
	while (*cp) {
		/* skip leading and inner runs of spaces */
		while (*cp == ' ' || *cp == '\t')
			cp++;
		/* search for and process individual options */
		if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
			i = atoi(cp + sizeof("ndots:") - 1);
			if (i <= RES_MAXNDOTS)
				statp->ndots = i;
			else
				statp->ndots = RES_MAXNDOTS;
#ifdef DEBUG
			if (statp->options & RES_DEBUG)
				printf(";;\tndots=%d\n", statp->ndots);
#endif
		} else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
			i = atoi(cp + sizeof("timeout:") - 1);
			if (i <= RES_MAXRETRANS)
				statp->retrans = i;
			else
				statp->retrans = RES_MAXRETRANS;
		} else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
			i = atoi(cp + sizeof("attempts:") - 1);
			if (i <= RES_MAXRETRY)
				statp->retry = i;
			else
				statp->retry = RES_MAXRETRY;
		} else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
#ifdef DEBUG
			if (!(statp->options & RES_DEBUG)) {
				printf(";; res_setoptions(\"%s\", \"%s\")..\n",
				       options, source);
				statp->options |= RES_DEBUG;
			}
			printf(";;\tdebug\n");
#endif
		} else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
			statp->options |= RES_USE_INET6;
		} else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
			statp->options |= RES_ROTATE;
		} else if (!strncmp(cp, "no-check-names",
				    sizeof("no-check-names") - 1)) {
			statp->options |= RES_NOCHECKNAME;
		} else {
			/* XXX - print a warning here? */
		}
		/* skip to next run of spaces */
		while (*cp && *cp != ' ' && *cp != '\t')
			cp++;
	}
}

#ifdef RESOLVSORT
/* XXX - should really support CIDR which means explicit masks always. */
static u_int32_t
net_mask(in)		/* XXX - should really use system's version of this */
	struct in_addr in;
{
	register u_int32_t i = ntohl(in.s_addr);

	if (IN_CLASSA(i))
		return (htonl(IN_CLASSA_NET));
	else if (IN_CLASSB(i))
		return (htonl(IN_CLASSB_NET));
	return (htonl(IN_CLASSC_NET));
}
#endif

u_int
res_randomid(void) {
	struct timeval now;

	__gettimeofday(&now, NULL);
	return (0xffff & (now.tv_sec ^ now.tv_usec ^ __getpid()));
}

/*
 * This routine is for closing the socket if a virtual circuit is used and
 * the program wants to close it.  This provides support for endhostent()
 * which expects to close the socket.
 *
 * This routine is not expected to be user visible.
 */
void
res_nclose(res_state statp) {
	int ns;

	if (statp->_vcsock >= 0) {
		(void) __close(statp->_vcsock);
		statp->_vcsock = -1;
		statp->_flags &= ~(RES_F_VC | RES_F_CONN);
	}
#ifdef _LIBC
	for (ns = 0; ns < statp->_u._ext.nscount + statp->_u._ext.nscount6;
	     ns++)
#else
	for (ns = 0; ns < statp->_u._ext.nscount; ns++)
#endif
	{
		if (statp->_u._ext.nssocks[ns] != -1) {
			(void) __close(statp->_u._ext.nssocks[ns]);
			statp->_u._ext.nssocks[ns] = -1;
		}
	}
	statp->_u._ext.nsinit = 0;
}