unix/fiss

src/serdo/serdo.c in master
Repositories | Summary | Log | Files | LICENSE

serdo.c (2684B) download


  1#include "arg.h"
  2#define _GNU_SOURCE
  3
  4#include <ctype.h>
  5#include <fcntl.h>
  6#include <fmt.h>
  7#include <linux/limits.h>
  8#include <stdio.h>
  9#include <stdlib.h>
 10#include <string.h>
 11#include <sys/stat.h>
 12#include <sys/wait.h>
 13#include <unistd.h>
 14
 15#define MAXENV 256
 16
 17const char* current_prog(void) {
 18	return "serdo";
 19}
 20
 21char* envp[MAXENV + 2];
 22int   envc;
 23
 24int continueonerror;
 25
 26extern const struct builtin {
 27	const char* name;
 28	int (*func)(int argv, char** argc);
 29} builtins[];
 30
 31static int spawn(int argc, char** argv) {
 32	pid_t pid;
 33	int   status;
 34
 35	for (const struct builtin* bi = builtins; bi->name; bi++) {
 36		if (!strcmp(argv[0], bi->name))
 37			return bi->func(argc, argv);
 38	}
 39
 40	switch (pid = fork()) {
 41		case -1:
 42			fprint(1, "unable to fork: %r\n");
 43			exit(1);
 44		case 0:
 45			execvpe(argv[0], argv, envp);
 46			fprint(1, "unable to exec: %r\n");
 47			_exit(1);
 48	}
 49
 50	if (waitpid(pid, &status, 0) == -1)
 51		fprint(1, "unable to waid for process: %r\n");
 52
 53	if (!WIFEXITED(status))
 54		return -1;
 55
 56	return WEXITSTATUS(status);
 57}
 58
 59static int doline(char* line, ssize_t line_size) {
 60	int    rc;
 61	int    i          = 0;
 62	int    spacecount = 0;
 63	int    argc       = 0;
 64	char** argv;
 65
 66	while (isspace(line[i])) i++;
 67
 68	if (line[i] == '#')
 69		return 0;
 70
 71	for (int j = i; j < line_size; j++)
 72		if (isspace(line[j])) spacecount++;
 73
 74	argv = malloc((spacecount + 1) * sizeof(char*));
 75
 76	while (i < line_size && line[i] != '\n') {
 77		if (line[i] == '"') {
 78			i++;
 79			argv[argc++] = &line[i];
 80			while (i < line_size && line[i - 1] == '\\' && line[i] != '"') i++;
 81			line[i++] = '\0';
 82		} else if (line[i] == '\'') {
 83			i++;
 84			argv[argc++] = &line[i];
 85			while (i < line_size && line[i - 1] == '\\' && line[i] != '\'') i++;
 86			line[i++] = '\0';
 87		} else {
 88			argv[argc++] = &line[i];
 89			while (i < line_size && !isspace(line[i])) i++;
 90			line[i++] = '\0';
 91		}
 92
 93		while (i < line_size && isspace(line[i])) i++;
 94	}
 95
 96	argv[argc] = NULL;
 97
 98	rc = spawn(argc, argv);
 99	free(argv);
100	return rc;
101}
102
103int execute(FILE* file) {
104	int     rc         = 0;
105	char*   line       = NULL;
106	size_t  line_alloc = 0;
107	ssize_t line_size;
108
109	while ((line_size = getline(&line, &line_alloc, file)) > 0) {
110		if ((rc = doline(line, line_size)) && !continueonerror)
111			break;
112	}
113	if (line)
114		free(line);
115
116	return rc;
117}
118
119int main(int argc, char* argv[], char* env[]) {
120	FILE* f;
121	(void) argc;
122
123	for (envc = 0; envc < MAXENV && env[envc]; ++envc)
124		envp[envc] = env[envc];
125
126	envp[envc] = 0;
127
128	SHIFT(1);
129
130	if (argc > 1 && !strcmp(*argv, "-c")) {
131		continueonerror = 1;
132		SHIFT(1);
133	}
134
135	if (argc > 1) {
136		if (!(f = fopen(*argv, "r"))) {
137			fprint(1, "unable to open %s: %r\n", *argv);
138			return 1;
139		}
140	} else
141		f = stdin;
142
143	return execute(f);
144}