Skip to content

Instantly share code, notes, and snippets.

@bachue
Created December 17, 2015 06:30
Show Gist options
  • Save bachue/efb9a554db9fac4bfcad to your computer and use it in GitHub Desktop.
Save bachue/efb9a554db9fac4bfcad to your computer and use it in GitHub Desktop.
As you can see, when you read file in /proc, any error could happen. E.g. When you read the status from a process, you may get ESRCH
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <linux/limits.h>
#define ERROR_PRINTF(fmt, args...) {\
fprintf(stderr, fmt, args); \
_exit(EXIT_FAILURE); \
}
static int open_proc(const pid_t pid) {
int fd;
char path[PATH_MAX + 1];
snprintf(path, PATH_MAX, "/proc/%ld/stat", (long) pid);
path[PATH_MAX] = '\0';
if ((fd = open(path, O_RDONLY)) < 0)
ERROR_PRINTF("Cannot open %s: %s\n", path, strerror(errno));
return fd;
}
static void read_proc(const int fd) {
ssize_t n;
char buf[256];
while((n = read(fd, buf, 256))) {
if (n < 0) {
if (errno == EINTR)
continue;
else
ERROR_PRINTF("Cannot read file %d: %s\n", fd, strerror(errno));
}
if (write(STDOUT_FILENO, buf, n) < 0)
ERROR_PRINTF("Cannot output buf: %s\n", strerror(errno));
}
}
static void ready_for_reread(const int fd) {
if (lseek(fd, 0, SEEK_SET) < 0)
ERROR_PRINTF("Cannot seek file: %s\n", strerror(errno));
}
static pid_t execute_command(char *argv[]) {
pid_t pid;
int dev_null;
switch ((pid = fork())) {
case -1:
ERROR_PRINTF("Cannot fork: %s\n", strerror(errno));
case 0:
if (close(STDIN_FILENO) < 0)
ERROR_PRINTF("Cannot close STDIN: %s\n", strerror(errno));
if ((dev_null = open("/dev/null", O_WRONLY)) < 0)
ERROR_PRINTF("Cannot open /dev/null: %s\n", strerror(errno));
if (dup2(dev_null, STDOUT_FILENO) < 0 || dup2(dev_null, STDERR_FILENO) < 0)
ERROR_PRINTF("Cannot dup /dev/null to STDOUT/STDERR: %s\n", strerror(errno));
execvp(*argv, argv);
ERROR_PRINTF("Cannot exec %s: %s\n", *argv, strerror(errno));
default:
return pid;
}
}
static void wait_command(const pid_t pid) {
// Never mind the command status
if (waitpid(pid, NULL, 0) < 0)
ERROR_PRINTF("Cannot wait command %ld: %s\n", (long) pid, strerror(errno));
}
int main(int argc, char const *argv[]) {
char *command[] = {"find", "/", NULL};
pid_t pid;
int proc_fd;
pid = execute_command(command);
proc_fd = open_proc(pid);
printf("1:\n");
read_proc(proc_fd);
ready_for_reread(proc_fd);
sleep(1);
printf("2:\n");
read_proc(proc_fd);
ready_for_reread(proc_fd);
wait_command(pid);
printf("3:\n");
read_proc(proc_fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment