# read: analogously to write, support reading from in-memory streams in
# addition to file descriptors.
#
# We can pass it either a file descriptor or an address to a stream. If a
# file descriptor is passed in, we _read from it using the right syscall. If a
# stream is passed in (a fake file descriptor), we read from it instead. This
# lets us initialize input for tests.
#
# A little counter-intuitively, the output of 'read' ends up in.. a stream. So
# tests end up doing a redundant copy. Why? Well, consider the alternatives:
#
# a) Reading into a string, and returning a pointer to the end of the read
# region, or a count of bytes written. Now this count or end pointer must be
# managed separately by the caller, which can be error-prone.
#
# b) Having 'read' return a buffer that it allocates. But there's no way to
# know in advance how large to make the buffer. If you read less than the
# size of the buffer you again end up needing to manage initialized vs
# uninitialized memory.
#
# c) Creating more helpful variants like 'read-byte' or 'read-until' which
# also can take a file descriptor or stream, just like 'write'. But such
# primitives don't exist in the Linux kernel, so we'd be implementing them
# somehow, either with more internal buffering or by making multiple
# sysca/*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include "dwm.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
/* static */
static void
bad_malloc(unsigned int size)
{
fprintf(stderr, "fatal: could not malloc() %d bytes\n",
(int) size);
exit(EXIT_FAILURE);
}
/* extern */
void *
emallocz(unsigned int size)
{
void *res = calloc(1, size);
if(!res)
bad_malloc(size);
return res;
}
void
eprint(const char *errstr, ...) {
va_list ap;
va_start(ap, errstr);
vfprintf(stderr, errstr, ap);
va_end(ap);
exit(EXIT_FAILURE);
}
void
spawn(Arg *arg)
{
char **argv = (char **)arg->argv;
if(!argv || !argv[0])
return;
if(fork() == 0) {
if(fork() == 0) {
if(dpy)
close(ConnectionNumber(dpy));
setsid();
execvp(argv[0], argv);
fprintf(stderr, "dwm: execvp %s", argv[0]);
perror(" failed");
}
exit(EXIT_FAILURE);
}
wait(0);
}