busybox/libbb/platform.c
<<
>>
Prefs
   1/*
   2 * Replacements for common but usually nonstandard functions that aren't
   3 * supplied by all platforms.
   4 *
   5 * Copyright (C) 2009 by Dan Fandrich <dan@coneharvesters.com>, et. al.
   6 *
   7 * Licensed under GPLv2, see file LICENSE in this source tree.
   8 */
   9#include "libbb.h"
  10
  11#ifndef HAVE_STRCHRNUL
  12char* FAST_FUNC strchrnul(const char *s, int c)
  13{
  14        while (*s != '\0' && *s != c)
  15                s++;
  16        return (char*)s;
  17}
  18#endif
  19
  20#ifndef HAVE_USLEEP
  21int FAST_FUNC usleep(unsigned usec)
  22{
  23        struct timespec ts;
  24        ts.tv_sec = usec / 1000000u;
  25        ts.tv_nsec = (usec % 1000000u) * 1000u;
  26        /*
  27         * If a signal has non-default handler, nanosleep returns early.
  28         * Our version of usleep doesn't return early
  29         * if interrupted by such signals:
  30         */
  31        while (nanosleep(&ts, &ts) != 0)
  32                continue;
  33        return 0;
  34}
  35#endif
  36
  37#ifndef HAVE_VASPRINTF
  38int FAST_FUNC vasprintf(char **string_ptr, const char *format, va_list p)
  39{
  40        int r;
  41        va_list p2;
  42        char buf[128];
  43
  44        va_copy(p2, p);
  45        r = vsnprintf(buf, 128, format, p);
  46        va_end(p);
  47
  48        /* Note: can't use xstrdup/xmalloc, they call vasprintf (us) on failure! */
  49
  50        if (r < 128) {
  51                va_end(p2);
  52                *string_ptr = strdup(buf);
  53                return (*string_ptr ? r : -1);
  54        }
  55
  56        *string_ptr = malloc(r+1);
  57        r = (*string_ptr ? vsnprintf(*string_ptr, r+1, format, p2) : -1);
  58        va_end(p2);
  59
  60        return r;
  61}
  62#endif
  63
  64#ifndef HAVE_DPRINTF
  65/* dprintf is now part of POSIX.1, but was only added in 2008 */
  66int dprintf(int fd, const char *format, ...)
  67{
  68        va_list p;
  69        int r;
  70        char *string_ptr;
  71
  72        va_start(p, format);
  73        r = vasprintf(&string_ptr, format, p);
  74        va_end(p);
  75        if (r >= 0) {
  76                r = full_write(fd, string_ptr, r);
  77                free(string_ptr);
  78        }
  79        return r;
  80}
  81#endif
  82
  83#ifndef HAVE_MEMRCHR
  84/* Copyright (C) 2005 Free Software Foundation, Inc.
  85 * memrchr() is a GNU function that might not be available everywhere.
  86 * It's basically the inverse of memchr() - search backwards in a
  87 * memory block for a particular character.
  88 */
  89void* FAST_FUNC memrchr(const void *s, int c, size_t n)
  90{
  91        const char *start = s, *end = s;
  92
  93        end += n - 1;
  94
  95        while (end >= start) {
  96                if (*end == (char)c)
  97                        return (void *) end;
  98                end--;
  99        }
 100
 101        return NULL;
 102}
 103#endif
 104
 105#ifndef HAVE_MKDTEMP
 106/* This is now actually part of POSIX.1, but was only added in 2008 */
 107char* FAST_FUNC mkdtemp(char *template)
 108{
 109        /* NB: on error, mktemp returns an empty string, not NULL */
 110        if (mktemp(template)[0] == '\0' || mkdir(template, 0700) != 0)
 111                return NULL;
 112        return template;
 113}
 114#endif
 115
 116#ifndef HAVE_STRCASESTR
 117/* Copyright (c) 1999, 2000 The ht://Dig Group */
 118char* FAST_FUNC strcasestr(const char *s, const char *pattern)
 119{
 120        int length = strlen(pattern);
 121
 122        while (*s) {
 123                if (strncasecmp(s, pattern, length) == 0)
 124                        return (char *)s;
 125                s++;
 126        }
 127        return 0;
 128}
 129#endif
 130
 131#ifndef HAVE_STRSEP
 132/* Copyright (C) 2004 Free Software Foundation, Inc. */
 133char* FAST_FUNC strsep(char **stringp, const char *delim)
 134{
 135        char *start = *stringp;
 136        char *ptr;
 137
 138        if (!start)
 139                return NULL;
 140
 141        if (!*delim)
 142                ptr = start + strlen(start);
 143        else {
 144                ptr = strpbrk(start, delim);
 145                if (!ptr) {
 146                        *stringp = NULL;
 147                        return start;
 148                }
 149        }
 150
 151        *ptr = '\0';
 152        *stringp = ptr + 1;
 153
 154        return start;
 155}
 156#endif
 157
 158#ifndef HAVE_STPCPY
 159char* FAST_FUNC stpcpy(char *p, const char *to_add)
 160{
 161        while ((*p = *to_add) != '\0') {
 162                p++;
 163                to_add++;
 164        }
 165        return p;
 166}
 167#endif
 168
 169#ifndef HAVE_STPNCPY
 170char* FAST_FUNC stpncpy(char *p, const char *to_add, size_t n)
 171{
 172        while (n != 0 && (*p = *to_add) != '\0') {
 173                p++;
 174                to_add++;
 175                n--;
 176        }
 177        return p;
 178}
 179#endif
 180
 181#ifndef HAVE_GETLINE
 182ssize_t FAST_FUNC getline(char **lineptr, size_t *n, FILE *stream)
 183{
 184        int ch;
 185        char *line = *lineptr;
 186        size_t alloced = *n;
 187        size_t len = 0;
 188
 189        do {
 190                ch = fgetc(stream);
 191                if (ch == EOF)
 192                        break;
 193                if (len + 1 >= alloced) {
 194                        alloced += alloced/4 + 64;
 195                        line = xrealloc(line, alloced);
 196                }
 197                line[len++] = ch;
 198        } while (ch != '\n');
 199
 200        if (len == 0)
 201                return -1;
 202
 203        line[len] = '\0';
 204        *lineptr = line;
 205        *n = alloced;
 206        return len;
 207}
 208#endif
 209
 210#ifndef HAVE_TTYNAME_R
 211int ttyname_r(int fd, char *buf, size_t buflen)
 212{
 213        int r;
 214        char path[sizeof("/proc/self/fd/%d") + sizeof(int)*3];
 215
 216        if (!isatty(fd))
 217                return errno == EINVAL ? ENOTTY : errno;
 218        sprintf(path, "/proc/self/fd/%d", fd);
 219        r = readlink(path, buf, buflen);
 220        if (r < 0)
 221                return errno;
 222        if (r >= buflen)
 223                return ERANGE;
 224        buf[r] = '\0';
 225        return 0;
 226}
 227#endif
 228