💾 Archived View for thrig.me › tech › openbsd › few.c captured on 2024-12-17 at 12:12:34.
-=-=-=-=-=-=-
// few - a shell that only allows a few programs to be run // // CFLAGS="-ledit -lcurses" make few #include <sys/wait.h> #include <ctype.h> #include <err.h> #include <histedit.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> EditLine *elp; char *prompt(EditLine *e); void resize(int nsig); int runit(const char *arg, int interactive); int main(int argc, char *const *argv) { int ch, status = EXIT_SUCCESS; while ((ch = getopt(argc, argv, "abCefhimnuvxo:c:s")) != -1) { switch (ch) { case 'c': status = runit(optarg, 0); if (status == -1) { exit(EXIT_SUCCESS); } else { exit(status); } } } //argc -= optind; //argv += optind; elp = el_init(getprogname(), stdin, stdout, stderr); if (!elp) err(1, "el_init"); el_parse(elp, argc, (const char **) argv); el_set(elp, EL_EDITOR, "vi"); el_set(elp, EL_PROMPT, prompt); el_set(elp, EL_TERMINAL, NULL); // use $TERM el_source(elp, NULL); // reads ~/.editrc // One may want more complicated control+c handling than this, // but this isn't much of a shell. Complicated things like // pipelines and job control are not offered. signal(SIGINT, SIG_IGN); signal(SIGTSTP, SIG_IGN); signal(SIGWINCH, resize); #ifdef __OpenBSD__ if (pledge("exec proc stdio tty unveil", NULL) == -1) err(1, "pledge"); if (unveil("/usr/libexec/sftp-server", "x") == -1) err(1, "unveil"); if (unveil("/usr/bin/uptime", "x") == -1) err(1, "unveil"); if (unveil(NULL, NULL) == -1) err(1, "unveil"); #endif while (1) { int nchars; const char *line = el_gets(elp, &nchars); if (!line) { if (nchars == -1) err(1, "el_gets"); continue; } if (nchars <= 1) continue; // probably only "\n" status = runit(line, 1); if (status == -1) exit(EXIT_SUCCESS); } el_end(elp); exit(status); } char * prompt(EditLine *e) { return "] "; } void resize(int nsig) { el_resize(elp); } int runit(const char *arg, int interactive) { int status = EXIT_SUCCESS; char *command = strdup(arg); if (!command) err(1, "strdup"); char *cp = command; while (isspace(*cp)) cp++; char *cmd = strsep(&cp, " \f\n\r\t\v"); if (!cmd) goto CLEANUP; if (strcmp(cmd, "exit") == 0) { status = -1; } else if (strcmp(cmd, "/usr/libexec/sftp-server") == 0) { if (interactive) { warnx("use sftp for SFTP access"); status = 42; } else { execl("/usr/libexec/sftp-server", "sftp-server", (char *) 0); err(1, "execl"); } } else if (strcmp(cmd, "uptime") == 0) { pid_t pid = fork(); switch (pid) { case -1: warn("fork"); break; case 0: execl("/usr/bin/uptime", "uptime", (char *) 0); err(1, "execl"); default: wait(&status); } } else { status = 42; } CLEANUP: free(command); return status; }