This commit is contained in:
2022-07-19 16:52:28 -04:00
parent 1ba5208e58
commit 9a95b64618
4 changed files with 129 additions and 0 deletions
+88
View File
@@ -0,0 +1,88 @@
#include <ascii.h>
#include <sysexits.h>
#include <sys/wait.h>
#include <unistd.h>
#include "libio.h"
static char *program_name = "pscat";
/* Originally designed to use parentheses but changed to brackets to escape the
* hassle of escaping them from the Bourne shell. */
#define L_PAREN ASCII_LEFT_SQUARE_BRACKET
#define R_PAREN ASCII_RIGHT_SQUARE_BRACKET
/* Test string containing { c, '\0' } without iteration.
* Theoretically saves a little bit of time compared to strcmp(3). */
int
scmpflat(char *s, int c){
return
s[0] != '\0'
&& s[1] == '\0'
&& s[0] == c
;
}
/* Verifies arguments to pscat are sensible. */
int
check_arg(char **argv){
enum {
UNINITIALIZED = 0,
INLPAREN = 1,
NORMAL = 2
} s;
int terms;
for(s = UNINITIALIZED, terms = 0; *argv != NULL; ++argv)
switch(s){
case UNINITIALIZED: case NORMAL:
if(scmpflat(*argv, L_PAREN))
s = INLPAREN;
else
return 0; /* syntax error */
break;
case INLPAREN:
if(scmpflat(*argv, R_PAREN))
{ ++s; ++terms; }
break;
}
return terms;
}
int main(int argc, char *argv[]){
char *argv0;
char **psstart;
int child;
int i;
int retval;
int terms;
argv0 = argv[0] == NULL ? program_name : argv[0];
retval = 0;
if((terms = check_arg(++argv)) == 0){
write(2, "Usage: ", 7);
fdprint(2, argv0);
write(2, " \"[\" [utility [argument...]] \"]\" ...\n", 37);
return EX_USAGE;
}
/* loop starts with *argv -> the next L_PAREN */
for(i = 0; i < terms; ++i){
psstart = ++argv;
while(!scmpflat(*++argv, R_PAREN));
/* *argv -> the corresponding R_PAREN. turn it into NULL to
* terminate the argument list to send to execvp(3) */
*argv = NULL;
if(fork() == 0){
execvp(psstart[0], psstart);
}else
wait(&child);
/* interpret status information from wait(2) */
if(WIFEXITED(child))
retval += WEXITSTATUS(child);
++argv;
}
return retval;
}