X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=string.c;h=51985404817d032261d0f19ba2ebce35682156dd;hp=ba32e8bfbddc9b314cfcf78011b4f85bc6322906;hb=299df142bb50bacebc0b3050768f941bc95b5b6f;hpb=6bdac07456cb5872f824028912d1049883a9c21f diff --git a/string.c b/string.c index ba32e8bf..51985404 100644 --- a/string.c +++ b/string.c @@ -33,7 +33,7 @@ __must_check __malloc void *para_realloc(void *p, size_t size) { /* - * No need to check for NULL pointers: If p is NULL, the call + * No need to check for NULL pointers: If p is NULL, the call * to realloc is equivalent to malloc(size) */ assert(size); @@ -64,7 +64,7 @@ __must_check __malloc void *para_malloc(size_t size) assert(size); p = malloc(size); if (!p) { - PARA_EMERG_LOG("malloc failed (size = %zu), aborting\n", + PARA_EMERG_LOG("malloc failed (size = %zu), aborting\n", size); exit(EXIT_FAILURE); } @@ -99,7 +99,7 @@ __must_check __malloc void *para_calloc(size_t size) * A wrapper for strdup(3). It calls \p exit(EXIT_FAILURE) on errors, i.e. * there is no need to check the return value in the caller. * - * \return A pointer to the duplicated string. If \p s was the NULL pointer, + * \return A pointer to the duplicated string. If \a s was the \p NULL pointer, * an pointer to an empty string is returned. * * \sa strdup(3) @@ -200,15 +200,15 @@ __must_check __malloc char *para_dirname(const char *name) * ends with a slash. Otherwise, a pointer within \a name is returned. Caller * must not free the result. */ -__must_check const char *para_basename(const char *name) +__must_check char *para_basename(const char *name) { - const char *ret; + char *ret; if (!name || !*name) return NULL; ret = strrchr(name, '/'); if (!ret) - return name; + return (char *)name; ret++; return ret; } @@ -218,44 +218,24 @@ __must_check const char *para_basename(const char *name) * * \param buf The string to be chopped. * - * Replace the last character in \p buf by zero if it is euqal to + * Replace the last character in \p buf by zero if it is equal to * the newline character. */ void chop(char *buf) { int n = strlen(buf); + if (!n) return; if (buf[n - 1] == '\n') buf[n - 1] = '\0'; } -/** - * Get a random filename. - * - * This is by no means a secure way to create temporary files in a hostile - * direcory like \p /tmp. However, it is OK to use for temp files, fifos, - * sockets that are created in ~/.paraslash. Result must be freed by the - * caller. - * - * \return A pointer to a random filename. - */ -__must_check __malloc char *para_tmpname(void) -{ - struct timeval now; - unsigned int seed; - - gettimeofday(&now, NULL); - seed = now.tv_usec; - srand(seed); - return make_message("%08i", rand()); -} - /** * Get the logname of the current user. * - * \return A dynammically allocated string that must be freed by the caller. On - * errors, the string "unknown user" is returned, i.e. this function never + * \return A dynamically allocated string that must be freed by the caller. On + * errors, the string "unknown_user" is returned, i.e. this function never * returns \p NULL. * * \sa getpwuid(3). @@ -269,7 +249,7 @@ __must_check __malloc char *para_logname(void) /** * Get the home directory of the current user. * - * \return A dynammically allocated string that must be freed by the caller. If + * \return A dynamically allocated string that must be freed by the caller. If * the home directory could not be found, this function returns "/tmp". */ __must_check __malloc char *para_homedir(void) @@ -285,16 +265,16 @@ __must_check __malloc char *para_homedir(void) * \param argv_ptr Pointer to the list of substrings. * \param delim Delimiter. * - * This function modifies \a args by replacing each occurance of \a delim by + * This function modifies \a args by replacing each occurrence of \a delim by * zero. A \p NULL-terminated array of pointers to char* is allocated dynamically * and these pointers are initialized to point to the broken-up substrings * within \a args. A pointer to this array is returned via \a argv_ptr. * * \return The number of substrings found in \a args. */ -__must_check unsigned split_args(char *args, char *** const argv_ptr, const char *delim) +unsigned split_args(char *args, char *** const argv_ptr, const char *delim) { - char *p = args; + char *p; char **argv; size_t n = 0, i, j; @@ -331,7 +311,7 @@ __must_check unsigned split_args(char *args, char *** const argv_ptr, const char /** * Get the own hostname. * - * \return A dynammically allocated string containing the hostname. + * \return A dynamically allocated string containing the hostname. * * \sa uname(2). */ @@ -408,7 +388,7 @@ static int for_each_complete_line(enum for_each_line_modes mode, char *buf, /** * Call a custom function for each complete line. * - * \param buf The buffer containing data seperated by newlines. + * \param buf The buffer containing data separated by newlines. * \param size The number of bytes in \a buf. * \param line_handler The custom function. * \param private_data Pointer passed to \a line_handler. @@ -456,8 +436,42 @@ int for_each_line_ro(char *buf, size_t size, line_handler_t *line_handler, private_data); } +#define hex(a) (hexchar[(a) & 15]) +static void write_size_header(char *buf, int n) +{ + static char hexchar[] = "0123456789abcdef"; + + buf[0] = hex(n >> 12); + buf[1] = hex(n >> 8); + buf[2] = hex(n >> 4); + buf[3] = hex(n); + buf[4] = ' '; +} + +int read_size_header(const char *buf) +{ + int i, len = 0; + + for (i = 0; i < 4; i++) { + unsigned char c = buf[i]; + len <<= 4; + if (c >= '0' && c <= '9') { + len += c - '0'; + continue; + } + if (c >= 'a' && c <= 'f') { + len += c - 'a' + 10; + continue; + } + return -E_SIZE_PREFIX; + } + if (buf[4] != ' ') + return -E_SIZE_PREFIX; + return len; +} + /** - * Safely print into a buffer at a given offset + * Safely print into a buffer at a given offset. * * \param b Determines the buffer, its size, and the offset. * \param fmt The format string. @@ -465,13 +479,14 @@ int for_each_line_ro(char *buf, size_t size, line_handler_t *line_handler, * This function prints into the buffer given by \a b at the offset which is * also given by \a b. If there is not enough space to hold the result, the * buffer size is doubled until the underlying call to vsnprintf() succeeds - * or the size of the buffer exceeds the maximal size specified in \a pb. + * or the size of the buffer exceeds the maximal size specified in \a b. * * In the latter case the unmodified \a buf and \a offset values as well as the * private_data pointer of \a b are passed to the \a max_size_handler of \a b. * If this function succeeds, i.e. returns a non-negative value, the offset of * \a b is reset to zero and the given data is written to the beginning of the - * buffer. + * buffer. If \a max_size_handler() returns a negative value, this value is + * returned by \a para_printf(). * * Upon return, the offset of \a b is adjusted accordingly so that subsequent * calls to this function append data to what is already contained in the @@ -481,13 +496,15 @@ int for_each_line_ro(char *buf, size_t size, line_handler_t *line_handler, * initial buffer is allocated. * * \return The number of bytes printed into the buffer (not including the - * therminating \p NULL byte). + * terminating \p NULL byte) on success, negative on errors. If there is no + * size-bound on \a b, i.e. if \p b->max_size is zero, this function never + * fails. * * \sa make_message(), vsnprintf(3). */ __printf_2_3 int para_printf(struct para_buffer *b, const char *fmt, ...) { - int ret; + int ret, sz_off = (b->flags & PBF_SIZE_PREFIX)? 5 : 0; if (!b->buf) { b->buf = para_malloc(128); @@ -498,13 +515,16 @@ __printf_2_3 int para_printf(struct para_buffer *b, const char *fmt, ...) char *p = b->buf + b->offset; size_t size = b->size - b->offset; va_list ap; - if (size) { + + if (size > sz_off) { va_start(ap, fmt); - ret = vsnprintf(p, size, fmt, ap); + ret = vsnprintf(p + sz_off, size - sz_off, fmt, ap); va_end(ap); - if (ret > -1 && ret < size) { /* success */ - b->offset += ret; - return ret; + if (ret > -1 && ret < size - sz_off) { /* success */ + b->offset += ret + sz_off; + if (sz_off) + write_size_header(p, ret); + return ret + sz_off; } } /* check if we may grow the buffer */ @@ -586,3 +606,34 @@ int para_atoi32(const char *str, int32_t *value) *value = tmp; return 1; } + +static inline int loglevel_equal(const char *arg, const char * const ll) +{ + return !strncasecmp(arg, ll, strlen(ll)); +} + +/** + * Compute the loglevel number from its name. + * + * \param txt The name of the loglevel (debug, info, ...). + * + * \return The numeric representation of the loglevel name. + */ +int get_loglevel_by_name(const char *txt) +{ + if (loglevel_equal(txt, "debug")) + return LL_DEBUG; + if (loglevel_equal(txt, "info")) + return LL_INFO; + if (loglevel_equal(txt, "notice")) + return LL_NOTICE; + if (loglevel_equal(txt, "warning")) + return LL_WARNING; + if (loglevel_equal(txt, "error")) + return LL_ERROR; + if (loglevel_equal(txt, "crit")) + return LL_CRIT; + if (loglevel_equal(txt, "emerg")) + return LL_EMERG; + return -1; +}