mirror of https://github.com/ericonr/purr-c.git
Split platform compatibility code into compat.c.
Also use getentropy() in entropy.c, since it should be available in all platforms. This also cleaned up the error checking in general.
This commit is contained in:
parent
4678f8691b
commit
8a6dadd57e
|
@ -0,0 +1,62 @@
|
|||
#if defined(HAVE_PIPE2) || defined (HAVE_PROG_INVOCATION)
|
||||
#define _GNU_SOURCE /* pipe2 or program_invocation_short_name */
|
||||
#endif /* HAVE_PIPE2 */
|
||||
|
||||
/* pipe_cloexec */
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
/* socket_cloexec */
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
/* program_name */
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
int pipe_cloexec(int fds[2])
|
||||
{
|
||||
#ifdef HAVE_PIPE2
|
||||
// atomic (on newer kernels) application of close-on-exec
|
||||
if (pipe2(fds, O_CLOEXEC) < 0) {
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
// delayed application of close-on-exec
|
||||
if (pipe(fds) < 0) {
|
||||
return 1;
|
||||
}
|
||||
fcntl(fds[0], F_SETFD, FD_CLOEXEC);
|
||||
fcntl(fds[1], F_SETFD, FD_CLOEXEC);
|
||||
#endif /* HAVE_PIPE2 */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int socket_cloexec(int domain, int type, int protocol)
|
||||
{
|
||||
#ifdef HAVE_SOCK_CLOEXEC_H
|
||||
return socket(domain, (type | SOCK_CLOEXEC), protocol);
|
||||
#else
|
||||
int fd = socket(domain, type, protocol);
|
||||
if (fd < 0) {
|
||||
return fd;
|
||||
}
|
||||
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
return fd;
|
||||
#endif /* HAVE_SOCK_CLOEXEC_H */
|
||||
}
|
||||
|
||||
const char *program_name(void)
|
||||
{
|
||||
#ifdef HAVE_PROG_INVOCATION
|
||||
return program_invocation_short_name;
|
||||
#elif HAVE_GETPROGNAME
|
||||
return getprogname();
|
||||
#else
|
||||
#error "no progname impl"
|
||||
#endif /* PROG_INVOCATION & GETPROGNAME */
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef __COMPAT_H_
|
||||
#define __COMPAT_H_
|
||||
|
||||
int pipe_cloexec(int [2]);
|
||||
int socket_cloexec(int, int, int);
|
||||
const char *program_name(void);
|
||||
|
||||
#endif // __COMPAT_H_
|
|
@ -5,31 +5,6 @@ ARGS="${CFLAGS} ${LDFLAGS} -x c -o /dev/null -"
|
|||
|
||||
printf "" > config.mk
|
||||
|
||||
$CC $ARGS <<EOF 2>/dev/null
|
||||
#include <sys/random.h>
|
||||
int main() {
|
||||
ssize_t (*p)(void *, size_t, unsigned int) = getrandom;
|
||||
}
|
||||
EOF
|
||||
[ $? -eq 0 ] && HAVE_GETRANDOM=yes
|
||||
|
||||
$CC $ARGS <<EOF 2>/dev/null
|
||||
#include <stdlib.h>
|
||||
int main() {
|
||||
void (*p)(void *, size_t) = arc4random_buf;
|
||||
}
|
||||
EOF
|
||||
[ $? -eq 0 ] && HAVE_ARC4RANDOM=yes
|
||||
|
||||
echo "HAVE_GETRANDOM:$HAVE_GETRANDOM"
|
||||
echo "HAVE_ARC4RANDOM:$HAVE_ARC4RANDOM"
|
||||
|
||||
if [ "$HAVE_ARC4RANDOM" ]; then
|
||||
echo "DEFS += -DHAVE_ARC4RANDOM" >> config.mk
|
||||
elif [ "$HAVE_GETRANDOM" ]; then
|
||||
echo "DEFS += -DHAVE_GETRANDOM" >> config.mk
|
||||
fi
|
||||
|
||||
$CC $ARGS <<EOF 2>/dev/null
|
||||
#define _GNU_SOURCE /* program_invocation_short_name */
|
||||
#include <errno.h>
|
||||
|
|
17
encrypt.c
17
encrypt.c
|
@ -16,6 +16,7 @@
|
|||
* expected by the other PurritoBin clients.
|
||||
*/
|
||||
|
||||
#define _DEFAULT_SOURCE /* getentropy */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -62,23 +63,15 @@ struct mmap_file encrypt_mmap(struct mmap_file file, uint8_t **keyp, uint8_t **i
|
|||
return rv;
|
||||
}
|
||||
|
||||
ssize_t err = getrandom(key, KEY_LEN, 0);
|
||||
if (err != KEY_LEN) {
|
||||
fputs("getrandom() error!\n", stderr);
|
||||
if (getentropy(key, KEY_LEN) < 0) {
|
||||
perror("getentropy()");
|
||||
return rv;
|
||||
}
|
||||
#ifdef RANDOMIZE_IV
|
||||
#ifdef HAVE_GETRANDOM
|
||||
err = getrandom(iv, IV_LEN, 0);
|
||||
if (err != IV_LEN) {
|
||||
fputs("getrandom() error!\n", stderr);
|
||||
if (getentropy(iv, IV_LEN) < 0) {
|
||||
perror("getentropy()");
|
||||
return rv;
|
||||
}
|
||||
#elif HAVE_ARC4RANDOM
|
||||
arc4random_buf(iv, IV_LEN);
|
||||
#else
|
||||
#error "no random buf impl"
|
||||
#endif /* GETRANDOM & ARC4RANDOM */
|
||||
memcpy(iv_throwaway, iv, IV_LEN);
|
||||
#endif /* RANDOMIZE_IV */
|
||||
|
||||
|
|
2
makefile
2
makefile
|
@ -12,7 +12,7 @@ LDLIBS += -lbearssl
|
|||
LDFLAGS += $(CFLAGS) -Wl,--as-needed
|
||||
|
||||
PURROBJS = socket.o urls.o files.o comm.o formats.o encrypt.o mmap_file.o
|
||||
PURROBJS += read_certs.o gemini.o pager.o
|
||||
PURROBJS += read_certs.o gemini.o pager.o compat.o
|
||||
|
||||
LIBSOBJS = $(PURROBJS)
|
||||
|
||||
|
|
10
meson.build
10
meson.build
|
@ -9,8 +9,6 @@ subdir('po')
|
|||
bearssl = compiler.find_library('bearssl', required: true)
|
||||
|
||||
gnu_source = '#define _GNU_SOURCE'
|
||||
getrandom = compiler.has_header_symbol('sys/random.h', 'getrandom')
|
||||
arc4random = compiler.has_header_symbol('stdlib.h', 'arc4random')
|
||||
gnu_progname = compiler.has_header_symbol(
|
||||
'errno.h',
|
||||
'program_invocation_short_name',
|
||||
|
@ -21,13 +19,6 @@ sock_cloexec = compiler.has_header_symbol('sys/socket.h', 'SOCK_CLOEXEC')
|
|||
pipe2 = compiler.has_header_symbol('unistd.h', 'pipe2', prefix: gnu_source)
|
||||
|
||||
args = []
|
||||
if arc4random
|
||||
args += '-DHAVE_ARC4RANDOM'
|
||||
elif getrandom
|
||||
args += '-DHAVE_GETRANDOM'
|
||||
else
|
||||
error('no random buf impl')
|
||||
endif
|
||||
if bsd_progname
|
||||
args += '-DHAVE_GETPROGNAME'
|
||||
elif gnu_progname
|
||||
|
@ -55,6 +46,7 @@ purrlib = static_library(
|
|||
'formats.c',
|
||||
'encrypt.c',
|
||||
'socket.c',
|
||||
'compat.c',
|
||||
)
|
||||
|
||||
executable('purr', 'purr.c', link_with: purrlib, dependencies: bearssl, install: true)
|
||||
|
|
19
pager.c
19
pager.c
|
@ -1,7 +1,4 @@
|
|||
#define _POSIX_C_SOURCE 200112L /* fdopen, nanosleep */
|
||||
#ifdef HAVE_PIPE2
|
||||
#define _GNU_SOURCE /* pipe2 */
|
||||
#endif /* HAVE_PIPE2 */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -10,9 +7,9 @@
|
|||
#include <spawn.h>
|
||||
#include <time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h> /* O_CLOEXEC or fcntl */
|
||||
|
||||
#include "pager.h"
|
||||
#include "compat.h"
|
||||
|
||||
int launch_pager(struct pager_proc *p)
|
||||
{
|
||||
|
@ -22,20 +19,10 @@ int launch_pager(struct pager_proc *p)
|
|||
|
||||
// using close-on-exec here is safe, because fds created by dup don't
|
||||
// inherit flags
|
||||
#ifdef HAVE_PIPE2
|
||||
// atomic application of close-on-exec
|
||||
if (pipe2(pipes, O_CLOEXEC) < 0) {
|
||||
perror("pipe2()");
|
||||
}
|
||||
#else
|
||||
// delayed application of close-on-exec
|
||||
if (pipe(pipes) < 0) {
|
||||
perror("pipe()");
|
||||
if (pipe_cloexec(pipes)) {
|
||||
perror("pipe_cloexec()");
|
||||
return rv;
|
||||
}
|
||||
fcntl(pipes[0], F_SETFD, FD_CLOEXEC);
|
||||
fcntl(pipes[1], F_SETFD, FD_CLOEXEC);
|
||||
#endif /* HAVE_PIPE2 */
|
||||
|
||||
char *pager = getenv("PAGER");
|
||||
if (pager == NULL || *pager == 0) {
|
||||
|
|
31
purr.c
31
purr.c
|
@ -1,10 +1,4 @@
|
|||
#define _POSIX_C_SOURCE 200112L /* getopt */
|
||||
|
||||
#ifdef HAVE_PROG_INVOCATION
|
||||
#define _GNU_SOURCE /* program_invocation_short_name */
|
||||
#include <errno.h>
|
||||
#endif /* HAVE_PROG_INVOCATION */
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
@ -14,28 +8,27 @@
|
|||
#include <bearssl.h>
|
||||
|
||||
#include "purr.h"
|
||||
#include "compat.h"
|
||||
#include "mmap_file.h"
|
||||
#include "read_certs.h"
|
||||
#include "translation.h"
|
||||
|
||||
const char *progname;
|
||||
|
||||
__attribute__ ((noreturn))
|
||||
static void usage(bool fail)
|
||||
{
|
||||
char *proghelp;
|
||||
if (strcmp(progname, "meow") == 0) {
|
||||
if (strcmp(program_name(), "meow") == 0) {
|
||||
proghelp = _(
|
||||
"Usage: meow [options] <file>\n"
|
||||
" send <file> in encrypted format\n");
|
||||
} else if (strcmp(progname, "meowd") == 0) {
|
||||
} else if (strcmp(program_name(), "meowd") == 0) {
|
||||
proghelp = _(
|
||||
"Usage meowd [options] <url>\n"
|
||||
" receive encrypted file from <url>\n");
|
||||
} else {
|
||||
proghelp = _(
|
||||
"Usage: purr [options] <action> <file>|<url>\n"
|
||||
" action: s[end] | r[ecv]\n");
|
||||
proghelp = _(
|
||||
"Usage: purr [options] <action> <file>|<url>\n"
|
||||
" action: s[end] | r[ecv]\n");
|
||||
}
|
||||
|
||||
FILE *stream = fail ? stderr : stdout;
|
||||
|
@ -71,21 +64,13 @@ int main (int argc, char **argv)
|
|||
bindtextdomain(GETTEXT_PACKAGE, GETTEXT_DIR);
|
||||
textdomain(GETTEXT_PACKAGE);
|
||||
|
||||
#ifdef HAVE_PROG_INVOCATION
|
||||
progname = program_invocation_short_name;
|
||||
#elif HAVE_GETPROGNAME
|
||||
progname = getprogname();
|
||||
#else
|
||||
#error "no progname impl"
|
||||
#endif /* PROG_INVOCATION & GETPROGNAME */
|
||||
|
||||
// check program name:
|
||||
// symlinks to original program with special behavior
|
||||
if (strcmp(progname, "meow") == 0) {
|
||||
if (strcmp(program_name(), "meow") == 0) {
|
||||
// encrypted send mode
|
||||
send = true;
|
||||
encrypt = true;
|
||||
} else if (strcmp(progname, "meowd") == 0) {
|
||||
} else if (strcmp(program_name(), "meowd") == 0) {
|
||||
// encrypted recv mode
|
||||
recv = true;
|
||||
encrypt = true;
|
||||
|
|
19
urls.c
19
urls.c
|
@ -3,28 +3,18 @@
|
|||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef HAVE_SOCK_CLOEXEC_H
|
||||
#include <fcntl.h>
|
||||
#endif /* HAVE_SOCK_CLOEXEC_H */
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "purr.h"
|
||||
#include "compat.h"
|
||||
#include "translation.h"
|
||||
|
||||
#define MAX_DOMAIN_LEN 254
|
||||
#define MAX_SHORTY_LEN 16
|
||||
|
||||
/* enable atomic close-on-exec for socket */
|
||||
#ifdef HAVE_SOCK_CLOEXEC_H
|
||||
#define SOCKET_FLAG SOCK_CLOEXEC
|
||||
#else
|
||||
#define SOCKET_FLAG 0
|
||||
#endif /* HAVE_SOCK_CLOEXEC_H */
|
||||
|
||||
static const char *http_sch = "http://";
|
||||
static const char *https_sch = "https://";
|
||||
static const char *gemini_sch = "gemini://";
|
||||
|
@ -215,14 +205,11 @@ int host_connect(const char *host, const char *port, bool debug)
|
|||
if (debug) fprintf(stderr, "%s: %s\n", _("IP address"), ip_addr);
|
||||
|
||||
// try to establish connection
|
||||
fd = socket(p->ai_family, p->ai_socktype | SOCKET_FLAG, p->ai_protocol);
|
||||
fd = socket_cloexec(p->ai_family, p->ai_socktype, p->ai_protocol);
|
||||
if (fd < 0) {
|
||||
perror("socket()");
|
||||
perror("socket_cloexec()");
|
||||
continue;
|
||||
}
|
||||
#ifndef HAVE_SOCK_CLOEXEC_H
|
||||
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
#endif /* HAVE_SOCK_CLOEXEC_H */
|
||||
|
||||
if (connect(fd, p->ai_addr, p->ai_addrlen) < 0) {
|
||||
// connect errors can be caused server-side
|
||||
|
|
Loading…
Reference in New Issue