build-sys: Relocate lib/
test files in lib go to src/tests include/ goes to local/ lib/*.c goes to local/ Signed-off-by: Craig Small <csmall@dropbear.xyz>
This commit is contained in:
@ -1,45 +0,0 @@
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_ERROR_H
|
||||
# include <error.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDIO_EXT_H
|
||||
# include <stdio_ext.h>
|
||||
#else
|
||||
/* FIXME: use a more portable definition of __fpending() (from gnulib?) */
|
||||
# include <stdio.h>
|
||||
# define __fpending(fp) ((fp)->_p - (fp)->_bf._base)
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "nls.h"
|
||||
#include "fileutils.h"
|
||||
#ifndef HAVE_ERROR_H
|
||||
# include "c.h" /* for error() emulation */
|
||||
#endif
|
||||
|
||||
int close_stream(FILE * stream)
|
||||
{
|
||||
const int some_pending = (__fpending(stream) != 0);
|
||||
const int prev_fail = (ferror(stream) != 0);
|
||||
const int fclose_fail = (fclose(stream) != 0);
|
||||
if (prev_fail || (fclose_fail && (some_pending || errno != EBADF))) {
|
||||
if (!fclose_fail && errno != EPIPE)
|
||||
errno = 0;
|
||||
return EOF;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use atexit(); */
|
||||
void close_stdout(void)
|
||||
{
|
||||
if (close_stream(stdout) != 0 && !(errno == EPIPE)) {
|
||||
char const *write_error = _("write error");
|
||||
error(0, errno, "%s", write_error);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (close_stream(stderr) != 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
292
lib/procio.c
292
lib/procio.c
@ -1,292 +0,0 @@
|
||||
/*
|
||||
* procio.c -- Replace stdio for read and write on files below
|
||||
* proc to be able to read and write large buffers as well.
|
||||
*
|
||||
* Copyright (C) 2017 Werner Fink
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef struct pcookie {
|
||||
char *buf;
|
||||
size_t count;
|
||||
size_t length;
|
||||
off_t offset;
|
||||
int fd;
|
||||
int delim;
|
||||
int final:1;
|
||||
} pcookie_t;
|
||||
|
||||
static ssize_t proc_read(void *, char *, size_t);
|
||||
static ssize_t proc_write(void *, const char *, size_t);
|
||||
static int proc_close(void *);
|
||||
|
||||
__extension__
|
||||
static cookie_io_functions_t procio = {
|
||||
.read = proc_read,
|
||||
.write = proc_write,
|
||||
.seek = NULL,
|
||||
.close = proc_close,
|
||||
};
|
||||
|
||||
FILE *fprocopen(const char *path, const char *mode)
|
||||
{
|
||||
pcookie_t *cookie = NULL;
|
||||
FILE *handle = NULL;
|
||||
mode_t flags = 0;
|
||||
size_t len = 0;
|
||||
int c, delim;
|
||||
|
||||
if (!mode || !(len = strlen(mode))) {
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* No append mode possible */
|
||||
switch (mode[0]) {
|
||||
case 'r':
|
||||
flags |= O_RDONLY;
|
||||
break;
|
||||
case 'w':
|
||||
flags |= O_WRONLY|O_TRUNC;
|
||||
break;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
delim = ','; /* default delimeter is the comma */
|
||||
for (c = 1; c < len; c++) {
|
||||
switch (mode[c]) {
|
||||
case '\0':
|
||||
break;
|
||||
case '+':
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
case 'e':
|
||||
flags |= O_CLOEXEC;
|
||||
continue;
|
||||
case 'b':
|
||||
case 'm':
|
||||
case 'x':
|
||||
/* ignore this */
|
||||
continue;
|
||||
default:
|
||||
if (mode[c] == ' ' || (mode[c] >= ',' && mode[c] <= '.') || mode[c] == ':')
|
||||
delim = mode[c];
|
||||
else {
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
cookie = (pcookie_t *)malloc(sizeof(pcookie_t));
|
||||
if (!cookie)
|
||||
goto out;
|
||||
cookie->count = BUFSIZ;
|
||||
cookie->buf = (char *)malloc(cookie->count);
|
||||
if (!cookie->buf) {
|
||||
int errsv = errno;
|
||||
free(cookie);
|
||||
errno = errsv;
|
||||
goto out;
|
||||
}
|
||||
cookie->final = 0;
|
||||
cookie->offset = 0;
|
||||
cookie->length = 0;
|
||||
cookie->delim = delim;
|
||||
|
||||
cookie->fd = openat(AT_FDCWD, path, flags);
|
||||
if (cookie->fd < 0) {
|
||||
int errsv = errno;
|
||||
free(cookie->buf);
|
||||
free(cookie);
|
||||
errno = errsv;
|
||||
goto out;
|
||||
}
|
||||
|
||||
handle = fopencookie(cookie, mode, procio);
|
||||
if (!handle) {
|
||||
int errsv = errno;
|
||||
close(cookie->fd);
|
||||
free(cookie->buf);
|
||||
free(cookie);
|
||||
errno = errsv;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
return handle;
|
||||
}
|
||||
|
||||
static
|
||||
ssize_t proc_read(void *c, char *buf, size_t count)
|
||||
{
|
||||
pcookie_t *cookie = c;
|
||||
ssize_t len = -1;
|
||||
void *ptr;
|
||||
|
||||
if (cookie->count < count) {
|
||||
ptr = realloc(cookie->buf, count);
|
||||
if (!ptr)
|
||||
goto out;
|
||||
cookie->buf = ptr;
|
||||
cookie->count = count;
|
||||
}
|
||||
|
||||
while (!cookie->final) {
|
||||
len = read(cookie->fd, cookie->buf, cookie->count);
|
||||
|
||||
if (len <= 0) {
|
||||
if (len == 0) {
|
||||
/* EOF */
|
||||
cookie->final = 1;
|
||||
cookie->buf[cookie->length] = '\0';
|
||||
break;
|
||||
}
|
||||
goto out; /* error or done */
|
||||
}
|
||||
|
||||
cookie->length = len;
|
||||
|
||||
if (cookie->length < cookie->count)
|
||||
continue;
|
||||
|
||||
/* Likly to small buffer here */
|
||||
|
||||
lseek(cookie->fd, 0, SEEK_SET); /* reset for a retry */
|
||||
|
||||
ptr = realloc(cookie->buf, cookie->count += BUFSIZ);
|
||||
if (!ptr)
|
||||
goto out;
|
||||
cookie->buf = ptr;
|
||||
}
|
||||
|
||||
len = count;
|
||||
if (cookie->length - cookie->offset < len)
|
||||
len = cookie->length - cookie->offset;
|
||||
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
|
||||
if (len) {
|
||||
(void)memcpy(buf, cookie->buf+cookie->offset, len);
|
||||
cookie->offset += len;
|
||||
} else
|
||||
len = EOF;
|
||||
out:
|
||||
return len;
|
||||
}
|
||||
|
||||
#define LINELEN 4096
|
||||
|
||||
static
|
||||
ssize_t proc_write(void *c, const char *buf, size_t count)
|
||||
{
|
||||
pcookie_t *cookie = c;
|
||||
ssize_t len = -1;
|
||||
void *ptr;
|
||||
|
||||
if (!count) {
|
||||
len = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* NL is the final input */
|
||||
cookie->final = memrchr(buf, '\n', count) ? 1 : 0;
|
||||
|
||||
while (cookie->count < cookie->offset + count) {
|
||||
ptr = realloc(cookie->buf, cookie->count += count);
|
||||
if (!ptr)
|
||||
goto out;
|
||||
cookie->buf = ptr;
|
||||
}
|
||||
|
||||
len = count;
|
||||
(void)memcpy(cookie->buf+cookie->offset, buf, count);
|
||||
cookie->offset += count;
|
||||
|
||||
if (cookie->final) {
|
||||
len = write(cookie->fd, cookie->buf, cookie->offset);
|
||||
if (len < 0 && errno == EINVAL) {
|
||||
size_t offset;
|
||||
off_t amount;
|
||||
char *token;
|
||||
/*
|
||||
* Oops buffer might be to large, split buffer into
|
||||
* pieces at delimeter if provided
|
||||
*/
|
||||
if (!cookie->delim)
|
||||
goto out; /* Hey dude?! */
|
||||
offset = 0;
|
||||
do {
|
||||
token = NULL;
|
||||
if (cookie->offset > LINELEN)
|
||||
token = (char*)memrchr(cookie->buf+offset, cookie->delim, LINELEN);
|
||||
else
|
||||
token = (char*)memrchr(cookie->buf+offset, '\n', cookie->offset);
|
||||
if (token)
|
||||
*token = '\n';
|
||||
else {
|
||||
errno = EINVAL;
|
||||
len = -1;
|
||||
goto out; /* Wrong/Missing delimeter? */
|
||||
}
|
||||
if (offset > 0)
|
||||
lseek(cookie->fd, 1, SEEK_CUR);
|
||||
|
||||
amount = token-(cookie->buf+offset)+1;
|
||||
ptr = cookie->buf+offset;
|
||||
|
||||
len = write(cookie->fd, ptr, amount);
|
||||
if (len < 1 || len >= cookie->offset)
|
||||
break;
|
||||
|
||||
offset += len;
|
||||
cookie->offset -= len;
|
||||
|
||||
} while (cookie->offset > 0);
|
||||
}
|
||||
if (len > 0)
|
||||
len = count;
|
||||
}
|
||||
out:
|
||||
return len;
|
||||
}
|
||||
|
||||
static
|
||||
int proc_close(void *c)
|
||||
{
|
||||
pcookie_t *cookie = c;
|
||||
close(cookie->fd);
|
||||
free(cookie->buf);
|
||||
free(cookie);
|
||||
return 0;
|
||||
}
|
316
lib/signals.c
316
lib/signals.c
@ -1,316 +0,0 @@
|
||||
/*
|
||||
* signals.c - signal name, and number, conversions
|
||||
* Copyright 1998-2003 by Albert Cahalan
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "signals.h"
|
||||
#include "c.h"
|
||||
|
||||
/* Linux signals:
|
||||
*
|
||||
* SIGSYS is required by Unix98.
|
||||
* SIGEMT is part of SysV, BSD, and ancient UNIX tradition.
|
||||
*
|
||||
* They are provided by these Linux ports: alpha, mips, sparc, and sparc64.
|
||||
* You get SIGSTKFLT and SIGUNUSED instead on i386, m68k, ppc, and arm.
|
||||
* (this is a Linux & libc bug -- both must be fixed)
|
||||
*
|
||||
* Total garbage: SIGIO SIGINFO SIGIOT SIGCLD
|
||||
* (popular ones are handled as aliases)
|
||||
* SIGLOST
|
||||
* (except on the Hurd; reused to mean a server died)
|
||||
* Nearly garbage: SIGSTKFLT SIGUNUSED (nothing else to fill slots)
|
||||
*/
|
||||
|
||||
/* Linux 2.3.29 replaces SIGUNUSED with the standard SIGSYS signal */
|
||||
#ifndef SIGSYS
|
||||
# warning Standards require that <signal.h> define SIGSYS
|
||||
# define SIGSYS SIGUNUSED
|
||||
#endif
|
||||
|
||||
/* If we see both, it is likely SIGSTKFLT (junk) was replaced. */
|
||||
#ifdef SIGEMT
|
||||
# undef SIGSTKFLT
|
||||
#endif
|
||||
|
||||
#ifndef SIGRTMIN
|
||||
# warning Standards require that <signal.h> define SIGRTMIN; assuming 32
|
||||
# define SIGRTMIN 32
|
||||
#endif
|
||||
|
||||
/* It seems the SPARC libc does not know the kernel supports SIGPWR. */
|
||||
#if defined(__linux__) && !defined(SIGPWR)
|
||||
# warning Your header files lack SIGPWR. (assuming it is number 29)
|
||||
# define SIGPWR 29
|
||||
#endif
|
||||
|
||||
typedef struct mapstruct {
|
||||
const char *name;
|
||||
int num;
|
||||
} mapstruct;
|
||||
|
||||
|
||||
static const mapstruct sigtable[] = {
|
||||
{"ABRT", SIGABRT}, /* IOT */
|
||||
{"ALRM", SIGALRM},
|
||||
{"BUS", SIGBUS},
|
||||
{"CHLD", SIGCHLD}, /* CLD */
|
||||
{"CONT", SIGCONT},
|
||||
#ifdef SIGEMT
|
||||
{"EMT", SIGEMT},
|
||||
#endif
|
||||
{"FPE", SIGFPE},
|
||||
{"HUP", SIGHUP},
|
||||
{"ILL", SIGILL},
|
||||
{"INT", SIGINT},
|
||||
{"KILL", SIGKILL},
|
||||
#if defined(__GNU__)
|
||||
{"LOST", SIGLOST}, /* Hurd-specific */
|
||||
#endif
|
||||
{"PIPE", SIGPIPE},
|
||||
{"POLL", SIGPOLL}, /* IO */
|
||||
{"PROF", SIGPROF},
|
||||
#ifdef SIGPWR
|
||||
{"PWR", SIGPWR},
|
||||
#endif
|
||||
{"QUIT", SIGQUIT},
|
||||
{"SEGV", SIGSEGV},
|
||||
#ifdef SIGSTKFLT
|
||||
{"STKFLT", SIGSTKFLT},
|
||||
#endif
|
||||
{"STOP", SIGSTOP},
|
||||
{"SYS", SIGSYS}, /* UNUSED */
|
||||
{"TERM", SIGTERM},
|
||||
{"TRAP", SIGTRAP},
|
||||
{"TSTP", SIGTSTP},
|
||||
{"TTIN", SIGTTIN},
|
||||
{"TTOU", SIGTTOU},
|
||||
{"URG", SIGURG},
|
||||
{"USR1", SIGUSR1},
|
||||
{"USR2", SIGUSR2},
|
||||
{"VTALRM", SIGVTALRM},
|
||||
{"WINCH", SIGWINCH},
|
||||
{"XCPU", SIGXCPU},
|
||||
{"XFSZ", SIGXFSZ}
|
||||
};
|
||||
|
||||
|
||||
#define number_of_signals (sizeof(sigtable)/sizeof(mapstruct))
|
||||
|
||||
#define XJOIN(a, b) JOIN(a, b)
|
||||
#define JOIN(a, b) a##b
|
||||
#define STATIC_ASSERT(x) typedef int XJOIN(static_assert_on_line_,__LINE__)[(x) ? 1 : -1]
|
||||
|
||||
/* sanity check */
|
||||
#if defined(__linux__)
|
||||
STATIC_ASSERT(number_of_signals == 31);
|
||||
#elif defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
|
||||
STATIC_ASSERT(number_of_signals == 30);
|
||||
#elif defined(__GNU__)
|
||||
STATIC_ASSERT(number_of_signals == 31);
|
||||
#elif defined(__CYGWIN__)
|
||||
STATIC_ASSERT(number_of_signals == 31);
|
||||
#else
|
||||
# warning Unknown operating system; assuming number_of_signals is correct
|
||||
#endif
|
||||
|
||||
static int compare_signal_names(const void *a, const void *b){
|
||||
return strcasecmp( ((const mapstruct*)a)->name, ((const mapstruct*)b)->name );
|
||||
}
|
||||
|
||||
|
||||
const char *get_sigtable_name(int row)
|
||||
{
|
||||
if (row < 0 || row >= number_of_signals)
|
||||
return NULL;
|
||||
return sigtable[row].name;
|
||||
}
|
||||
|
||||
const int get_sigtable_num(int row)
|
||||
{
|
||||
if (row < 0 || row >= number_of_signals)
|
||||
return -1;
|
||||
return sigtable[row].num;
|
||||
}
|
||||
|
||||
/* return -1 on failure */
|
||||
int signal_name_to_number(const char *restrict name){
|
||||
long val;
|
||||
int offset;
|
||||
|
||||
/* clean up name */
|
||||
if(!strncasecmp(name,"SIG",3))
|
||||
name += 3;
|
||||
|
||||
if(!strcasecmp(name,"CLD"))
|
||||
return SIGCHLD;
|
||||
if(!strcasecmp(name,"IO"))
|
||||
return SIGPOLL;
|
||||
if(!strcasecmp(name,"IOT"))
|
||||
return SIGABRT;
|
||||
/* search the table */
|
||||
{
|
||||
const mapstruct ms = {name,0};
|
||||
const mapstruct *restrict const ptr = bsearch(
|
||||
&ms,
|
||||
sigtable,
|
||||
number_of_signals,
|
||||
sizeof(mapstruct),
|
||||
compare_signal_names);
|
||||
if(ptr)
|
||||
return ptr->num;
|
||||
}
|
||||
|
||||
if(!strcasecmp(name,"RTMIN"))
|
||||
return SIGRTMIN;
|
||||
if(!strcasecmp(name,"EXIT"))
|
||||
return 0;
|
||||
if(!strcasecmp(name,"NULL"))
|
||||
return 0;
|
||||
|
||||
offset = 0;
|
||||
if(!strncasecmp(name,"RTMIN+",6)) {
|
||||
name += 6;
|
||||
offset = SIGRTMIN;
|
||||
}
|
||||
|
||||
/* not found, so try as a number */
|
||||
{
|
||||
char *endp;
|
||||
val = strtol(name,&endp,10);
|
||||
if(*endp || endp==name)
|
||||
return -1; /* not valid */
|
||||
}
|
||||
if(val<0 || val+SIGRTMIN>127)
|
||||
return -1; /* not valid */
|
||||
return val+offset;
|
||||
}
|
||||
|
||||
const char *signal_number_to_name(int signo)
|
||||
{
|
||||
static char buf[32];
|
||||
int n = number_of_signals;
|
||||
signo &= 0x7f; /* need to process exit values too */
|
||||
while (n--) {
|
||||
if(sigtable[n].num==signo)
|
||||
return sigtable[n].name;
|
||||
}
|
||||
if (signo == SIGRTMIN)
|
||||
return "RTMIN";
|
||||
if (signo)
|
||||
sprintf(buf, "RTMIN+%d", signo-SIGRTMIN);
|
||||
else
|
||||
strcpy(buf,"0"); /* AIX has NULL; Solaris has EXIT */
|
||||
return buf;
|
||||
}
|
||||
|
||||
int skill_sig_option(int *argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
int signo = -1;
|
||||
for (i = 1; i < *argc; i++) {
|
||||
if (argv[i][0] == '-') {
|
||||
signo = signal_name_to_number(argv[i] + 1);
|
||||
if (-1 < signo) {
|
||||
memmove(argv + i, argv + i + 1,
|
||||
sizeof(char *) * (*argc - i));
|
||||
(*argc)--;
|
||||
return signo;
|
||||
}
|
||||
}
|
||||
}
|
||||
return signo;
|
||||
}
|
||||
|
||||
|
||||
/* strtosig is similar to print_given_signals() with exception, that
|
||||
* this function takes a string, and converts it to a signal name or
|
||||
* a number string depending on which way a round conversion is
|
||||
* queried. Non-existing signals return NULL. Notice that the
|
||||
* returned string should be freed after use.
|
||||
*/
|
||||
char *strtosig(const char *restrict s)
|
||||
{
|
||||
char *converted = NULL, *copy, *p, *endp;
|
||||
int i, numsignal = 0;
|
||||
|
||||
copy = strdup(s);
|
||||
if (!copy)
|
||||
xerrx(EXIT_FAILURE, "cannot duplicate string");
|
||||
for (p = copy; *p != '\0'; p++)
|
||||
*p = toupper(*p);
|
||||
p = copy;
|
||||
if (p[0] == 'S' && p[1] == 'I' && p[2] == 'G')
|
||||
p += 3;
|
||||
if (isdigit(*p)){
|
||||
numsignal = strtol(s,&endp,10);
|
||||
if(*endp || endp==s){
|
||||
free(p);
|
||||
return NULL; /* not valid */
|
||||
}
|
||||
}
|
||||
if (numsignal){
|
||||
for (i = 0; i < number_of_signals; i++){
|
||||
if (numsignal == get_sigtable_num(i)){
|
||||
converted = strdup(get_sigtable_name(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < number_of_signals; i++){
|
||||
if (strcmp(p, get_sigtable_name(i)) == 0){
|
||||
converted = malloc(12);
|
||||
if (converted)
|
||||
snprintf(converted, 12, "%d", sigtable[i].num);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(copy);
|
||||
return converted;
|
||||
}
|
||||
|
||||
void unix_print_signals(void)
|
||||
{
|
||||
int pos = 0;
|
||||
int i = 0;
|
||||
while(++i <= number_of_signals){
|
||||
if(i-1) printf("%c", (pos>73)?(pos=0,'\n'):(pos++,' ') );
|
||||
pos += printf("%s", signal_number_to_name(i));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void pretty_print_signals(void)
|
||||
{
|
||||
int i = 0;
|
||||
while(++i <= number_of_signals){
|
||||
int n;
|
||||
n = printf("%2d %s", i, signal_number_to_name(i));
|
||||
if(n>0 && i%7)
|
||||
printf("%s", " \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + n);
|
||||
else
|
||||
printf("\n");
|
||||
}
|
||||
if((i-1)%7) printf("\n");
|
||||
}
|
||||
|
123
lib/strutils.c
123
lib/strutils.c
@ -1,123 +0,0 @@
|
||||
/*
|
||||
* strutils.c - various string routines shared by commands
|
||||
* This file was copied from util-linux at fall 2011.
|
||||
*
|
||||
* Copyright (C) 2010 Karel Zak <kzak@redhat.com>
|
||||
* Copyright (C) 2010 Davidlohr Bueso <dave@gnu.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "c.h"
|
||||
#include "strutils.h"
|
||||
|
||||
/*
|
||||
* same as strtol(3) but exit on failure instead of returning crap
|
||||
*/
|
||||
long strtol_or_err(const char *str, const char *errmesg)
|
||||
{
|
||||
long num;
|
||||
char *end = NULL;
|
||||
|
||||
if (str != NULL && *str != '\0') {
|
||||
errno = 0;
|
||||
num = strtol(str, &end, 10);
|
||||
if (errno == 0 && str != end && end != NULL && *end == '\0')
|
||||
return num;
|
||||
}
|
||||
error(EXIT_FAILURE, errno, "%s: '%s'", errmesg, str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* same as strtod(3) but exit on failure instead of returning crap
|
||||
*/
|
||||
double strtod_or_err(const char *str, const char *errmesg)
|
||||
{
|
||||
double num;
|
||||
char *end = NULL;
|
||||
|
||||
if (str != NULL && *str != '\0') {
|
||||
errno = 0;
|
||||
num = strtod(str, &end);
|
||||
if (errno == 0 && str != end && end != NULL && *end == '\0')
|
||||
return num;
|
||||
}
|
||||
error(EXIT_FAILURE, errno, "%s: '%s'", errmesg, str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Covert a string into a double in a non-locale aware way.
|
||||
* This means the decimal point can be either . or ,
|
||||
* Also means you cannot use the other for thousands separator
|
||||
*
|
||||
* Exits on failure like its other _or_err cousins
|
||||
*/
|
||||
double strtod_nol_or_err(char *str, const char *errmesg)
|
||||
{
|
||||
double num;
|
||||
const char *cp, *radix;
|
||||
double mult;
|
||||
int negative = 0;
|
||||
|
||||
if (str != NULL && *str != '\0') {
|
||||
num = 0.0;
|
||||
cp = str;
|
||||
/* strip leading spaces */
|
||||
while (isspace(*cp))
|
||||
cp++;
|
||||
|
||||
/* get sign */
|
||||
if (*cp == '-') {
|
||||
negative = 1;
|
||||
cp++;
|
||||
} else if (*cp == '+')
|
||||
cp++;
|
||||
|
||||
/* find radix */
|
||||
radix = cp;
|
||||
mult=0.1;
|
||||
while(isdigit(*radix)) {
|
||||
radix++;
|
||||
mult *= 10;
|
||||
}
|
||||
while(isdigit(*cp)) {
|
||||
num += (*cp - '0') * mult;
|
||||
mult /= 10;
|
||||
cp++;
|
||||
}
|
||||
/* got the integers */
|
||||
if (*cp == '\0')
|
||||
return (negative?-num:num);
|
||||
if (*cp != '.' && *cp != ',')
|
||||
error(EXIT_FAILURE, EINVAL, "%s: '%s'", errmesg, str);
|
||||
|
||||
cp++;
|
||||
mult = 0.1;
|
||||
while(isdigit(*cp)) {
|
||||
num += (*cp - '0') * mult;
|
||||
mult /= 10;
|
||||
cp++;
|
||||
}
|
||||
if (*cp == '\0')
|
||||
return (negative?-num:num);
|
||||
}
|
||||
error(EXIT_FAILURE, errno, "%s: '%s'", errmesg, str);
|
||||
return 0;
|
||||
}
|
158
lib/strverscmp.c
158
lib/strverscmp.c
@ -1,158 +0,0 @@
|
||||
/* Compare strings while treating digits characters numerically.
|
||||
Copyright (C) 1997, 2002, 2005 Free Software Foundation, Inc.
|
||||
This file is part of the libiberty library.
|
||||
Contributed by Jean-Fran<61>ois Bignolles <bignolle@ecoledoc.ibp.fr>, 1997.
|
||||
|
||||
Libiberty 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.
|
||||
|
||||
Libiberty 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 the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA. */
|
||||
|
||||
/* #include "libiberty.h" */
|
||||
/* #include "safe-ctype.h" */
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
@deftypefun int strverscmp (const char *@var{s1}, const char *@var{s2})
|
||||
The @code{strverscmp} function compares the string @var{s1} against
|
||||
@var{s2}, considering them as holding indices/version numbers. Return
|
||||
value follows the same conventions as found in the @code{strverscmp}
|
||||
function. In fact, if @var{s1} and @var{s2} contain no digits,
|
||||
@code{strverscmp} behaves like @code{strcmp}.
|
||||
|
||||
Basically, we compare strings normally (character by character), until
|
||||
we find a digit in each string - then we enter a special comparison
|
||||
mode, where each sequence of digits is taken as a whole. If we reach the
|
||||
end of these two parts without noticing a difference, we return to the
|
||||
standard comparison mode. There are two types of numeric parts:
|
||||
"integral" and "fractional" (those begin with a '0'). The types
|
||||
of the numeric parts affect the way we sort them:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
integral/integral: we compare values as you would expect.
|
||||
|
||||
@item
|
||||
fractional/integral: the fractional part is less than the integral one.
|
||||
Again, no surprise.
|
||||
|
||||
@item
|
||||
fractional/fractional: the things become a bit more complex.
|
||||
If the common prefix contains only leading zeroes, the longest part is less
|
||||
than the other one; else the comparison behaves normally.
|
||||
@end itemize
|
||||
|
||||
@smallexample
|
||||
strverscmp ("no digit", "no digit")
|
||||
@result{} 0 // @r{same behavior as strcmp.}
|
||||
strverscmp ("item#99", "item#100")
|
||||
@result{} <0 // @r{same prefix, but 99 < 100.}
|
||||
strverscmp ("alpha1", "alpha001")
|
||||
@result{} >0 // @r{fractional part inferior to integral one.}
|
||||
strverscmp ("part1_f012", "part1_f01")
|
||||
@result{} >0 // @r{two fractional parts.}
|
||||
strverscmp ("foo.009", "foo.0")
|
||||
@result{} <0 // @r{idem, but with leading zeroes only.}
|
||||
@end smallexample
|
||||
|
||||
This function is especially useful when dealing with filename sorting,
|
||||
because filenames frequently hold indices/version numbers.
|
||||
@end deftypefun
|
||||
|
||||
*/
|
||||
|
||||
/* states: S_N: normal, S_I: comparing integral part, S_F: comparing
|
||||
fractional parts, S_Z: idem but with leading Zeroes only */
|
||||
#define S_N 0x0
|
||||
#define S_I 0x4
|
||||
#define S_F 0x8
|
||||
#define S_Z 0xC
|
||||
|
||||
/* result_type: CMP: return diff; LEN: compare using len_diff/diff */
|
||||
#define CMP 2
|
||||
#define LEN 3
|
||||
|
||||
|
||||
/* Compare S1 and S2 as strings holding indices/version numbers,
|
||||
returning less than, equal to or greater than zero if S1 is less than,
|
||||
equal to or greater than S2 (for more info, see the Glibc texinfo doc). */
|
||||
|
||||
int
|
||||
strverscmp (const char *s1, const char *s2)
|
||||
{
|
||||
const unsigned char *p1 = (const unsigned char *) s1;
|
||||
const unsigned char *p2 = (const unsigned char *) s2;
|
||||
unsigned char c1, c2;
|
||||
int state;
|
||||
int diff;
|
||||
|
||||
/* Symbol(s) 0 [1-9] others (padding)
|
||||
Transition (10) 0 (01) d (00) x (11) - */
|
||||
static const unsigned int next_state[] =
|
||||
{
|
||||
/* state x d 0 - */
|
||||
/* S_N */ S_N, S_I, S_Z, S_N,
|
||||
/* S_I */ S_N, S_I, S_I, S_I,
|
||||
/* S_F */ S_N, S_F, S_F, S_F,
|
||||
/* S_Z */ S_N, S_F, S_Z, S_Z
|
||||
};
|
||||
|
||||
static const int result_type[] =
|
||||
{
|
||||
/* state x/x x/d x/0 x/- d/x d/d d/0 d/-
|
||||
0/x 0/d 0/0 0/- -/x -/d -/0 -/- */
|
||||
|
||||
/* S_N */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
|
||||
CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
|
||||
/* S_I */ CMP, -1, -1, CMP, +1, LEN, LEN, CMP,
|
||||
+1, LEN, LEN, CMP, CMP, CMP, CMP, CMP,
|
||||
/* S_F */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
|
||||
CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
|
||||
/* S_Z */ CMP, +1, +1, CMP, -1, CMP, CMP, CMP,
|
||||
-1, CMP, CMP, CMP
|
||||
};
|
||||
|
||||
if (p1 == p2)
|
||||
return 0;
|
||||
|
||||
c1 = *p1++;
|
||||
c2 = *p2++;
|
||||
/* Hint: '0' is a digit too. */
|
||||
state = S_N | ((c1 == '0') + (isdigit (c1) != 0));
|
||||
|
||||
while ((diff = c1 - c2) == 0 && c1 != '\0')
|
||||
{
|
||||
state = next_state[state];
|
||||
c1 = *p1++;
|
||||
c2 = *p2++;
|
||||
state |= (c1 == '0') + (isdigit (c1) != 0);
|
||||
}
|
||||
|
||||
state = result_type[state << 2 | (((c2 == '0') + (isdigit (c2) != 0)))];
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case CMP:
|
||||
return diff;
|
||||
|
||||
case LEN:
|
||||
while (isdigit (*p1++))
|
||||
if (!isdigit (*p2++))
|
||||
return 1;
|
||||
|
||||
return isdigit (*p2) ? -1 : diff;
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "fileutils.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
atexit(close_stdout);
|
||||
printf("Hello, World!\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* test_procps -- program to create a process to test procps
|
||||
*
|
||||
* Copyright 2015 Craig Small <csmall@dropbear.xyz>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#ifdef __linux__
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
#include "c.h"
|
||||
|
||||
#define DEFAULT_SLEEPTIME 300
|
||||
#define MY_NAME "spcorp"
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr, " %s [options]\n", program_invocation_short_name);
|
||||
fprintf(stderr, " -s <seconds>\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
signal_handler(int signum, siginfo_t *siginfo, void *ucontext)
|
||||
{
|
||||
char *signame = NULL;
|
||||
|
||||
switch(signum) {
|
||||
case SIGUSR1:
|
||||
signame = strdup("SIGUSR1");
|
||||
break;
|
||||
case SIGUSR2:
|
||||
signame = strdup("SIGUSR2");
|
||||
break;
|
||||
default:
|
||||
printf("SIG unknown\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (signame == NULL) {
|
||||
printf("SIG malloc error\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
switch (siginfo->si_code) {
|
||||
case SI_USER:
|
||||
printf("SIG %s\n", signame);
|
||||
break;
|
||||
case SI_QUEUE:
|
||||
#ifdef HAVE_SIGINFO_T_SI_INT
|
||||
printf("SIG %s value=%d\n", signame, siginfo->si_int);
|
||||
#else
|
||||
printf("case SI_QUEUE: SIG %s siginfo->si_int undefined\n", signame);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf("Unknown si_code %d\n", siginfo->si_code);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
free(signame);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int sleep_time, opt;
|
||||
struct sigaction signal_action;
|
||||
|
||||
sleep_time = DEFAULT_SLEEPTIME;
|
||||
while ((opt = getopt(argc, argv, "s:")) != -1) {
|
||||
switch(opt) {
|
||||
case 's':
|
||||
sleep_time = atoi(optarg);
|
||||
if (sleep_time < 1) {
|
||||
fprintf(stderr, "sleep time must be 1 second or more\n");
|
||||
usage();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup signal handling */
|
||||
signal_action.sa_sigaction = signal_handler;
|
||||
sigemptyset (&signal_action.sa_mask);
|
||||
signal_action.sa_flags = SA_SIGINFO;
|
||||
sigaction(SIGUSR1, &signal_action, NULL);
|
||||
sigaction(SIGUSR2, &signal_action, NULL);
|
||||
|
||||
#ifdef __linux__
|
||||
/* set process name */
|
||||
prctl(PR_SET_NAME, MY_NAME, NULL, NULL, NULL);
|
||||
#endif
|
||||
|
||||
while (sleep_time > 0) {
|
||||
sleep_time = sleep(sleep_time);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* test_shm -- program to create a shared memory segment for testing
|
||||
*
|
||||
* Copyright 2022 Craig Small <csmall@dropbear.xyz>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/shm.h>
|
||||
#include "c.h"
|
||||
|
||||
#define DEFAULT_SLEEPTIME 300
|
||||
#define SHM_SIZE 50
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr, " %s [options]\n", program_invocation_short_name);
|
||||
fprintf(stderr, " -s <seconds>\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int sleep_time, opt;
|
||||
int shm_id;
|
||||
void *shm_addr;
|
||||
|
||||
sleep_time = DEFAULT_SLEEPTIME;
|
||||
while ((opt = getopt(argc, argv, "s:")) != -1)
|
||||
{
|
||||
switch(opt)
|
||||
{
|
||||
case 's':
|
||||
sleep_time = atoi(optarg);
|
||||
if (sleep_time < 1)
|
||||
{
|
||||
fprintf(stderr, "sleep time must be 1 second or more\n");
|
||||
usage();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
/* get some shared memory */
|
||||
if ( (shm_id = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0666)) < 0)
|
||||
xerr(EXIT_FAILURE, "Unable to shmget()");
|
||||
if ( (shm_addr = shmat(shm_id, NULL, SHM_RDONLY)) < 0)
|
||||
xerr(EXIT_FAILURE, "Unable to shmat()");
|
||||
printf("SHMID: %x\n", shm_id);
|
||||
sleep(sleep_time);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -1,45 +0,0 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "strutils.h"
|
||||
|
||||
struct strtod_tests {
|
||||
char *string;
|
||||
double result;
|
||||
};
|
||||
|
||||
struct strtod_tests tests[] = {
|
||||
{"123", 123.0},
|
||||
{"-123", -123.0},
|
||||
{"12.34", 12.34},
|
||||
{"-12.34", -12.34},
|
||||
{".34", 0.34},
|
||||
{"-.34", -0.34},
|
||||
{"12,34", 12.34},
|
||||
{"-12,34", -12.34},
|
||||
{",34", 0.34},
|
||||
{"-,34", -0.34},
|
||||
{"0", 0.0},
|
||||
{".0", 0.0},
|
||||
{"0.0", 0.0},
|
||||
{NULL, 0.0}
|
||||
};
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
double val;
|
||||
|
||||
for(i=0; tests[i].string != NULL; i++) {
|
||||
if(strtod_nol_or_err(tests[i].string, "Cannot parse number") !=
|
||||
tests[i].result) {
|
||||
fprintf(stderr, "FAIL: strtod_nol_or_err(\"%s\") != %f\n",
|
||||
tests[i].string, tests[i].result);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
//fprintf(stderr, "PASS: strtod_nol for %s\n", tests[i].string);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* test_strutils.c - tests for strutils.c routines
|
||||
* This file was copied from util-linux at fall 2011.
|
||||
*
|
||||
* Copyright (C) 2010 Karel Zak <kzak@redhat.com>
|
||||
* Copyright (C) 2010 Davidlohr Bueso <dave@gnu.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "c.h"
|
||||
#include "strutils.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2) {
|
||||
error(EXIT_FAILURE, 0, "no arguments");
|
||||
} else if (argc < 3) {
|
||||
printf("%ld\n", strtol_or_err(argv[1], "strtol_or_err"));
|
||||
} else {
|
||||
printf("%lf\n", strtod_or_err(argv[2], "strtod_or_err"));
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Reference in New Issue
Block a user