Beispiel #1
0
/* Open the catalog and return a descriptor for the catalog.  */
nl_catd
catopen (const char *cat_name, int flag)
{
  __nl_catd result;
  const char *env_var = NULL;
  const char *nlspath = NULL;
  char *tmp = NULL;

  if (strchr (cat_name, '/') == NULL)
    {
      if (flag == NL_CAT_LOCALE)
	/* Use the current locale setting for LC_MESSAGES.  */
	env_var = setlocale (LC_MESSAGES, NULL);
      else
	/* Use the LANG environment variable.  */
	env_var = getenv ("LANG");

      if (env_var == NULL || *env_var == '\0'
	  || (__libc_enable_secure && strchr (env_var, '/') != NULL))
	env_var = "C";

      nlspath = getenv ("NLSPATH");
      if (nlspath != NULL && *nlspath != '\0')
	{
	  /* Append the system dependent directory.  */
	  size_t len = strlen (nlspath) + 1 + sizeof NLSPATH;
	  tmp = malloc (len);

	  if (__glibc_unlikely (tmp == NULL))
	    return (nl_catd) -1;

	  __stpcpy (__stpcpy (__stpcpy (tmp, nlspath), ":"), NLSPATH);
	  nlspath = tmp;
	}
      else
	nlspath = NLSPATH;
    }

  result = (__nl_catd) malloc (sizeof (*result));
  if (result == NULL)
    {
      /* We cannot get enough memory.  */
      result = (nl_catd) -1;
    }
  else if (__open_catalog (cat_name, nlspath, env_var, result) != 0)
    {
      /* Couldn't open the file.  */
      free ((void *) result);
      result = (nl_catd) -1;
    }

  free (tmp);
  return (nl_catd) result;
}
Beispiel #2
0
/* Make a '\0' separated arg vector from a unix argv vector, returning it in
   ARGZ, and the total length in LEN.  If a memory allocation error occurs,
   ENOMEM is returned, otherwise 0.  */
error_t
__argz_create (char *const argv[], char **argz, size_t *len)
{
  int argc;
  size_t tlen = 0;
  char *const *ap;
  char *p;

  for (argc = 0; argv[argc] != NULL; ++argc)
    tlen += strlen (argv[argc]) + 1;

  if (tlen == 0)
    *argz = NULL;
  else
    {
      *argz = malloc (tlen);
      if (*argz == NULL)
	return ENOMEM;

      for (p = *argz, ap = argv; *ap; ++ap, ++p)
	p = __stpcpy (p, *ap);
    }
  *len = tlen;

  return 0;
}
static char *
describe_number (string_t description, const char *flavor, long int i)
{
  unsigned long int j;
  char *p = flavor ? description : __stpcpy (description, flavor);
  char *end;

  /* Handle sign.  */
  if (i < 0)
    {
      i = -i;
      *p++ = '-';
    }

  /* Allocate space for the number at the end of DESCRIPTION.  */
  for (j = i; j >= 10; j /= 10)
    p++;
  end = p + 1;
  *end = '\0';

  do
    {
      *p-- = '0' + i % 10;
      i /= 10;
    } while (i != 0);

  return end;
}
Beispiel #4
0
enum nss_status
_nss_grp_create_tablename (int *errnop)
{
  if (grp_tablename_val == NULL)
    {
      const char *local_dir = nis_local_directory ();
      size_t local_dir_len = strlen (local_dir);
      static const char prefix[] = "group.org_dir.";

      char *p = malloc (sizeof (prefix) + local_dir_len);
      if (p == NULL)
	{
	  *errnop = errno;
	  return NSS_STATUS_TRYAGAIN;
	}

      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);

      grp_tablename_len = sizeof (prefix) - 1 + local_dir_len;

      atomic_write_barrier ();

      if (atomic_compare_and_exchange_bool_acq (&grp_tablename_val, p, NULL))
	{
	  /* Another thread already installed the value.  */
	  free (p);
	  grp_tablename_len = strlen (grp_tablename_val);
	}
    }

  return NSS_STATUS_SUCCESS;
}
Beispiel #5
0
static enum nss_status
_nss_create_tablename (int *errnop)
{
  if (tablename_val == NULL)
    {
      const char *local_dir = nis_local_directory ();
      size_t local_dir_len = strlen (local_dir);
      static const char prefix[] = "ethers.org_dir.";

      char *p = malloc (sizeof (prefix) + local_dir_len);
      if (p == NULL)
	{
	  *errnop = errno;
	  return NSS_STATUS_TRYAGAIN;
	}

      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);

      tablename_len = sizeof (prefix) - 1 + local_dir_len;

      atomic_write_barrier ();

      tablename_val = p;
    }
  return NSS_STATUS_SUCCESS;
}
Beispiel #6
0
__locale_t
__duplocale (__locale_t dataset)
{
  /* This static object is returned for newlocale (LC_ALL_MASK, "C").  */
  if (dataset == _nl_C_locobj_ptr)
    return dataset;

  /* Handle a special value.  */
  if (dataset == LC_GLOBAL_LOCALE)
    dataset = &_nl_global_locale;

  __locale_t result;
  int cnt;
  size_t names_len = 0;

  /* Calculate the total space we need to store all the names.  */
  for (cnt = 0; cnt < __LC_LAST; ++cnt)
    if (cnt != LC_ALL && dataset->__names[cnt] != _nl_C_name)
      names_len += strlen (dataset->__names[cnt]) + 1;

  /* Get memory.  */
  result = malloc (sizeof (struct __locale_struct) + names_len);

  if (result != NULL)
    {
      char *namep = (char *) (result + 1);

      /* We modify global data (the usage counts).  */
      __libc_rwlock_wrlock (__libc_setlocale_lock);

      for (cnt = 0; cnt < __LC_LAST; ++cnt)
	if (cnt != LC_ALL)
	  {
	    result->__locales[cnt] = dataset->__locales[cnt];
	    if (result->__locales[cnt]->usage_count < MAX_USAGE_COUNT)
	      ++result->__locales[cnt]->usage_count;

	    if (dataset->__names[cnt] == _nl_C_name)
	      result->__names[cnt] = _nl_C_name;
	    else
	      {
		result->__names[cnt] = namep;
		namep = __stpcpy (namep, dataset->__names[cnt]) + 1;
	      }
	  }

      /* Update the special members.  */
      result->__ctype_b = dataset->__ctype_b;
      result->__ctype_tolower = dataset->__ctype_tolower;
      result->__ctype_toupper = dataset->__ctype_toupper;

      /* It's done.  */
      __libc_rwlock_unlock (__libc_setlocale_lock);
    }

  return result;
}
static enum nss_status
_nss_create_tablename (int *errnop)
{
  if (tablename_val == NULL)
    {
      char buf [40 + strlen (nis_local_directory ())];
      char *p;

      p = __stpcpy (buf, "passwd.org_dir.");
      p = __stpcpy (p, nis_local_directory ());
      tablename_val = __strdup (buf);
      if (tablename_val == NULL)
	{
	  *errnop = errno;
	  return NSS_STATUS_TRYAGAIN;
	}
      tablename_len = strlen (tablename_val);
    }
  return NSS_STATUS_SUCCESS;
}
Beispiel #8
0
char *strcpy(char *dest, const char *src)
{
#if 1
	__stpcpy(dest, src);
	return dest;
#else
	const unsigned char *s = src;
	unsigned char *d = dest;
	while ((*d++ = *s++));
	return dest;
#endif
}
static char *
describe_port (string_t description, mach_port_t port)
{
  int i;

  if (port == MACH_PORT_NULL)
    return __stpcpy (description, "(null)");
  if (port == MACH_PORT_DEAD)
    return __stpcpy (description, "(dead)");

  if (port == __mach_task_self ())
    return __stpcpy (description, "task-self");

  for (i = 0; i < _hurd_nports; ++i)
    if (port == _hurd_ports[i].port)
      return describe_number (description, "init#", i);

  if (_hurd_init_dtable)
    {
      for (i = 0; i < _hurd_init_dtablesize; ++i)
	if (port == _hurd_init_dtable[i])
	  return describe_number (description, "fd#", i);
    }
  else if (_hurd_dtable)
    {
      for (i = 0; i < _hurd_dtablesize; ++i)
	if (_hurd_dtable[i] == NULL)
	  continue;
	else if (port == _hurd_dtable[i]->port.port)
	  return describe_number (description, "fd#", i);
	else if (port == _hurd_dtable[i]->ctty.port)
	  return describe_number (description, "bgfd#", i);
    }

  return describe_number (description, "port#", port);
}
Beispiel #10
0
static TACommandVerdict __stpcpy_cmd(TAThread thread, TAInputStream stream)
{
    char* s1;
    char* s2;
    char* res;

    // Prepare
    s1 = (char*)readPointer(&stream);
    s2 = (char*)readPointer(&stream);

    START_TARGET_OPERATION(thread);

    // Execute
    res = __stpcpy(s1, s2);

    END_TARGET_OPERATION(thread);

    // Response
    writePointer(thread, res);
    sendResponse(thread);

    return taDefaultVerdict;
}
Beispiel #11
0
static void
__vsyslogex_chk(int pri, int flag, pid_t cpid, pid_t ctid, const char *fmt, va_list ap) {
    struct tm now_tm;
    time_t now;
    int fd;
    FILE *f;
    char *buf = 0;
    size_t bufsize = 0;
    size_t prioff, msgoff;
#ifndef NO_SIGPIPE
    struct sigaction action, oldaction;
    int sigpipe;
#endif
    int saved_errno = errno;
    char failbuf[3 * sizeof (pid_t) + sizeof "out of memory []"];
    const int LogMask = setlogmask(0);

#ifdef _DEBUGFLAGS_H_
    {
        static unsigned int registered = 0;
        if (unlikely(0 == registered)) {
            registered = 1; /* dirty work around to avoid deadlock: syslogex->register->syslogex */
            registered = (registerLibraryDebugFlags(&debugFlags) == EXIT_SUCCESS);
        }
    }
#endif /*_DEBUGFLAGS_H_*/

#define INTERNALLOG LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
    /* Check for invalid bits. */
    if (unlikely(pri & ~(LOG_PRIMASK | LOG_FACMASK))) {
        /*syslog(INTERNALLOG,
               "syslog: unknown facility/priority: %x", pri);*/
        WARNING_MSG("unknown facility/priority: %x", pri);
        pri &= LOG_PRIMASK | LOG_FACMASK;
    }

    /* Check priority against setlogmask values. */
    if (unlikely((LOG_MASK(LOG_PRI(pri)) & LogMask) == 0))
        return;

    /* Set default facility if none specified. */
    if (unlikely((pri & LOG_FACMASK) == 0))
        pri |= LogFacility;

    /* Build the message in a memory-buffer stream.  */
    f = open_memstream(&buf, &bufsize);
    if (unlikely(f == NULL)) {
        /* We cannot get a stream.  There is not much we can do but
           emitting an error messages with the Process ID.  */
        char numbuf[3 * sizeof (pid_t)];
        char *nump;
        char *endp = __stpcpy(failbuf, "out of memory [");
        pid_t pid = getpid();

        nump = numbuf + sizeof (numbuf);
        /* The PID can never be zero.  */
        do {
            *--nump = '0' + pid % 10;
        } while ((pid /= 10) != 0);

        endp = mempcpy((void*) endp, (const void*) nump, (size_t) ((numbuf + sizeof (numbuf)) - nump));
        *endp++ = ']';
        *endp = '\0';
        buf = failbuf;
        bufsize = endp - failbuf;
        msgoff = 0;
    } else {
        __fsetlocking(f, FSETLOCKING_BYCALLER);
        prioff = fprintf(f, "<%d>", pri);
        (void) time(&now);
        f->_IO_write_ptr += strftime(f->_IO_write_ptr,
                f->_IO_write_end - f->_IO_write_ptr,
                "%h %e %T ",
                localtime_r(&now, &now_tm));
        /*f->_IO_write_ptr += strftime_l (f->_IO_write_ptr,
                                          f->_IO_write_end - f->_IO_write_ptr,
                                          "%h %e %T ",
                                          localtime_r (&now, &now_tm));*/
        msgoff = ftell(f);
        if (LogTag == NULL)
            LogTag = __progname;
        if (LogTag != NULL)
            fputs_unlocked(LogTag, f);
        if (LogStat & LOG_PID) {
            const pid_t pid = ((0 == cpid) ? getpid() : cpid);
            if (LogStat & LOG_TID) {
                const pid_t tid = ((0 == ctid) ? gettid() : ctid);
                fprintf(f, "[%d:%d]", (int) pid, (int) tid);
            } else {
                fprintf(f, "[%d]", (int) pid);
            }
        }

        if (LogStat & LOG_RDTSC) {
            const unsigned long long int t = rdtsc();
            fprintf(f, "(%llu)", t);
        } /* (LogStat & LOG_RDTSC) */

        if (LogStat & LOG_CLOCK) {
            #if HAVE_CLOCK_GETTIME
                struct timespec timeStamp;
                if (clock_gettime(CLOCK_MONOTONIC,&timeStamp) == 0) {
                    fprintf(f,"(%lu.%.9d)",timeStamp.tv_sec,timeStamp.tv_nsec);
                } else {
                    const int error = errno;
                    ERROR_MSG("clock_gettime CLOCK_MONOTONIC error %d (%m)",error);
            }
            #else
                static unsigned int alreadyPrinted = 0;
                if (unlikely(0 == alreadyPrinted)) {
                    ERROR_MSG("clock_gettime  not available on this system");
                    alreadyPrinted = 1;
                }
            #endif
        }  /* (LogStat & LOG_CLOCK) */

        if (LogStat & LOG_LEVEL) {
            switch (LOG_PRI(pri)) {
                case LOG_EMERG:
                    fprintf(f, "[EMERG]");
                    break;
                case LOG_ALERT:
                    fprintf(f, "[ALERT]");
                    break;
                case LOG_CRIT:
                    fprintf(f, "[CRIT]");
                    break;
                case LOG_ERR:
                    fprintf(f, "[ERROR]");
                    break;
                case LOG_WARNING:
                    fprintf(f, "[WARNING]");
                    break;
                case LOG_NOTICE:
                    fprintf(f, "[NOTICE]");
                    break;
                case LOG_INFO:
                    fprintf(f, "[INFO]");
                    break;
                case LOG_DEBUG:
                    fprintf(f, "[DEBUG]");
                    break;
            } /* switch(LOG_PRI(pri))*/
        } /* (LogStat & LOG_LEVEL) */

        if (LogTag != NULL) {
            putc_unlocked(':', f);
            putc_unlocked(' ', f);
        }

        /* Restore errno for %m format.  */
        __set_errno(saved_errno);

        /* We have the header.  Print the user's format into the
         buffer.  */
        if (flag == -1) {
            vfprintf(f, fmt, ap);
        } else {
            __vfprintf_chk(f, flag, fmt, ap);
        }

        /* Close the memory stream; this will finalize the data
           into a malloc'd buffer in BUF.  */
        fclose(f);
    }

    /* Output to stderr if requested. */
    if (LogStat & LOG_PERROR) {
        struct iovec iov[2];
        register struct iovec *v = iov;

        v->iov_base = buf + msgoff;
        v->iov_len = bufsize - msgoff;
        /* Append a newline if necessary.  */
        if (buf[bufsize - 1] != '\n') {
            ++v;
            v->iov_base = (char *) "\n";
            v->iov_len = 1;
        }

        pthread_cleanup_push(free, buf == failbuf ? NULL : buf);

        /* writev is a cancellation point.  */
        (void) writev(STDERR_FILENO, iov, v - iov + 1);

        pthread_cleanup_pop(0);
    }

    /* Prepare for multiple users.  We have to take care: open and
  write are cancellation points.  */
    struct cleanup_arg clarg;
    clarg.buf = buf;
    clarg.oldaction = NULL;
    pthread_cleanup_push(cancel_handler, &clarg);
    pthread_mutex_lock(&syslogex_lock);

#ifndef NO_SIGPIPE
    /* Prepare for a broken connection.  */
    memset(&action, 0, sizeof (action));
    action.sa_handler = sigpipe_handler;
    sigemptyset(&action.sa_mask);
    sigpipe = __sigaction(SIGPIPE, &action, &oldaction);
    if (sigpipe == 0)
        clarg.oldaction = &oldaction;
#endif

    /* Get connected, output the message to the local logger. */
    if (!connected) {
        openlog_internal(LogTag, LogStat | LOG_NDELAY, 0);
    }

    /* If we have a SOCK_STREAM connection, also send ASCII NUL as
  a record terminator.  */
    if (LogType == SOCK_STREAM) {
        ++bufsize;
    }

    if (!connected || __send(LogFile, buf, bufsize, send_flags) < 0) {
        if (connected) {
            /* Try to reopen the syslog connection.  Maybe it went
          down.  */
            closelog_internal();
            openlog_internal(LogTag, LogStat | LOG_NDELAY, 0);
        }

        if (!connected || __send(LogFile, buf, bufsize, send_flags) < 0) {
            closelog_internal(); /* attempt re-open next time */
            /*
             * Output the message to the console; don't worry
             * about blocking, if console blocks everything will.
             * Make sure the error reported is the one from the
             * syslogd failure.
             */
            if (LogStat & LOG_CONS &&
                    (fd = __open(_PATH_CONSOLE, O_WRONLY | O_NOCTTY, 0)) >= 0) {
                dprintf(fd, "%s\r\n", buf + msgoff);
                (void) __close(fd);
            }
        }
    }

#ifndef NO_SIGPIPE
    if (sigpipe == 0)
        __sigaction(SIGPIPE, &oldaction, (struct sigaction *) NULL);
#endif

    /* End of critical section.  */
    pthread_cleanup_pop(0);
    pthread_mutex_unlock(&syslogex_lock);

    if (buf != failbuf) {
        free(buf);
    }
}
Beispiel #12
0
/* Return the pathname of the terminal FD is open on, or NULL on errors.
   The returned storage is good only until the next call to this function.  */
char *
ttyname (int fd)
{
  static size_t buflen;
  char procname[30];
  struct stat64 st, st1;
  int dostat = 0;
  char *name;
  int save = errno;
  struct termios term;

  /* isatty check, tcgetattr is used because it sets the correct
     errno (EBADF resp. ENOTTY) on error.  */
  if (__builtin_expect (__tcgetattr (fd, &term) < 0, 0))
    return NULL;

  /* We try using the /proc filesystem.  */
  *_fitoa_word (fd, __stpcpy (procname, "/proc/self/fd/"), 10, 0) = '\0';

  if (buflen == 0)
    {
      buflen = 4095;
      ttyname_buf = (char *) malloc (buflen + 1);
      if (ttyname_buf == NULL)
	{
	  buflen = 0;
	  return NULL;
	}
    }

  ssize_t len = __readlink (procname, ttyname_buf, buflen);
  if (__builtin_expect (len == -1 && errno == ENOENT, 0))
    {
      __set_errno (EBADF);
      return NULL;
    }

  if (__builtin_expect (len != -1
#ifndef __ASSUME_PROC_SELF_FD_SYMLINK
			/* This is for Linux 2.0.  */
			&& ttyname_buf[0] != '['
#endif
			, 1))
    {
      if ((size_t) len >= buflen)
	return NULL;
      /* readlink need not terminate the string.  */
      ttyname_buf[len] = '\0';
      return ttyname_buf;
    }

  if (__fxstat64 (_STAT_VER, fd, &st) < 0)
    return NULL;

  if (__xstat64 (_STAT_VER, "/dev/pts", &st1) == 0 && S_ISDIR (st1.st_mode))
    {
#ifdef _STATBUF_ST_RDEV
      name = getttyname ("/dev/pts", st.st_rdev, st.st_ino, save, &dostat);
#else
      name = getttyname ("/dev/pts", st.st_dev, st.st_ino, save, &dostat);
#endif
    }
  else
    {
      __set_errno (save);
      name = NULL;
    }

  if (!name && dostat != -1)
    {
#ifdef _STATBUF_ST_RDEV
      name = getttyname ("/dev", st.st_rdev, st.st_ino, save, &dostat);
#else
      name = getttyname ("/dev", st.st_dev, st.st_ino, save, &dostat);
#endif
    }

  if (!name && dostat != -1)
    {
      dostat = 1;
#ifdef _STATBUF_ST_RDEV
      name = getttyname ("/dev", st.st_rdev, st.st_ino, save, &dostat);
#else
      name = getttyname ("/dev", st.st_dev, st.st_ino, save, &dostat);
#endif
    }

  return name;
}
Beispiel #13
0
/* Determine the directories we are looking for data in.  */
void
internal_function
__gconv_get_path (void)
{
  struct path_elem *result;
  __libc_lock_define_initialized (static, lock);

  __libc_lock_lock (lock);

  /* Make sure there wasn't a second thread doing it already.  */
  result = (struct path_elem *) __gconv_path_elem;
  if (result == NULL)
    {
      /* Determine the complete path first.  */
      char *gconv_path;
      size_t gconv_path_len;
      char *elem;
      char *oldp;
      char *cp;
      int nelems;
      char *cwd;
      size_t cwdlen;

      if (__gconv_path_envvar == NULL)
	{
	  /* No user-defined path.  Make a modifiable copy of the
	     default path.  */
	  gconv_path = strdupa (default_gconv_path);
	  gconv_path_len = sizeof (default_gconv_path);
	  cwd = NULL;
	  cwdlen = 0;
	}
      else
	{
	  /* Append the default path to the user-defined path.  */
	  size_t user_len = strlen (__gconv_path_envvar);

	  gconv_path_len = user_len + 1 + sizeof (default_gconv_path);
	  gconv_path = alloca (gconv_path_len);
	  __mempcpy (__mempcpy (__mempcpy (gconv_path, __gconv_path_envvar,
					   user_len),
				":", 1),
		     default_gconv_path, sizeof (default_gconv_path));
	  cwd = __getcwd (NULL, 0);
	  cwdlen = strlen (cwd);
	}
      assert (default_gconv_path[0] == '/');

      /* In a first pass we calculate the number of elements.  */
      oldp = NULL;
      cp = strchr (gconv_path, ':');
      nelems = 1;
      while (cp != NULL)
	{
	  if (cp != oldp + 1)
	    ++nelems;
	  oldp = cp;
	  cp =  strchr (cp + 1, ':');
	}

      /* Allocate the memory for the result.  */
      result = (struct path_elem *) malloc ((nelems + 1)
					    * sizeof (struct path_elem)
					    + gconv_path_len + nelems
					    + (nelems - 1) * (cwdlen + 1));
      if (result != NULL)
	{
	  char *strspace = (char *) &result[nelems + 1];
	  int n = 0;

	  /* Separate the individual parts.  */
	  __gconv_max_path_elem_len = 0;
	  elem = __strtok_r (gconv_path, ":", &gconv_path);
	  assert (elem != NULL);
	  do
	    {
	      result[n].name = strspace;
	      if (elem[0] != '/')
		{
		  assert (cwd != NULL);
		  strspace = __mempcpy (strspace, cwd, cwdlen);
		  *strspace++ = '/';
		}
	      strspace = __stpcpy (strspace, elem);
	      if (strspace[-1] != '/')
		*strspace++ = '/';

	      result[n].len = strspace - result[n].name;
	      if (result[n].len > __gconv_max_path_elem_len)
		__gconv_max_path_elem_len = result[n].len;

	      *strspace++ = '\0';
	      ++n;
	    }
	  while ((elem = __strtok_r (NULL, ":", &gconv_path)) != NULL);

	  result[n].name = NULL;
	  result[n].len = 0;
	}

      __gconv_path_elem = result ?: (struct path_elem *) &empty_path_elem;

      if (cwd != NULL)
	free (cwd);
    }
Beispiel #14
0
ftw_startup (const char *dir, int is_nftw, void *func, int descriptors,
	     int flags)
{
  struct ftw_data data;
  struct STAT st;
  int result = 0;
  int save_err;
  int cwdfd = -1;
  char *cwd = NULL;
  char *cp;

  /* First make sure the parameters are reasonable.  */
  if (dir[0] == '\0')
    {
      __set_errno (ENOENT);
      return -1;
    }

  data.maxdir = descriptors < 1 ? 1 : descriptors;
  data.actdir = 0;
  data.dirstreams = (struct dir_data **) alloca (data.maxdir
						 * sizeof (struct dir_data *));
  memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *));

  /* PATH_MAX is always defined when we get here.  */
  data.dirbufsize = MAX (2 * strlen (dir), PATH_MAX);
  data.dirbuf = (char *) malloc (data.dirbufsize);
  if (data.dirbuf == NULL)
    return -1;
  cp = __stpcpy (data.dirbuf, dir);
  /* Strip trailing slashes.  */
  while (cp > data.dirbuf + 1 && cp[-1] == '/')
    --cp;
  *cp = '\0';

  data.ftw.level = 0;

  /* Find basename.  */
  while (cp > data.dirbuf && cp[-1] != '/')
    --cp;
  data.ftw.base = cp - data.dirbuf;

  data.flags = flags;

  /* This assignment might seem to be strange but it is what we want.
     The trick is that the first three arguments to the `ftw' and
     `nftw' callback functions are equal.  Therefore we can call in
     every case the callback using the format of the `nftw' version
     and get the correct result since the stack layout for a function
     call in C allows this.  */
  data.func = (NFTW_FUNC_T) func;

  /* Since we internally use the complete set of FTW_* values we need
     to reduce the value range before calling a `ftw' callback.  */
  data.cvt_arr = is_nftw ? nftw_arr : ftw_arr;

  /* No object known so far.  */
  data.known_objects = NULL;

  /* Now go to the directory containing the initial file/directory.  */
  if (flags & FTW_CHDIR)
    {
      /* We have to be able to go back to the current working
	 directory.  The best way to do this is to use a file
	 descriptor.  */
      cwdfd = __open (".", O_RDONLY | O_DIRECTORY);
      if (cwdfd == -1)
	{
	  /* Try getting the directory name.  This can be needed if
	     the current directory is executable but not readable.  */
	  if (errno == EACCES)
	    /* GNU extension ahead.  */
	    cwd =  __getcwd (NULL, 0);

	  if (cwd == NULL)
	    goto out_fail;
	}
      else if (data.maxdir > 1)
	/* Account for the file descriptor we use here.  */
	--data.maxdir;

      if (data.ftw.base > 0)
	{
	  /* Change to the directory the file is in.  In data.dirbuf
	     we have a writable copy of the file name.  Just NUL
	     terminate it for now and change the directory.  */
	  if (data.ftw.base == 1)
	    /* I.e., the file is in the root directory.  */
	    result = __chdir ("/");
	  else
	    {
	      char ch = data.dirbuf[data.ftw.base - 1];
	      data.dirbuf[data.ftw.base - 1] = '\0';
	      result = __chdir (data.dirbuf);
	      data.dirbuf[data.ftw.base - 1] = ch;
	    }
	}
    }

  /* Get stat info for start directory.  */
  if (result == 0)
    {
      const char *name;

      if (data.flags & FTW_CHDIR)
	{
	  name = data.dirbuf + data.ftw.base;
	  if (name[0] == '\0')
	    name = ".";
	}
      else
	name = data.dirbuf;

      if (((flags & FTW_PHYS)
	   ? LXSTAT (_STAT_VER, name, &st)
	   : XSTAT (_STAT_VER, name, &st)) < 0)
	{
	  if (!(flags & FTW_PHYS)
	      && errno == ENOENT
	      && LXSTAT (_STAT_VER, name, &st) == 0
	      && S_ISLNK (st.st_mode))
	    result = (*data.func) (data.dirbuf, &st, data.cvt_arr[FTW_SLN],
				   &data.ftw);
	  else
	    /* No need to call the callback since we cannot say anything
	       about the object.  */
	    result = -1;
	}
      else
	{
	  if (S_ISDIR (st.st_mode))
	    {
	      /* Remember the device of the initial directory in case
		 FTW_MOUNT is given.  */
	      data.dev = st.st_dev;

	      /* We know this directory now.  */
	      if (!(flags & FTW_PHYS))
		result = add_object (&data, &st);

	      if (result == 0)
		result = ftw_dir (&data, &st, NULL);
	    }
	  else
	    {
	      int flag = S_ISLNK (st.st_mode) ? FTW_SL : FTW_F;

	      result = (*data.func) (data.dirbuf, &st, data.cvt_arr[flag],
				     &data.ftw);
	    }
	}

      if ((flags & FTW_ACTIONRETVAL)
	  && (result == FTW_SKIP_SUBTREE || result == FTW_SKIP_SIBLINGS))
	result = 0;
    }

  /* Return to the start directory (if necessary).  */
  if (cwdfd != -1)
    {
      int save_err = errno;
      __fchdir (cwdfd);
      __close_nocancel_nostatus (cwdfd);
      __set_errno (save_err);
    }
  else if (cwd != NULL)
    {
      int save_err = errno;
      __chdir (cwd);
      free (cwd);
      __set_errno (save_err);
    }

  /* Free all memory.  */
 out_fail:
  save_err = errno;
  __tdestroy (data.known_objects, free);
  free (data.dirbuf);
  __set_errno (save_err);

  return result;
}
Beispiel #15
0
static hp_timing_t
__get_clockfreq_via_proc_openprom (void)
{
  hp_timing_t result;
  int obp_fd;

  result = 0;

  obp_fd = __open ("/proc/openprom", O_RDONLY);
  if (obp_fd != -1)
    {
      unsigned long int buf[4096 / sizeof (unsigned long int)];
      struct dirent *dirp = (struct dirent *) buf;
      ssize_t len;

      while ((len = __getdents (obp_fd, (char *) dirp, sizeof (buf))) > 0)
	{
	  struct dirent *this_dirp = dirp;

	  while (len > 0)
	    {
	      char node[strlen ("/proc/openprom/")
			+ _D_ALLOC_NAMLEN (this_dirp)
			+ strlen ("/clock-frequency")];
	      char *prop;
	      int fd;

	      /* Note that
		   strlen("/clock-frequency") > strlen("/device_type")
	      */
	      __stpcpy (prop = __stpcpy (__stpcpy (node, "/proc/openprom/"),
					 this_dirp->d_name),
			"/device_type");
	      fd = __open (node, O_RDONLY);
	      if (fd != -1)
		{
		  char type_string[128];
		  int ret;

		  ret = __read (fd, type_string, sizeof (type_string));
		  if (ret > 0 && strncmp (type_string, "'cpu'", 5) == 0)
		    {
		      int clkfreq_fd;

		      __stpcpy (prop, "/clock-frequency");
		      clkfreq_fd = __open (node, O_RDONLY);
		      if (clkfreq_fd != -1)
			{
			  if (__read (clkfreq_fd, type_string,
				      sizeof (type_string)) > 0)
			    result = (hp_timing_t)
			      strtoumax (type_string, NULL, 16);
			  __close (clkfreq_fd);
			}
		    }
		  __close (fd);
		}

	      if (result != 0)
		break;

	      len -= this_dirp->d_reclen;
	      this_dirp = (struct dirent *)
		((char *) this_dirp + this_dirp->d_reclen);
	    }
	  if (result != 0)
	    break;
	}
      __close (obp_fd);
    }

  return result;
}
Beispiel #16
0
/* Using Unix sockets this way is a security risk.  */
static int
gaih_local (const char *name, const struct gaih_service *service,
	    const struct addrinfo *req, struct addrinfo **pai)
{
    struct utsname utsname;

    if ((name != NULL) && (req->ai_flags & AI_NUMERICHOST))
	return GAIH_OKIFUNSPEC | -EAI_NONAME;

    if ((name != NULL) || (req->ai_flags & AI_CANONNAME))
	if (uname (&utsname) < 0)
	    return -EAI_SYSTEM;

    if (name != NULL)
    {
	if (strcmp(name, "localhost") &&
	    strcmp(name, "local") &&
	    strcmp(name, "unix") &&
	    strcmp(name, utsname.nodename))
	    return GAIH_OKIFUNSPEC | -EAI_NONAME;
    }

    if (req->ai_protocol || req->ai_socktype)
    {
	const struct gaih_typeproto *tp = gaih_inet_typeproto + 1;

	while (tp->name[0]
	       && ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0
		   || (req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
		   || (req->ai_protocol != 0
		       && !(tp->protoflag & GAI_PROTO_PROTOANY)
		       && req->ai_protocol != tp->protocol)))
	    ++tp;

	if (! tp->name[0])
	{
	    if (req->ai_socktype)
		return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
	    else
		return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
	}
    }

    *pai = malloc (sizeof (struct addrinfo) + sizeof (struct sockaddr_un)
		   + ((req->ai_flags & AI_CANONNAME)
		      ? (strlen(utsname.nodename) + 1): 0));
    if (*pai == NULL)
	return -EAI_MEMORY;

    (*pai)->ai_next = NULL;
    (*pai)->ai_flags = req->ai_flags;
    (*pai)->ai_family = AF_LOCAL;
    (*pai)->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM;
    (*pai)->ai_protocol = req->ai_protocol;
    (*pai)->ai_addrlen = sizeof (struct sockaddr_un);
    (*pai)->ai_addr = (void *) (*pai) + sizeof (struct addrinfo);

#if SALEN
    ((struct sockaddr_un *) (*pai)->ai_addr)->sun_len =
	sizeof (struct sockaddr_un);
#endif /* SALEN */

    ((struct sockaddr_un *)(*pai)->ai_addr)->sun_family = AF_LOCAL;
    memset(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, 0, UNIX_PATH_MAX);

    if (service)
    {
	struct sockaddr_un *sunp = (struct sockaddr_un *) (*pai)->ai_addr;

	if (strchr (service->name, '/') != NULL)
	{
	    if (strlen (service->name) >= sizeof (sunp->sun_path))
		return GAIH_OKIFUNSPEC | -EAI_SERVICE;

	    strcpy (sunp->sun_path, service->name);
	}
	else
	{
	    if (strlen (P_tmpdir "/") + 1 + strlen (service->name) >=
		sizeof (sunp->sun_path))
		return GAIH_OKIFUNSPEC | -EAI_SERVICE;

	    __stpcpy (__stpcpy (sunp->sun_path, P_tmpdir "/"), service->name);
	}
    }
    else
    {
	/* This is a dangerous use of the interface since there is a time
	   window between the test for the file and the actual creation
	   (done by the caller) in which a file with the same name could
	   be created.  */
	char *buf = ((struct sockaddr_un *) (*pai)->ai_addr)->sun_path;

	if (__builtin_expect (__path_search (buf, L_tmpnam, NULL, NULL, 0),
			      0) != 0
	    || __builtin_expect (__gen_tempname (buf, __GT_NOCREATE), 0) != 0)
	    return -EAI_SYSTEM;
    }

    if (req->ai_flags & AI_CANONNAME)
	(*pai)->ai_canonname = strcpy ((char *) *pai + sizeof (struct addrinfo)
				       + sizeof (struct sockaddr_un),
				       utsname.nodename);
    else
	(*pai)->ai_canonname = NULL;
    return 0;
}
Beispiel #17
0
void *
__nss_lookup_function (service_user *ni, const char *fct_name)
{
  void **found, *result;

  /* We now modify global data.  Protect it.  */
  __libc_lock_lock (lock);

  /* Search the tree of functions previously requested.  Data in the
     tree are `known_function' structures, whose first member is a
     `const char *', the lookup key.  The search returns a pointer to
     the tree node structure; the first member of the is a pointer to
     our structure (i.e. what will be a `known_function'); since the
     first member of that is the lookup key string, &FCT_NAME is close
     enough to a pointer to our structure to use as a lookup key that
     will be passed to `known_compare' (above).  */

  found = __tsearch (&fct_name, (void **) &ni->known, &known_compare);
  if (*found != &fct_name)
    /* The search found an existing structure in the tree.  */
    result = ((known_function *) *found)->fct_ptr;
  else
    {
      /* This name was not known before.  Now we have a node in the tree
	 (in the proper sorted position for FCT_NAME) that points to
	 &FCT_NAME instead of any real `known_function' structure.
	 Allocate a new structure and fill it in.  */

      known_function *known = malloc (sizeof *known);
      if (! known)
	{
	remove_from_tree:
	  /* Oops.  We can't instantiate this node properly.
	     Remove it from the tree.  */
	  __tdelete (&fct_name, (void **) &ni->known, &known_compare);
	  result = NULL;
	}
      else
	{
	  /* Point the tree node at this new structure.  */
	  *found = known;
	  known->fct_name = fct_name;

	  if (ni->library == NULL)
	    {
	      /* This service has not yet been used.  Fetch the service
		 library for it, creating a new one if need be.  If there
		 is no service table from the file, this static variable
		 holds the head of the service_library list made from the
		 default configuration.  */
	      static name_database default_table;
	      ni->library = nss_new_service (service_table ?: &default_table,
					     ni->name);
	      if (ni->library == NULL)
		{
		  /* This only happens when out of memory.  */
		  free (known);
		  goto remove_from_tree;
		}
	    }

#if !defined DO_STATIC_NSS || defined SHARED
	  if (ni->library->lib_handle == NULL)
	    {
	      /* Load the shared library.  */
	      size_t shlen = (7 + strlen (ni->library->name) + 3
			      + strlen (__nss_shlib_revision) + 1);
	      int saved_errno = errno;
	      char shlib_name[shlen];

	      /* Construct shared object name.  */
	      __stpcpy (__stpcpy (__stpcpy (__stpcpy (shlib_name,
						      "libnss_"),
					    ni->library->name),
				  ".so"),
			__nss_shlib_revision);

	      ni->library->lib_handle = __libc_dlopen (shlib_name);
	      if (ni->library->lib_handle == NULL)
		{
		  /* Failed to load the library.  */
		  ni->library->lib_handle = (void *) -1l;
		  __set_errno (saved_errno);
		}
	    }

	  if (ni->library->lib_handle == (void *) -1l)
	    /* Library not found => function not found.  */
	    result = NULL;
	  else
	    {
	      /* Get the desired function.  */
	      size_t namlen = (5 + strlen (ni->library->name) + 1
			       + strlen (fct_name) + 1);
	      char name[namlen];

	      /* Construct the function name.  */
	      __stpcpy (__stpcpy (__stpcpy (__stpcpy (name, "_nss_"),
					    ni->library->name),
				  "_"),
			fct_name);

	      /* Look up the symbol.  */
	      result = __libc_dlsym (ni->library->lib_handle, name);
	    }
#else
	  /* We can't get function address dynamically in static linking. */
	  {
# define DEFINE_ENT(h,nm)						      \
	    { #h"_get"#nm"ent_r", _nss_##h##_get##nm##ent_r },		      \
	    { #h"_end"#nm"ent", _nss_##h##_end##nm##ent },		      \
	    { #h"_set"#nm"ent", _nss_##h##_set##nm##ent },
# define DEFINE_GET(h,nm)						      \
	    { #h"_get"#nm"_r", _nss_##h##_get##nm##_r },
# define DEFINE_GETBY(h,nm,ky)						      \
	    { #h"_get"#nm"by"#ky"_r", _nss_##h##_get##nm##by##ky##_r },
	    static struct fct_tbl { const char *fname; void *fp; } *tp, tbl[] =
	      {
# include "function.def"
		{ NULL, NULL }
	      };
	    size_t namlen = (5 + strlen (ni->library->name) + 1
			     + strlen (fct_name) + 1);
	    char name[namlen];

	    /* Construct the function name.  */
	    __stpcpy (__stpcpy (__stpcpy (name, ni->library->name),
				"_"),
		      fct_name);

	    result = NULL;
	    for (tp = &tbl[0]; tp->fname; tp++)
	      if (strcmp (tp->fname, name) == 0)
		{
		  result = tp->fp;
		  break;
		}
	  }
#endif

	  /* Remember function pointer for later calls.  Even if null, we
	     record it so a second try needn't search the library again.  */
	  known->fct_ptr = result;
	}
    }

  /* Remove the lock.  */
  __libc_lock_unlock (lock);

  return result;
}
Beispiel #18
0
int
__ptsname_internal (int fd, char *buf, size_t buflen, struct stat64 *stp)
{
  int save_errno = errno;
  unsigned int ptyno;

  if (buf == NULL)
    {
      __set_errno (EINVAL);
      return EINVAL;
    }

  if (!__isatty (fd))
    {
      __set_errno (ENOTTY);
      return ENOTTY;
    }

#ifdef TIOCGPTN
  if (__ioctl (fd, TIOCGPTN, &ptyno) == 0)
    {
      /* Buffer we use to print the number in.  For a maximum size for
	 `int' of 8 bytes we never need more than 20 digits.  */
      char numbuf[21];
      const char *devpts = _PATH_DEVPTS;
      const size_t devptslen = strlen (_PATH_DEVPTS);
      char *p;

      numbuf[sizeof (numbuf) - 1] = '\0';
      p = _itoa_word (ptyno, &numbuf[sizeof (numbuf) - 1], 10, 0);

      if (buflen < devptslen + (&numbuf[sizeof (numbuf)] - p))
	{
	  __set_errno (ERANGE);
	  return ERANGE;
	}

      memcpy (__stpcpy (buf, devpts), p, &numbuf[sizeof (numbuf)] - p);
    }
  else if (errno != EINVAL)
    return errno;
  else
#endif
    {
      char *p;

      if (buflen < strlen (_PATH_TTY) + 3)
	{
	  __set_errno (ERANGE);
	  return ERANGE;
	}

      if (__fxstat64 (_STAT_VER, fd, stp) < 0)
	return errno;

      /* Check if FD really is a master pseudo terminal.  */
      if (! MASTER_P (stp->st_rdev))
	{
	  __set_errno (ENOTTY);
	  return ENOTTY;
	}

      ptyno = minor (stp->st_rdev);

      if (ptyno / 16 >= strlen (__libc_ptyname1))
	{
	  __set_errno (ENOTTY);
	  return ENOTTY;
	}

      p = __stpcpy (buf, _PATH_TTY);
      p[0] = __libc_ptyname1[ptyno / 16];
      p[1] = __libc_ptyname2[ptyno % 16];
      p[2] = '\0';
    }

  if (__xstat64 (_STAT_VER, buf, stp) < 0)
    return errno;

  /* Check if the name we're about to return really corresponds to a
     slave pseudo terminal.  */
  if (! S_ISCHR (stp->st_mode) || ! SLAVE_P (stp->st_rdev))
    {
      /* This really is a configuration problem.  */
      __set_errno (ENOTTY);
      return ENOTTY;
    }

  __set_errno (save_errno);
  return 0;
}
Beispiel #19
0
/* If we run out of memory, we don't give already allocated memory
   free. The overhead for bringing getnames back in a safe state to
   free it is to big. */
nis_name *
nis_getnames (const_nis_name name)
{
  const char *local_domain = nis_local_directory ();
  size_t local_domain_len = strlen (local_domain);
  size_t name_len = strlen (name);
  char *path;
  int pos = 0;
  char *saveptr = NULL;
  int have_point;
  const char *cp;
  const char *cp2;

  int count = 2;
  nis_name *getnames = malloc ((count + 1) * sizeof (char *));
  if (__glibc_unlikely (getnames == NULL))
      return NULL;

  /* Do we have a fully qualified NIS+ name ? If yes, give it back */
  if (name[name_len - 1] == '.')
    {
      if ((getnames[0] = strdup (name)) == NULL)
	{
	free_null:
	  while (pos-- > 0)
	    free (getnames[pos]);
	  free (getnames);
	  return NULL;
	}

      getnames[1] = NULL;

      return getnames;
    }

  /* If the passed NAME is shared a suffix (the latter of course with
     a final dot) with each other we pass back NAME with a final
     dot.  */
  if (local_domain_len > 2)
    {
      have_point = 0;
      cp = &local_domain[local_domain_len - 2];
      cp2 = &name[name_len - 1];

      while (*cp == *cp2)
	{
	  if (*cp == '.')
	    have_point = 1;
	  --cp;
	  --cp2;
	  if (cp < local_domain)
	    {
	      have_point = cp2 < name || *cp2 == '.';
	      break;
	    }
	  if (cp2 < name)
	    {
	      have_point = *cp == '.';
	      break;
	    }
	}

      if (have_point)
	{
	  getnames[0] = malloc (name_len + 2);
	  if (getnames[0] == NULL)
	    goto free_null;

	  strcpy (stpcpy (getnames[0], name), ".");
	  ++pos;
	}
    }

  /* Get the search path, where we have to search "name" */
  path = getenv ("NIS_PATH");
  if (path == NULL)
    path = strdupa ("$");
  else
    path = strdupa (path);

  have_point = strchr (name, '.') != NULL;

  cp = __strtok_r (path, ":", &saveptr);
  while (cp)
    {
      if (strcmp (cp, "$") == 0)
	{
	  const char *cptr = local_domain;
	  char *tmp;

	  while (*cptr != '\0' && count_dots (cptr) >= 2)
	    {
	      if (pos >= count)
		{
		  count += 5;
		  nis_name *newp = realloc (getnames,
					    (count + 1) * sizeof (char *));
		  if (__glibc_unlikely (newp == NULL))
		    goto free_null;
		  getnames = newp;
		}
	      tmp = malloc (strlen (cptr) + local_domain_len + name_len + 2);
	      if (__glibc_unlikely (tmp == NULL))
		goto free_null;

	      getnames[pos] = tmp;
	      tmp = stpcpy (tmp, name);
	      *tmp++ = '.';
	      if (cptr[1] != '\0')
		stpcpy (tmp, cptr);
	      else
		++cptr;

	      ++pos;

	      while (*cptr != '.' && *cptr != '\0')
		++cptr;
	      if (cptr[0] != '\0' && cptr[1] != '\0')
		/* If we have only ".", don't remove the "." */
		++cptr;
	    }
	}
      else
	{
	  char *tmp;
	  size_t cplen = strlen (cp);

	  if (cp[cplen - 1] == '$')
	    {
	      char *p;

	      tmp = malloc (cplen + local_domain_len + name_len + 2);
	      if (__glibc_unlikely (tmp == NULL))
		goto free_null;

	      p = __stpcpy (tmp, name);
	      *p++ = '.';
	      p = __mempcpy (p, cp, cplen);
	      --p;
	      if (p[-1] != '.')
		*p++ = '.';
	      __stpcpy (p, local_domain);
	    }
	  else
	    {
	      char *p;

	      tmp = malloc (cplen + name_len + 3);
	      if (__glibc_unlikely (tmp == NULL))
		goto free_null;

	      p = __mempcpy (tmp, name, name_len);
	      *p++ = '.';
	      p = __mempcpy (p, cp, cplen);
	      if (p[-1] != '.')
		*p++ = '.';
	      *p = '\0';
	    }

	  if (pos >= count)
	    {
	      count += 5;
	      nis_name *newp = realloc (getnames,
					(count + 1) * sizeof (char *));
	      if (__glibc_unlikely (newp == NULL))
		goto free_null;
	      getnames = newp;
	    }
	  getnames[pos] = tmp;
	  ++pos;
	}
      cp = __strtok_r (NULL, ":", &saveptr);
    }

  if (pos == 0
      && __asprintf (&getnames[pos++], "%s%s%s%s",
		     name, name[name_len - 1] == '.' ? "" : ".",
		     local_domain,
		     local_domain[local_domain_len - 1] == '.' ? "" : ".") < 0)
    goto free_null;

  getnames[pos] = NULL;

  return getnames;
}
Beispiel #20
0
/* Return the pathname of the terminal FD is open on, or NULL on errors.
   The returned storage is good only until the next call to this function.  */
char *
ttyname (int fd)
{
  static size_t buflen;
  char procname[30];
  struct stat64 st, st1;
  int dostat = 0;
  char *name;
  int save = errno;
  struct termios term;

  /* isatty check, tcgetattr is used because it sets the correct
     errno (EBADF resp. ENOTTY) on error.  */
  if (__glibc_unlikely (__tcgetattr (fd, &term) < 0))
    return NULL;

  if (__fxstat64 (_STAT_VER, fd, &st) < 0)
    return NULL;

  /* We try using the /proc filesystem.  */
  *_fitoa_word (fd, __stpcpy (procname, "/proc/self/fd/"), 10, 0) = '\0';

  if (buflen == 0)
    {
      buflen = 4095;
      ttyname_buf = (char *) malloc (buflen + 1);
      if (ttyname_buf == NULL)
	{
	  buflen = 0;
	  return NULL;
	}
    }

  ssize_t len = __readlink (procname, ttyname_buf, buflen);
  if (__glibc_likely (len != -1))
    {
      if ((size_t) len >= buflen)
	return NULL;

#define UNREACHABLE_LEN strlen ("(unreachable)")
      if (len > UNREACHABLE_LEN
	  && memcmp (ttyname_buf, "(unreachable)", UNREACHABLE_LEN) == 0)
	{
	  memmove (ttyname_buf, ttyname_buf + UNREACHABLE_LEN,
		   len - UNREACHABLE_LEN);
	  len -= UNREACHABLE_LEN;
	}

      /* readlink need not terminate the string.  */
      ttyname_buf[len] = '\0';

      /* Verify readlink result, fall back on iterating through devices.  */
      if (ttyname_buf[0] == '/'
	  && __xstat64 (_STAT_VER, ttyname_buf, &st1) == 0
#ifdef _STATBUF_ST_RDEV
	  && S_ISCHR (st1.st_mode)
	  && st1.st_rdev == st.st_rdev
#else
	  && st1.st_ino == st.st_ino
	  && st1.st_dev == st.st_dev
#endif
	  )
	return ttyname_buf;
    }

  if (__xstat64 (_STAT_VER, "/dev/pts", &st1) == 0 && S_ISDIR (st1.st_mode))
    {
#ifdef _STATBUF_ST_RDEV
      name = getttyname ("/dev/pts", st.st_rdev, st.st_ino, save, &dostat);
#else
      name = getttyname ("/dev/pts", st.st_dev, st.st_ino, save, &dostat);
#endif
    }
  else
    {
      __set_errno (save);
      name = NULL;
    }

  if (!name && dostat != -1)
    {
#ifdef _STATBUF_ST_RDEV
      name = getttyname ("/dev", st.st_rdev, st.st_ino, save, &dostat);
#else
      name = getttyname ("/dev", st.st_dev, st.st_ino, save, &dostat);
#endif
    }

  if (!name && dostat != -1)
    {
      dostat = 1;
#ifdef _STATBUF_ST_RDEV
      name = getttyname ("/dev", st.st_rdev, st.st_ino, save, &dostat);
#else
      name = getttyname ("/dev", st.st_dev, st.st_ino, save, &dostat);
#endif
    }

  return name;
}
Beispiel #21
0
int
ruserpass (const char *host, const char **aname, const char **apass)
{
	char *hdir, *buf, *tmp;
	char myname[1024], *mydomain;
	int t, usedefault = 0;
	struct stat64 stb;

	hdir = __libc_secure_getenv("HOME");
	if (hdir == NULL) {
		/* If we can't get HOME, fail instead of trying ".",
		   which is no improvement. This really should call
		   getpwuid(getuid()).  */
		/*hdir = ".";*/
		return -1;
	}

	buf = alloca (strlen (hdir) + 8);

	__stpcpy (__stpcpy (buf, hdir), "/.netrc");
	cfile = fopen(buf, "rce");
	if (cfile == NULL) {
		if (errno != ENOENT)
			warn("%s", buf);
		return (0);
	}
	/* No threads use this stream.  */
	__fsetlocking (cfile, FSETLOCKING_BYCALLER);
	if (__gethostname(myname, sizeof(myname)) < 0)
		myname[0] = '\0';
	mydomain = __strchrnul(myname, '.');
next:
	while ((t = token())) switch(t) {

	case DEFAULT:
		usedefault = 1;
		/* FALL THROUGH */

	case MACHINE:
		if (!usedefault) {
			if (token() != ID)
				continue;
			/*
			 * Allow match either for user's input host name
			 * or official hostname.  Also allow match of
			 * incompletely-specified host in local domain.
			 */
			if (__strcasecmp(host, tokval) == 0)
				goto match;
/*			if (__strcasecmp(hostname, tokval) == 0)
				goto match;
			if ((tmp = strchr(hostname, '.')) != NULL &&
			    __strcasecmp(tmp, mydomain) == 0 &&
			    __strncasecmp(hostname, tokval, tmp-hostname) == 0 &&
			    tokval[tmp - hostname] == '\0')
				goto match; */
			if ((tmp = strchr(host, '.')) != NULL &&
			    __strcasecmp(tmp, mydomain) == 0 &&
			    __strncasecmp(host, tokval, tmp - host) == 0 &&
			    tokval[tmp - host] == '\0')
				goto match;
			continue;
		}
	match:
		while ((t = token()) && t != MACHINE && t != DEFAULT) switch(t) {

		case LOGIN:
			if (token()) {
				if (*aname == 0) {
				  char *newp;
				  newp = malloc((unsigned) strlen(tokval) + 1);
				  if (newp == NULL)
				    {
				      warnx(_("out of memory"));
				      goto bad;
				    }
				  *aname = strcpy(newp, tokval);
				} else {
					if (strcmp(*aname, tokval))
						goto next;
				}
			}
			break;
		case PASSWD:
			if (strcmp(*aname, "anonymous") &&
			    fstat64(fileno(cfile), &stb) >= 0 &&
			    (stb.st_mode & 077) != 0) {
	warnx(_("Error: .netrc file is readable by others."));
	warnx(_("Remove password or make file unreadable by others."));
				goto bad;
			}
			if (token() && *apass == 0) {
				char *newp;
				newp = malloc((unsigned) strlen(tokval) + 1);
				if (newp == NULL)
				  {
				    warnx(_("out of memory"));
				    goto bad;
				  }
				*apass = strcpy(newp, tokval);
			}
			break;
		case ACCOUNT:
			break;
		case MACDEF:
			break;
		default:
			warnx(_("Unknown .netrc keyword %s"), tokval);
			break;
		}
		goto done;
	}
done:
	(void) fclose(cfile);
	return (0);
bad:
	(void) fclose(cfile);
	return (-1);
}
Beispiel #22
0
char *
__old_stpcpy_g (char *dest, const char *src)
{
  return __stpcpy (dest, src);
}
Beispiel #23
0
void
__vsyslog_chk(int pri, int flag, const char *fmt, va_list ap)
{
    struct tm now_tm;
    time_t now;
    int fd;
    FILE *f;
    char *buf = 0;
    size_t bufsize = 0;
    size_t msgoff;
#ifndef NO_SIGPIPE
    struct sigaction action, oldaction;
    int sigpipe;
#endif
    int saved_errno = errno;
    char failbuf[3 * sizeof (pid_t) + sizeof "out of memory []"];

#define	INTERNALLOG	LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
    /* Check for invalid bits. */
    if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
        syslog(INTERNALLOG,
               "syslog: unknown facility/priority: %x", pri);
        pri &= LOG_PRIMASK|LOG_FACMASK;
    }

    /* Check priority against setlogmask values. */
    if ((LOG_MASK (LOG_PRI (pri)) & LogMask) == 0)
        return;

    /* Set default facility if none specified. */
    if ((pri & LOG_FACMASK) == 0)
        pri |= LogFacility;

    /* Build the message in a memory-buffer stream.  */
    f = __open_memstream (&buf, &bufsize);
    if (f == NULL)
    {
        /* We cannot get a stream.  There is not much we can do but
           emitting an error messages.  */
        char numbuf[3 * sizeof (pid_t)];
        char *nump;
        char *endp = __stpcpy (failbuf, "out of memory [");
        pid_t pid = __getpid ();

        nump = numbuf + sizeof (numbuf);
        /* The PID can never be zero.  */
        do
            *--nump = '0' + pid % 10;
        while ((pid /= 10) != 0);

        endp = __mempcpy (endp, nump, (numbuf + sizeof (numbuf)) - nump);
        *endp++ = ']';
        *endp = '\0';
        buf = failbuf;
        bufsize = endp - failbuf;
        msgoff = 0;
    }
    else
    {
        __fsetlocking (f, FSETLOCKING_BYCALLER);
        fprintf (f, "<%d>", pri);
        (void) time (&now);
        f->_IO_write_ptr += __strftime_l (f->_IO_write_ptr,
                                          f->_IO_write_end
                                          - f->_IO_write_ptr,
                                          "%h %e %T ",
                                          __localtime_r (&now, &now_tm),
                                          _nl_C_locobj_ptr);
        msgoff = ftell (f);
        if (LogTag == NULL)
            LogTag = __progname;
        if (LogTag != NULL)
            __fputs_unlocked (LogTag, f);
        if (LogStat & LOG_PID)
            fprintf (f, "[%d]", (int) __getpid ());
        if (LogTag != NULL)
        {
            putc_unlocked (':', f);
            putc_unlocked (' ', f);
        }

        /* Restore errno for %m format.  */
        __set_errno (saved_errno);

        /* We have the header.  Print the user's format into the
               buffer.  */
        if (flag == -1)
            vfprintf (f, fmt, ap);
        else
            __vfprintf_chk (f, flag, fmt, ap);

        /* Close the memory stream; this will finalize the data
           into a malloc'd buffer in BUF.  */
        fclose (f);
    }

    /* Output to stderr if requested. */
    if (LogStat & LOG_PERROR) {
        struct iovec iov[2];
        struct iovec *v = iov;

        v->iov_base = buf + msgoff;
        v->iov_len = bufsize - msgoff;
        /* Append a newline if necessary.  */
        if (buf[bufsize - 1] != '\n')
        {
            ++v;
            v->iov_base = (char *) "\n";
            v->iov_len = 1;
        }

        __libc_cleanup_push (free, buf == failbuf ? NULL : buf);

        /* writev is a cancellation point.  */
        (void)__writev(STDERR_FILENO, iov, v - iov + 1);

        __libc_cleanup_pop (0);
    }

    /* Prepare for multiple users.  We have to take care: open and
       write are cancellation points.  */
    struct cleanup_arg clarg;
    clarg.buf = buf;
    clarg.oldaction = NULL;
    __libc_cleanup_push (cancel_handler, &clarg);
    __libc_lock_lock (syslog_lock);

#ifndef NO_SIGPIPE
    /* Prepare for a broken connection.  */
    memset (&action, 0, sizeof (action));
    action.sa_handler = sigpipe_handler;
    sigemptyset (&action.sa_mask);
    sigpipe = __sigaction (SIGPIPE, &action, &oldaction);
    if (sigpipe == 0)
        clarg.oldaction = &oldaction;
#endif

    /* Get connected, output the message to the local logger. */
    if (!connected)
        openlog_internal(LogTag, LogStat | LOG_NDELAY, 0);

    /* If we have a SOCK_STREAM connection, also send ASCII NUL as
       a record terminator.  */
    if (LogType == SOCK_STREAM)
        ++bufsize;

    if (!connected || __send(LogFile, buf, bufsize, send_flags) < 0)
    {
        if (connected)
        {
            /* Try to reopen the syslog connection.  Maybe it went
               down.  */
            closelog_internal ();
            openlog_internal(LogTag, LogStat | LOG_NDELAY, 0);
        }

        if (!connected || __send(LogFile, buf, bufsize, send_flags) < 0)
        {
            closelog_internal ();	/* attempt re-open next time */
            /*
             * Output the message to the console; don't worry
             * about blocking, if console blocks everything will.
             * Make sure the error reported is the one from the
             * syslogd failure.
             */
            if (LogStat & LOG_CONS &&
                    (fd = __open(_PATH_CONSOLE, O_WRONLY|O_NOCTTY, 0)) >= 0)
            {
                __dprintf (fd, "%s\r\n", buf + msgoff);
                (void)__close(fd);
            }
        }
    }

#ifndef NO_SIGPIPE
    if (sigpipe == 0)
        __sigaction (SIGPIPE, &oldaction, (struct sigaction *) NULL);
#endif

    /* End of critical section.  */
    __libc_cleanup_pop (0);
    __libc_lock_unlock (syslog_lock);

    if (buf != failbuf)
        free (buf);
}
Beispiel #24
0
/* If we run out of memory, we don't give already allocated memory
   free. The overhead for bringing getnames back in a safe state to
   free it is to big. */
nis_name *
nis_getnames (const_nis_name name)
{
  nis_name *getnames = NULL;
  char local_domain[NIS_MAXNAMELEN + 1];
  char *path;
  char *cp;
  int count;
  int pos = 0;
  int have_point;
  char *saveptr;

  strncpy (local_domain, nis_local_directory (), NIS_MAXNAMELEN);
  local_domain[NIS_MAXNAMELEN] = '\0';

  count = 1;
  getnames = malloc ((count + 1) * sizeof (char *));
  if (__builtin_expect (getnames == NULL, 0))
      return NULL;

  /* Do we have a fully qualified NIS+ name ? If yes, give it back */
  if (name[strlen (name) - 1] == '.')
    {
      if ((getnames[0] = strdup (name)) == NULL)
	{
	free_null:
	  while (pos-- > 0)
	    free (getnames[pos]);
	  free (getnames);
	  return NULL;
	}

      getnames[1] = NULL;

      return getnames;
    }

  /* Get the search path, where we have to search "name" */
  path = getenv ("NIS_PATH");
  if (path == NULL)
    path = strdupa ("$");
  else
    path = strdupa (path);

  have_point = (strchr (name, '.') != NULL);

  cp = __strtok_r (path, ":", &saveptr);
  while (cp)
    {
      if (strcmp (cp, "$") == 0)
	{
	  char *cptr = local_domain;
	  char *tmp;

	  while ((have_point && *cptr != '\0') || (count_dots (cptr) >= 2))
	    {
	      if (pos >= count)
		{
		  count += 5;
		  nis_name *newp = realloc (getnames,
					    (count + 1) * sizeof (char *));
		  if (__builtin_expect (newp == NULL, 0))
		    goto free_null;
		  getnames = newp;
		}
	      tmp = malloc (strlen (cptr) + strlen (local_domain) +
			    strlen (name) + 2);
	      if (__builtin_expect (tmp == NULL, 0))
		goto free_null;

	      getnames[pos] = tmp;
	      tmp = stpcpy (tmp, name);
	      *tmp++ = '.';
	      if (cptr[1] != '\0')
		stpcpy (tmp, cptr);
	      else
		++cptr;

	      ++pos;

	      while (*cptr != '.' && *cptr != '\0')
		++cptr;
	      if (cptr[0] != '\0' && cptr[1] != '\0')
		/* If we have only ".", don't remove the "." */
		++cptr;
	    }
	}
      else
	{
	  char *tmp;
	  size_t cplen = strlen (cp);

	  if (cp[cplen - 1] == '$')
	    {
	      char *p;

	      tmp = malloc (cplen + strlen (local_domain) + strlen (name) + 2);
	      if (__builtin_expect (tmp == NULL, 0))
		goto free_null;

	      p = __stpcpy (tmp, name);
	      *p++ = '.';
	      p = __mempcpy (p, cp, cplen);
	      --p;
	      if (p[-1] != '.')
		*p++ = '.';
	      __stpcpy (p, local_domain);
	    }
	  else
	    {
	      char *p;

	      tmp = malloc (cplen + strlen (name) + 2);
	      if (__builtin_expect (tmp == NULL, 0))
		goto free_null;

	      p = __stpcpy (tmp, name);
	      *p++ = '.';
	      memcpy (p, cp, cplen + 1);
	    }

	  if (pos >= count)
	    {
	      count += 5;
	      nis_name *newp = realloc (getnames,
					(count + 1) * sizeof (char *));
	      if (__builtin_expect (newp == NULL, 0))
		goto free_null;
	      getnames = newp;
	    }
	  getnames[pos] = tmp;
	  ++pos;
	}
      cp = __strtok_r (NULL, ":", &saveptr);
    }

  getnames[pos] = NULL;

  return getnames;
}
Beispiel #25
0
/* Store at most BUFLEN character of the pathname of the terminal FD is
   open on in BUF.  Return 0 on success,  otherwise an error number.  */
int
__ttyname_r (int fd, char *buf, size_t buflen)
{
  char procname[30];
  struct stat64 st, st1;
  int dostat = 0;
  int save = errno;
  int ret;

  /* Test for the absolute minimal size.  This makes life easier inside
     the loop.  */
  if (!buf)
    {
      __set_errno (EINVAL);
      return EINVAL;
    }

  if (buflen < sizeof ("/dev/pts/"))
    {
      __set_errno (ERANGE);
      return ERANGE;
    }

  /* We try using the /proc filesystem.  */
  *_fitoa_word (fd, __stpcpy (procname, "/proc/self/fd/"), 10, 0) = '\0';

  ret = __readlink (procname, buf, buflen - 1);
  if (ret == -1 && errno == ENOENT)
    {
      __set_errno (EBADF);
      return EBADF;
    }

  if (!__isatty (fd))
    {
      __set_errno (ENOTTY);
      return ENOTTY;
    }

  if (ret == -1 && errno == ENAMETOOLONG)
    {
      __set_errno (ERANGE);
      return ERANGE;
    }

  if (ret != -1 && buf[0] != '[')
    {
      buf[ret] = '\0';
      return 0;
    }

  if (__fxstat64 (_STAT_VER, fd, &st) < 0)
    return errno;

  /* Prepare the result buffer.  */
  memcpy (buf, "/dev/pts/", sizeof ("/dev/pts/"));
  buflen -= sizeof ("/dev/pts/") - 1;

  if (__xstat64 (_STAT_VER, buf, &st1) == 0 && S_ISDIR (st1.st_mode))
    {
#ifdef _STATBUF_ST_RDEV
      ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save,
			  &dostat);
#else
      ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save,
			  &dostat);
#endif
    }
  else
    {
      __set_errno (save);
      ret = ENOENT;
    }

  if (ret && dostat != -1)
    {
      buf[sizeof ("/dev/") - 1] = '\0';
      buflen += sizeof ("pts/") - 1;
#ifdef _STATBUF_ST_RDEV
      ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save,
			  &dostat);
#else
      ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save,
			  &dostat);
#endif
    }

  if (ret && dostat != -1)
    {
      buf[sizeof ("/dev/") - 1] = '\0';
      dostat = 1;
#ifdef _STATBUF_ST_RDEV
      ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino,
			  save, &dostat);
#else
      ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino,
			  save, &dostat);
#endif
    }

  return ret;
}
Beispiel #26
0
__locale_t
__newlocale (int category_mask, const char *locale, __locale_t base)
{
  /* Intermediate memory for result.  */
  const char *newnames[__LC_LAST];
  struct __locale_struct result;
  __locale_t result_ptr;
  char *locale_path;
  size_t locale_path_len;
  const char *locpath_var;
  int cnt;
  size_t names_len;

  /* We treat LC_ALL in the same way as if all bits were set.  */
  if (category_mask == 1 << LC_ALL)
    category_mask = (1 << __LC_LAST) - 1 - (1 << LC_ALL);

  /* Sanity check for CATEGORY argument.  */
  if ((category_mask & ~((1 << __LC_LAST) - 1 - (1 << LC_ALL))) != 0)
    ERROR_RETURN;

  /* `newlocale' does not support asking for the locale name. */
  if (locale == NULL)
    ERROR_RETURN;

  if (base == _nl_C_locobj_ptr)
    /* We're to modify BASE, returned for a previous call with "C".
       We can't really modify the read-only structure, so instead
       start over by copying it.  */
    base = NULL;

  if ((base == NULL || category_mask == (1 << __LC_LAST) - 1 - (1 << LC_ALL))
      && (category_mask == 0 || !strcmp (locale, "C")))
    /* Asking for the "C" locale needn't allocate a new object.  */
    return _nl_C_locobj_ptr;

  /* Allocate memory for the result.  */
  if (base != NULL)
    result = *base;
  else
    /* Fill with pointers to C locale data.  */
    result = _nl_C_locobj;

  /* If no category is to be set we return BASE if available or a
     dataset using the C locale data.  */
  if (category_mask == 0)
    {
      result_ptr = (__locale_t) malloc (sizeof (struct __locale_struct));
      if (result_ptr == NULL)
	return NULL;
      *result_ptr = result;

      goto update;
    }

  /* We perhaps really have to load some data.  So we determine the
     path in which to look for the data now.  The environment variable
     `LOCPATH' must only be used when the binary has no SUID or SGID
     bit set.  If using the default path, we tell _nl_find_locale
     by passing null and it can check the canonical locale archive.  */
  locale_path = NULL;
  locale_path_len = 0;

  locpath_var = getenv ("LOCPATH");
  if (locpath_var != NULL && locpath_var[0] != '\0')
    {
      if (__argz_create_sep (locpath_var, ':',
			     &locale_path, &locale_path_len) != 0)
	return NULL;

      if (__argz_add_sep (&locale_path, &locale_path_len,
			  _nl_default_locale_path, ':') != 0)
	return NULL;
    }

  /* Get the names for the locales we are interested in.  We either
     allow a composite name or a single name.  */
  for (cnt = 0; cnt < __LC_LAST; ++cnt)
    if (cnt != LC_ALL)
      newnames[cnt] = locale;
  if (strchr (locale, ';') != NULL)
    {
      /* This is a composite name.  Make a copy and split it up.  */
      char *np = strdupa (locale);
      char *cp;
      int specified_mask = 0;

      while ((cp = strchr (np, '=')) != NULL)
	{
	  for (cnt = 0; cnt < __LC_LAST; ++cnt)
	    if (cnt != LC_ALL
		&& (size_t) (cp - np) == _nl_category_name_sizes[cnt]
		&& memcmp (np, (_nl_category_names.str
				+ _nl_category_name_idxs[cnt]), cp - np) == 0)
	      break;

	  if (cnt == __LC_LAST)
	    /* Bogus category name.  */
	    ERROR_RETURN;

	  /* Found the category this clause sets.  */
	  specified_mask |= 1 << cnt;
	  newnames[cnt] = ++cp;
	  cp = strchr (cp, ';');
	  if (cp != NULL)
	    {
	      /* Examine the next clause.  */
	      *cp = '\0';
	      np = cp + 1;
	    }
	  else
	    /* This was the last clause.  We are done.  */
	    break;
	}

      if (category_mask &~ specified_mask)
	/* The composite name did not specify all categories we need.  */
	ERROR_RETURN;
    }

  /* Protect global data.  */
  __libc_rwlock_wrlock (__libc_setlocale_lock);

  /* Now process all categories we are interested in.  */
  names_len = 0;
  for (cnt = 0; cnt < __LC_LAST; ++cnt)
    {
      if ((category_mask & 1 << cnt) != 0)
	{
	  result.__locales[cnt] = _nl_find_locale (locale_path,
						   locale_path_len,
						   cnt, &newnames[cnt]);
	  if (result.__locales[cnt] == NULL)
	    {
	    free_cnt_data_and_exit:
	      while (cnt-- > 0)
		if (((category_mask & 1 << cnt) != 0)
		    && result.__locales[cnt]->usage_count != UNDELETABLE)
		  /* We can remove the data.  */
		  _nl_remove_locale (cnt, result.__locales[cnt]);

              /* Critical section left.  */
              __libc_rwlock_unlock (__libc_setlocale_lock);
	      return NULL;
	    }

	  if (newnames[cnt] != _nl_C_name)
	    names_len += strlen (newnames[cnt]) + 1;
	}
      else if (cnt != LC_ALL && result.__names[cnt] != _nl_C_name)
	/* Tally up the unchanged names from BASE as well.  */
	names_len += strlen (result.__names[cnt]) + 1;
    }

  /* We successfully loaded all required data.  Allocate a new structure.
     We can't just reuse the BASE pointer, because the name strings are
     changing and we need the old name string area intact so we can copy
     out of it into the new one without overlap problems should some
     category's name be getting longer.  */
  result_ptr = malloc (sizeof (struct __locale_struct) + names_len);
  if (result_ptr == NULL)
    {
      cnt = __LC_LAST;
      goto free_cnt_data_and_exit;
    }

  if (base == NULL)
    {
      /* Fill in this new structure from scratch.  */

      char *namep = (char *) (result_ptr + 1);

      /* Install copied new names in the new structure's __names array.
	 If resolved to "C", that is already in RESULT.__names to start.  */
      for (cnt = 0; cnt < __LC_LAST; ++cnt)
	if ((category_mask & 1 << cnt) != 0 && newnames[cnt] != _nl_C_name)
	  {
	    result.__names[cnt] = namep;
	    namep = __stpcpy (namep, newnames[cnt]) + 1;
	  }

      *result_ptr = result;
    }
  else
    {
      /* We modify the base structure.  */

      char *namep = (char *) (result_ptr + 1);

      for (cnt = 0; cnt < __LC_LAST; ++cnt)
	if ((category_mask & 1 << cnt) != 0)
	  {
	    if (base->__locales[cnt]->usage_count != UNDELETABLE)
	      /* We can remove the old data.  */
	      _nl_remove_locale (cnt, base->__locales[cnt]);
	    result_ptr->__locales[cnt] = result.__locales[cnt];

	    if (newnames[cnt] == _nl_C_name)
	      result_ptr->__names[cnt] = _nl_C_name;
	    else
	      {
		result_ptr->__names[cnt] = namep;
		namep = __stpcpy (namep, newnames[cnt]) + 1;
	      }
	  }
	else if (cnt != LC_ALL)
	  {
	    /* The RESULT members point into the old BASE structure.  */
	    result_ptr->__locales[cnt] = result.__locales[cnt];
	    if (result.__names[cnt] == _nl_C_name)
	      result_ptr->__names[cnt] = _nl_C_name;
	    else
	      {
		result_ptr->__names[cnt] = namep;
		namep = __stpcpy (namep, result.__names[cnt]) + 1;
	      }
	  }

      free (base);
    }

  /* Critical section left.  */
  __libc_rwlock_unlock (__libc_setlocale_lock);

  /* Update the special members.  */
 update:
  {
    union locale_data_value *ctypes = result_ptr->__locales[LC_CTYPE]->values;
    result_ptr->__ctype_b = (const unsigned short int *)
      ctypes[_NL_ITEM_INDEX (_NL_CTYPE_CLASS)].string + 128;
    result_ptr->__ctype_tolower = (const int *)
      ctypes[_NL_ITEM_INDEX (_NL_CTYPE_TOLOWER)].string + 128;
    result_ptr->__ctype_toupper = (const int *)
      ctypes[_NL_ITEM_INDEX (_NL_CTYPE_TOUPPER)].string + 128;
  }

  return result_ptr;
}
Beispiel #27
0
/* Store at most BUFLEN character of the pathname of the terminal FD is
   open on in BUF.  Return 0 on success,  otherwise an error number.  */
int
__ttyname_r (int fd, char *buf, size_t buflen)
{
  char procname[30];
  struct stat64 st, st1;
  int dostat = 0;
  int save = errno;

  /* Test for the absolute minimal size.  This makes life easier inside
     the loop.  */
  if (!buf)
    {
      __set_errno (EINVAL);
      return EINVAL;
    }

  if (buflen < sizeof ("/dev/pts/"))
    {
      __set_errno (ERANGE);
      return ERANGE;
    }

  /* isatty check, tcgetattr is used because it sets the correct
     errno (EBADF resp. ENOTTY) on error.  */
  struct termios term;
  if (__glibc_unlikely (__tcgetattr (fd, &term) < 0))
    return errno;

  if (__fxstat64 (_STAT_VER, fd, &st) < 0)
    return errno;

  /* We try using the /proc filesystem.  */
  *_fitoa_word (fd, __stpcpy (procname, "/proc/self/fd/"), 10, 0) = '\0';

  ssize_t ret = __readlink (procname, buf, buflen - 1);
  if (__glibc_unlikely (ret == -1 && errno == ENAMETOOLONG))
    {
      __set_errno (ERANGE);
      return ERANGE;
    }

  if (__glibc_likely (ret != -1))
    {
#define UNREACHABLE_LEN strlen ("(unreachable)")
      if (ret > UNREACHABLE_LEN
	  && memcmp (buf, "(unreachable)", UNREACHABLE_LEN) == 0)
	{
	  memmove (buf, buf + UNREACHABLE_LEN, ret - UNREACHABLE_LEN);
	  ret -= UNREACHABLE_LEN;
	}

      /* readlink need not terminate the string.  */
      buf[ret] = '\0';

      /* Verify readlink result, fall back on iterating through devices.  */
      if (buf[0] == '/'
	  && __xstat64 (_STAT_VER, buf, &st1) == 0
#ifdef _STATBUF_ST_RDEV
	  && S_ISCHR (st1.st_mode)
	  && st1.st_rdev == st.st_rdev
#else
	  && st1.st_ino == st.st_ino
	  && st1.st_dev == st.st_dev
#endif
	  )
	return 0;
    }

  /* Prepare the result buffer.  */
  memcpy (buf, "/dev/pts/", sizeof ("/dev/pts/"));
  buflen -= sizeof ("/dev/pts/") - 1;

  if (__xstat64 (_STAT_VER, buf, &st1) == 0 && S_ISDIR (st1.st_mode))
    {
#ifdef _STATBUF_ST_RDEV
      ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save,
			  &dostat);
#else
      ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save,
			  &dostat);
#endif
    }
  else
    {
      __set_errno (save);
      ret = ENOENT;
    }

  if (ret && dostat != -1)
    {
      buf[sizeof ("/dev/") - 1] = '\0';
      buflen += sizeof ("pts/") - 1;
#ifdef _STATBUF_ST_RDEV
      ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save,
			  &dostat);
#else
      ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save,
			  &dostat);
#endif
    }

  if (ret && dostat != -1)
    {
      buf[sizeof ("/dev/") - 1] = '\0';
      dostat = 1;
#ifdef _STATBUF_ST_RDEV
      ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino,
			  save, &dostat);
#else
      ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino,
			  save, &dostat);
#endif
    }

  return ret;
}