diff options
author | Sven Eden <yamakuzure@gmx.net> | 2017-06-07 12:10:11 +0200 |
---|---|---|
committer | Sven Eden <yamakuzure@gmx.net> | 2017-06-16 10:12:58 +0200 |
commit | 955baa81f8239cb338f53c7707d6d2c656c32c33 (patch) | |
tree | d06f6a9f9b0c8199527a0023c8bee88aeb5bb10a /src/shared | |
parent | e1a3886b1048af543e67f4af0c02bb8d0abb9ca9 (diff) |
Prep v230: Move musl_missing and parse-printf-format to libshared.
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/musl_missing.c | 36 | ||||
-rw-r--r-- | src/shared/musl_missing.h | 92 | ||||
-rw-r--r-- | src/shared/parse-printf-format.c | 275 | ||||
-rw-r--r-- | src/shared/parse-printf-format.h | 56 |
4 files changed, 459 insertions, 0 deletions
diff --git a/src/shared/musl_missing.c b/src/shared/musl_missing.c new file mode 100644 index 000000000..5ce787beb --- /dev/null +++ b/src/shared/musl_missing.c @@ -0,0 +1,36 @@ +#include <string.h> +#include "alloc-util.h" + +#ifndef __GLIBC__ +char *program_invocation_name = NULL; +char *program_invocation_short_name = NULL; +#endif // __GLIBC__ + +#include "musl_missing.h" + +static void elogind_free_program_name(void) { + if (program_invocation_name) + program_invocation_name = mfree(program_invocation_name); + if (program_invocation_short_name) + program_invocation_short_name = mfree(program_invocation_short_name); +} + +void elogind_set_program_name(const char* pcall) { + assert(pcall && pcall[0]); + + if ( ( program_invocation_name + && strcmp(program_invocation_name, pcall)) + || ( program_invocation_short_name + && strcmp(program_invocation_short_name, basename(pcall)) ) ) + elogind_free_program_name(); + + if (NULL == program_invocation_name) + program_invocation_name = strdup(pcall); + if (NULL == program_invocation_short_name) + program_invocation_short_name = strdup(basename(pcall)); + +#ifndef __GLIBC__ + atexit(elogind_free_program_name); +#endif // __GLIBC__ +} + diff --git a/src/shared/musl_missing.h b/src/shared/musl_missing.h new file mode 100644 index 000000000..37a7005c9 --- /dev/null +++ b/src/shared/musl_missing.h @@ -0,0 +1,92 @@ +#pragma once +#ifndef ELOGIND_BASIC_MUSL_MISSING_H_INCLUDED +#define ELOGIND_BASIC_MUSL_MISSING_H_INCLUDED + + +/**************************************************************** + * musl_missing.h - work around glibc extensions for musl libc. + * + * Implements glibc functions missing in musl libc as macros. + * Is to be included where these functions are used. + * Also defines some glibc only constants as either 0 or + * as found in the corresponding glibc header file. + * + * Juergen Buchmueller <pullmoll@t-online.de> for Void Linux + * Public Domain; no warranties whatsoever. Thank you Mr. P. + * + ****************************************************************/ + + +void elogind_set_program_name(const char* pcall); + +#if !defined(__GLIBC__) +#include "config.h" +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define strerror_r(e, m, k) (strerror_r(e, m, k) < 0 ? strdup("strerror_r() failed") : m); + +#ifndef _ERRNO_H +extern char *program_invocation_name; +extern char *program_invocation_short_name; +#endif // errno.h included beforehand + +/* + * Possibly TODO according to http://man7.org/linux/man-pages/man3/getenv.3.html + * + test if the process's effective user ID does not match its real user ID or + * the process's effective group ID does not match its real group ID; + * typically this is the result of executing a set-user-ID or set- + * group-ID program. Is calling issetugid() sufficient here? + * + test if the effective capability bit was set on the executable file + * + test if the process has a nonempty permitted capability set + */ +#if !defined(HAVE_SECURE_GETENV) && !defined(HAVE___SECURE_GETENV) +# define secure_getenv(name) \ + (issetugid() ? NULL : getenv(name)) +# define HAVE_SECURE_GETENV 1 +#endif // HAVE_[__]SECURE_GETENV + +/* Poor man's basename */ +#define basename(path) \ + (strrchr(path, '/') ? strrchr(path, '/')+1 : path) + +/* strndupa may already be defined in another compatibility header */ +#if !defined(strndupa) +#define strndupa(src, n) \ + (__extension__ ({const char *in = (src); \ + size_t len = strnlen(in, (n)) + 1; \ + char *out = (char *) alloca(len); \ + out[len-1] = '\0'; \ + (char *) memcpy(out, in, len-1);}) \ + ) +#endif + +/* See http://man7.org/linux/man-pages/man3/canonicalize_file_name.3.html */ +#define canonicalize_file_name(path) \ + realpath(path, NULL) + +/* GLOB_BRACE is another glibc extension - ignore it for musl libc */ +#define GLOB_BRACE 0 + +/* getnameinfo(3) glibc extensions are undefined in musl libc */ +#define NI_IDN 0 +#define NI_IDN_USE_STD3_ASCII_RULES 0 + +/* Taken from glibc's net/if_arp.h */ +#if !defined(ARPHRD_IEEE802154_PHY) +#define ARPHRD_IEEE802154_PHY 805 /* IEEE 802.15.4 PHY header. */ +#endif + +/* Shorthand for type of comparison functions. */ +#ifndef __COMPAR_FN_T +# define __COMPAR_FN_T +typedef int (*__compar_fn_t) (const void *, const void *); +typedef __compar_fn_t comparison_fn_t; +#endif + + +#endif // !defined(__GLIBC__) + +#endif // ELOGIND_BASIC_MUSL_MISSING_H_INCLUDED + diff --git a/src/shared/parse-printf-format.c b/src/shared/parse-printf-format.c new file mode 100644 index 000000000..a99952b70 --- /dev/null +++ b/src/shared/parse-printf-format.c @@ -0,0 +1,275 @@ +/*** + This file is part of systemd. + + Copyright 2014 Emil Renner Berthing <systemd@esmil.dk> + + With parts from the musl C library + Copyright 2005-2014 Rich Felker, et al. + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <stddef.h> +#include <string.h> + +#include "parse-printf-format.h" + +#ifndef HAVE_PRINTF_H + +static const char *consume_nonarg(const char *fmt) +{ + do { + if (*fmt == '\0') + return fmt; + } while (*fmt++ != '%'); + return fmt; +} + +static const char *consume_num(const char *fmt) +{ + for (;*fmt >= '0' && *fmt <= '9'; fmt++) + /* do nothing */; + return fmt; +} + +static const char *consume_argn(const char *fmt, size_t *arg) +{ + const char *p = fmt; + size_t val = 0; + + if (*p < '1' || *p > '9') + return fmt; + do { + val = 10*val + (*p++ - '0'); + } while (*p >= '0' && *p <= '9'); + + if (*p != '$') + return fmt; + *arg = val; + return p+1; +} + +static const char *consume_flags(const char *fmt) +{ + while (1) { + switch (*fmt) { + case '#': + case '0': + case '-': + case ' ': + case '+': + case '\'': + case 'I': + fmt++; + continue; + } + return fmt; + } +} + +enum state { + BARE, + LPRE, + LLPRE, + HPRE, + HHPRE, + BIGLPRE, + ZTPRE, + JPRE, + STOP +}; + +enum type { + NONE, + PTR, + INT, + UINT, + ULLONG, + LONG, + ULONG, + SHORT, + USHORT, + CHAR, + UCHAR, + LLONG, + SIZET, + IMAX, + UMAX, + PDIFF, + UIPTR, + DBL, + LDBL, + MAXTYPE +}; + +static const short pa_types[MAXTYPE] = { + [NONE] = PA_INT, + [PTR] = PA_POINTER, + [INT] = PA_INT, + [UINT] = PA_INT, + [ULLONG] = PA_INT | PA_FLAG_LONG_LONG, + [LONG] = PA_INT | PA_FLAG_LONG, + [ULONG] = PA_INT | PA_FLAG_LONG, + [SHORT] = PA_INT | PA_FLAG_SHORT, + [USHORT] = PA_INT | PA_FLAG_SHORT, + [CHAR] = PA_CHAR, + [UCHAR] = PA_CHAR, + [LLONG] = PA_INT | PA_FLAG_LONG_LONG, + [SIZET] = PA_INT | PA_FLAG_LONG, + [IMAX] = PA_INT | PA_FLAG_LONG_LONG, + [UMAX] = PA_INT | PA_FLAG_LONG_LONG, + [PDIFF] = PA_INT | PA_FLAG_LONG_LONG, + [UIPTR] = PA_INT | PA_FLAG_LONG, + [DBL] = PA_DOUBLE, + [LDBL] = PA_DOUBLE | PA_FLAG_LONG_DOUBLE +}; + +#define S(x) [(x)-'A'] +#define E(x) (STOP + (x)) + +static const unsigned char states[]['z'-'A'+1] = { + { /* 0: bare types */ + S('d') = E(INT), S('i') = E(INT), + S('o') = E(UINT),S('u') = E(UINT),S('x') = E(UINT), S('X') = E(UINT), + S('e') = E(DBL), S('f') = E(DBL), S('g') = E(DBL), S('a') = E(DBL), + S('E') = E(DBL), S('F') = E(DBL), S('G') = E(DBL), S('A') = E(DBL), + S('c') = E(CHAR),S('C') = E(INT), + S('s') = E(PTR), S('S') = E(PTR), S('p') = E(UIPTR),S('n') = E(PTR), + S('m') = E(NONE), + S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE, + S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE + }, { /* 1: l-prefixed */ + S('d') = E(LONG), S('i') = E(LONG), + S('o') = E(ULONG),S('u') = E(ULONG),S('x') = E(ULONG),S('X') = E(ULONG), + S('e') = E(DBL), S('f') = E(DBL), S('g') = E(DBL), S('a') = E(DBL), + S('E') = E(DBL), S('F') = E(DBL), S('G') = E(DBL), S('A') = E(DBL), + S('c') = E(INT), S('s') = E(PTR), S('n') = E(PTR), + S('l') = LLPRE + }, { /* 2: ll-prefixed */ + S('d') = E(LLONG), S('i') = E(LLONG), + S('o') = E(ULLONG),S('u') = E(ULLONG), + S('x') = E(ULLONG),S('X') = E(ULLONG), + S('n') = E(PTR) + }, { /* 3: h-prefixed */ + S('d') = E(SHORT), S('i') = E(SHORT), + S('o') = E(USHORT),S('u') = E(USHORT), + S('x') = E(USHORT),S('X') = E(USHORT), + S('n') = E(PTR), + S('h') = HHPRE + }, { /* 4: hh-prefixed */ + S('d') = E(CHAR), S('i') = E(CHAR), + S('o') = E(UCHAR),S('u') = E(UCHAR), + S('x') = E(UCHAR),S('X') = E(UCHAR), + S('n') = E(PTR) + }, { /* 5: L-prefixed */ + S('e') = E(LDBL),S('f') = E(LDBL),S('g') = E(LDBL), S('a') = E(LDBL), + S('E') = E(LDBL),S('F') = E(LDBL),S('G') = E(LDBL), S('A') = E(LDBL), + S('n') = E(PTR) + }, { /* 6: z- or t-prefixed (assumed to be same size) */ + S('d') = E(PDIFF),S('i') = E(PDIFF), + S('o') = E(SIZET),S('u') = E(SIZET), + S('x') = E(SIZET),S('X') = E(SIZET), + S('n') = E(PTR) + }, { /* 7: j-prefixed */ + S('d') = E(IMAX), S('i') = E(IMAX), + S('o') = E(UMAX), S('u') = E(UMAX), + S('x') = E(UMAX), S('X') = E(UMAX), + S('n') = E(PTR) + } +}; + +size_t parse_printf_format(const char *fmt, size_t n, int *types) +{ + size_t i = 0; + size_t last = 0; + + memset(types, 0, n); + + while (1) { + size_t arg; + unsigned int state; + + fmt = consume_nonarg(fmt); + if (*fmt == '\0') + break; + if (*fmt == '%') { + fmt++; + continue; + } + arg = 0; + fmt = consume_argn(fmt, &arg); + /* flags */ + fmt = consume_flags(fmt); + /* width */ + if (*fmt == '*') { + size_t warg = 0; + fmt = consume_argn(fmt+1, &warg); + if (warg == 0) + warg = ++i; + if (warg > last) + last = warg; + if (warg <= n && types[warg-1] == NONE) + types[warg-1] = INT; + } else + fmt = consume_num(fmt); + /* precision */ + if (*fmt == '.') { + fmt++; + if (*fmt == '*') { + size_t parg = 0; + fmt = consume_argn(fmt+1, &parg); + if (parg == 0) + parg = ++i; + if (parg > last) + last = parg; + if (parg <= n && types[parg-1] == NONE) + types[parg-1] = INT; + } else { + if (*fmt == '-') + fmt++; + fmt = consume_num(fmt); + } + } + /* length modifier and conversion specifier */ + state = BARE; + do { + unsigned char c = *fmt++; + + if (c < 'A' || c > 'z') + continue; + state = states[state]S(c); + if (state == 0) + continue; + } while (state < STOP); + + if (state == E(NONE)) + continue; + + if (arg == 0) + arg = ++i; + if (arg > last) + last = arg; + if (arg <= n) + types[arg-1] = state - STOP; + } + + if (last > n) + last = n; + for (i = 0; i < last; i++) + types[i] = pa_types[types[i]]; + + return last; +} + +#endif // HAVE_PRINTF_H diff --git a/src/shared/parse-printf-format.h b/src/shared/parse-printf-format.h new file mode 100644 index 000000000..5ca0fdf56 --- /dev/null +++ b/src/shared/parse-printf-format.h @@ -0,0 +1,56 @@ +/*** + This file is part of systemd. + + Copyright 2014 Emil Renner Berthing <systemd@esmil.dk> + + With parts from the GNU C Library + Copyright 1991-2014 Free Software Foundation, Inc. + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#pragma once + +#include "config.h" + +#ifdef HAVE_PRINTF_H +#include <printf.h> +#else + +#include <stddef.h> + +enum { /* C type: */ + PA_INT, /* int */ + PA_CHAR, /* int, cast to char */ + PA_WCHAR, /* wide char */ + PA_STRING, /* const char *, a '\0'-terminated string */ + PA_WSTRING, /* const wchar_t *, wide character string */ + PA_POINTER, /* void * */ + PA_FLOAT, /* float */ + PA_DOUBLE, /* double */ + PA_LAST +}; + +/* Flag bits that can be set in a type returned by `parse_printf_format'. */ +#define PA_FLAG_MASK 0xff00 +#define PA_FLAG_LONG_LONG (1 << 8) +#define PA_FLAG_LONG_DOUBLE PA_FLAG_LONG_LONG +#define PA_FLAG_LONG (1 << 9) +#define PA_FLAG_SHORT (1 << 10) +#define PA_FLAG_PTR (1 << 11) + +size_t parse_printf_format(const char *fmt, size_t n, int *types); + +#endif /* HAVE_PRINTF_H */ + |