aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2024-07-11 16:03:13 -0400
committerB. Watson <urchlay@slackware.uk>2024-07-11 16:03:13 -0400
commit2ffb4dcd0e788a68b9089f02838f4bba0b79dd2c (patch)
tree23e780fbed8e4ed1b0e0d83a43460a1f80666570
parent1073c3969f5b79ada9ca8148f07cef6912432a2e (diff)
downloadbw-atari8-tools-2ffb4dcd0e788a68b9089f02838f4bba0b79dd2c.tar.gz
whichbas: initial support for multiple files on the command line.
-rw-r--r--whichbas.c86
1 files changed, 81 insertions, 5 deletions
diff --git a/whichbas.c b/whichbas.c
index aeb18f6..80ea507 100644
--- a/whichbas.c
+++ b/whichbas.c
@@ -4,6 +4,7 @@
#include <string.h>
#include <ctype.h>
#include <time.h>
+#include <sys/wait.h>
#include "bas.h"
@@ -42,17 +43,84 @@ unsigned char last_op_tok;
unsigned short last_cmd_pos;
void print_help(void) {
- printf("Usage: %s [-v] [-k] [-s] <inputfile>\n", self);
+ printf("Usage: %s [-v] [-h] [-k] [-s] <inputfile> ...\n", self);
+}
+
+int child_errs = 0;
+
+/* return true if the child ran and returned 0 (success) */
+int spawn_child(const char **args) {
+ pid_t pid, status;
+ int wstatus;
+
+ pid = fork();
+ if(pid == -1) {
+ perror("fork()");
+ die("Can't spawn child process");
+ } else if(pid) {
+ /* we are the parent */
+ status = waitpid(pid, &wstatus, 0);
+ if(status < 0) {
+ perror("waitpid()");
+ die("Child process went south");
+ }
+ if(! (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0) ) {
+ child_errs++;
+ return 0;
+ }
+ } else {
+ /* we are the child */
+ if(execv(args[0], (char * const *)args) < 0) {
+ perror("exec()");
+ exit(1);
+ }
+ }
+
+ return 1;
+}
+
+/* this is not the ideal way to handle multiple files. it forks a new
+ process for each one. however, I embedded a bunch of die() calls
+ in bas.c, thinking I'd never use some of the functions more than once
+ in the same run. what I get for trying to KISS... */
+void multiple_files(const char *argv0, char **list) {
+ const char *args[5]; /* 5 because eventually we include -k and/or -v */
+ int kidstat;
+
+ /* this isn't needed for things to work, but if I write buggy code,
+ it avoids a forkbomb. */
+ setenv("WHICHBAS_MULTI_PARANOIA", "1", 1);
+
+ args[0] = argv0;
+ args[2] = NULL;
+
+ while(*list) {
+ args[1] = *list;
+ printf("%s:\t", *list);
+ fflush(stdout);
+ kidstat = spawn_child(args);
+ if(!kidstat) puts("(detection failed)");
+ fflush(stdout);
+ list++;
+ }
+
+ if(child_errs) {
+ fprintf(stderr, "%s: exiting with error status because some files failed.\n", self);
+ exit(1);
+ } else {
+ exit(0);
+ }
}
void parse_args(int argc, char **argv) {
int opt;
- while( (opt = getopt(argc, argv, "vks")) != -1) {
+ while( (opt = getopt(argc, argv, "vksh")) != -1) {
switch(opt) {
case 'v': verbose = 1; break;
case 'k': keep_going = verbose = 1; break;
case 's': script_mode = 1; break;
+ case 'h': print_help(); exit(0);
default:
print_help();
exit(1);
@@ -61,10 +129,18 @@ void parse_args(int argc, char **argv) {
if(optind >= argc)
die("No input file given (and stdin not supported).");
- else
+
+ if(optind == argc - 1) { /* got one filename only */
open_input(argv[optind]);
- if(input_file == stdin)
- die("Reading from standard input not supported.");
+ if(input_file == stdin)
+ die("Reading from standard input not supported.");
+ } else { /* got multiple filenames */
+ if(keep_going || verbose || script_mode)
+ die("-k, -v, -s not supported with multiple filenames (yet?)");
+ if(getenv("WHICHBAS_MULTI_PARANOIA"))
+ die("BUG: multiple_files() recursion!");
+ multiple_files(argv[0], argv + optind);
+ }
}
/* don't need this.