blob: b24b987fff951abe094e758ac25cde9c91da7943 [file] [log] [blame]
/* Copyright 2019 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Library for creating subprocesses in a high level manner.
*/
#ifndef VBOOT_REFERENCE_SUBPROCESS_H_
#define VBOOT_REFERENCE_SUBPROCESS_H_
#include <stdio.h>
#include <stdlib.h>
/**
* subprocess_target is the "mini language" of the subprocess
* library. It describes where to read or write data from the process.
*
* There are currently five target of targets:
*
* - TARGET_NULL: /dev/null, no need to describe any other fields.
*
* - TARGET_FD: file descriptor, put the fd in the fd field.
*
* - TARGET_FILE: FILE *, put the FILE pointer in the file field.
*
* - TARGET_BUFFER: read to, or write from, a buffer. Fields:
* - buffer->buf: the buffer
* - buffer->size: the size of that buffer
* - buffer->bytes_consumed: do not fill out this field.
* subprocess_run will set it to the number of bytes read from the
* process (if writing to a buffer). Goes unused when reading from
* a buffer.
*
* - TARGET_BUFFER_NULL_TERMINATED: when reading from a buffer, don't
* fill out the size field and subprocess_run will strlen for you.
* When writing to a buffer, subprocess_run will reserve one byte of
* the size for a null terminator and guarantee that the output is
* always NULL terminated.
*
* - TARGET_CALLBACK: when the target is provided as an input to a
* process, the callback will be called occasionally to provide
* input to the process. The callback should fill buf with up to
* buf_sz bytes of data, and return the number of bytes
* written, or negative values on error. When the target is provided
* as an output to a process, the callback will be called
* occasionally with buf_sz bytes of data from the output put into
* buf. In this case, the return value from the callback is
* ignored except for errors. The data field is for application use
* and will always be passed to the data parameter of the callback
* function.
*/
struct subprocess_target {
enum {
TARGET_NULL,
TARGET_FD,
TARGET_FILE,
TARGET_BUFFER,
TARGET_BUFFER_NULL_TERMINATED,
TARGET_CALLBACK,
} type;
union {
int fd;
FILE *file;
struct {
char *buf;
size_t size;
/*
* This variable is the output of the number of bytes
* read or written. It should be read by the caller, not
* set.
*/
size_t bytes_consumed;
} buffer;
struct {
ssize_t (*cb)(char *buf, size_t buf_sz, void *data);
void *data;
} callback;
};
struct {
int pipefd[2];
} priv;
};
/**
* A convenience subprocess target which uses TARGET_NULL.
*/
extern struct subprocess_target subprocess_null;
/**
* A convenience subprocess target which uses TARGET_FD to STDIN_FILENO.
*/
extern struct subprocess_target subprocess_stdin;
/**
* A convenience subprocess target which uses TARGET_FD to STDOUT_FILENO.
*/
extern struct subprocess_target subprocess_stdout;
/**
* A convenience subprocess target which uses TARGET_FD to STDERR_FILENO.
*/
extern struct subprocess_target subprocess_stderr;
/**
* Call a process and run until completion.
*
* @param argv A NULL-terminated list of arguments describing
* the program to run.
* @param input The subprocess_target connected to stdin.
* @param output The subprocess_target connected to stdout.
* @param error The subprocess_target connected to stderr.
*
* If either input, output, or error are set to NULL, they will be
* &subprocess_stdin, &subprocess_stdout, or &subprocess_stderr
* respectively.
*
* @return The exit status on success, or negative values on error.
*/
int subprocess_run(const char *const argv[],
struct subprocess_target *input,
struct subprocess_target *output,
struct subprocess_target *error);
#endif /* VBOOT_REFERENCE_SUBPROCESS_H_ */