1.1 --- a/fsaccess/fsaccess.c Thu Jan 11 19:24:44 2024 +0100
1.2 +++ b/fsaccess/fsaccess.c Thu Jan 11 19:25:29 2024 +0100
1.3 @@ -1,7 +1,7 @@
1.4 /*
1.5 * Access a filesystem.
1.6 *
1.7 - * Copyright (C) 2019, 2022 Paul Boddie <paul@boddie.org.uk>
1.8 + * Copyright (C) 2019, 2022, 2024 Paul Boddie <paul@boddie.org.uk>
1.9 *
1.10 * This program is free software; you can redistribute it and/or
1.11 * modify it under the terms of the GNU General Public License as
1.12 @@ -50,7 +50,7 @@
1.13 \n\
1.14 Script operations:\n\
1.15 \n\
1.16 - script Read operations from a script file\n\
1.17 + script Read operations from a script file (or stdin)\n\
1.18 ";
1.19
1.20 /* Operations exposed by the program. */
2.1 --- a/fsaccess/input.c Thu Jan 11 19:24:44 2024 +0100
2.2 +++ b/fsaccess/input.c Thu Jan 11 19:25:29 2024 +0100
2.3 @@ -1,7 +1,7 @@
2.4 /*
2.5 * Elementary input utilities.
2.6 *
2.7 - * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
2.8 + * Copyright (C) 2022, 2024 Paul Boddie <paul@boddie.org.uk>
2.9 *
2.10 * This program is free software; you can redistribute it and/or
2.11 * modify it under the terms of the GNU General Public License as
2.12 @@ -19,74 +19,28 @@
2.13 * Boston, MA 02110-1301, USA
2.14 */
2.15
2.16 +#include <stdio.h>
2.17 #include <string.h>
2.18
2.19 #include "input.h"
2.20
2.21
2.22
2.23 -/* Read a line from a file into the given buffer. */
2.24 -
2.25 -char *read_line(FILE *fp, struct read_line_state *state)
2.26 -{
2.27 - size_t nread;
2.28 -
2.29 - do
2.30 - {
2.31 - do
2.32 - {
2.33 - /* Search for a newline character in any available text. */
2.34 +/* Read a line from a file into the given buffer, removing any newline. */
2.35
2.36 - if (state->end > state->start)
2.37 - {
2.38 - state->eolp = strchr(state->start, '\n');
2.39 -
2.40 - if (state->eolp != NULL)
2.41 - {
2.42 - *(state->eolp) = '\0';
2.43 - return state->eolp;
2.44 - }
2.45 - }
2.46 -
2.47 - /* Obtain more text if necessary. */
2.48 -
2.49 - nread = fread(state->end, sizeof(char), state->remaining, fp);
2.50 -
2.51 - /* Handle end of file condition. */
2.52 +char *read_line(FILE *fp, char *buffer, size_t bufsize)
2.53 +{
2.54 + char *last;
2.55
2.56 - if (!nread)
2.57 - {
2.58 - if (state->end > state->start)
2.59 - return state->end;
2.60 - else
2.61 - return NULL;
2.62 - }
2.63 + if (fgets(buffer, bufsize, fp) == NULL)
2.64 + return NULL;
2.65
2.66 - /* Zero-terminate the string for searching. */
2.67 -
2.68 - *(state->end + nread) = '\0';
2.69 -
2.70 - /* Advance the end of string and subtract remaining space. */
2.71 + last = buffer + strlen(buffer) - 1;
2.72
2.73 - state->end += nread;
2.74 - state->remaining -= nread;
2.75 - }
2.76 - while (state->remaining);
2.77 -
2.78 - /* Copy the remaining text to the start of the buffer. */
2.79 + if ((last >= buffer) && (*last == '\n'))
2.80 + *last = '\0';
2.81
2.82 - if (state->start > state->buffer)
2.83 - {
2.84 - strcpy(state->buffer, state->start);
2.85 -
2.86 - state->end -= (state->start - state->buffer);
2.87 - state->start = state->buffer;
2.88 - state->remaining = state->buffer_size - 1 - (state->end - state->buffer);
2.89 - }
2.90 - }
2.91 - while (state->remaining);
2.92 -
2.93 - return NULL;
2.94 + return buffer;
2.95 }
2.96
2.97 /* Parse the text in the given region, returning details of arguments. */
3.1 --- a/fsaccess/input.h Thu Jan 11 19:24:44 2024 +0100
3.2 +++ b/fsaccess/input.h Thu Jan 11 19:25:29 2024 +0100
3.3 @@ -1,7 +1,7 @@
3.4 /*
3.5 * Elementary input utilities.
3.6 *
3.7 - * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
3.8 + * Copyright (C) 2022, 2024 Paul Boddie <paul@boddie.org.uk>
3.9 *
3.10 * This program is free software; you can redistribute it and/or
3.11 * modify it under the terms of the GNU General Public License as
3.12 @@ -23,16 +23,10 @@
3.13
3.14 #include <stdio.h>
3.15
3.16 -struct read_line_state
3.17 -{
3.18 - char *buffer, *start, *end, *eolp;
3.19 - size_t buffer_size, remaining;
3.20 -};
3.21 -
3.22 void parse_line(char *start, char *end, int *num_args, char *args[],
3.23 const int max_args);
3.24
3.25 -char *read_line(FILE *fp, struct read_line_state *state);
3.26 +char *read_line(FILE *fp, char *buffer, size_t bufsize);
3.27
3.28 /* vim: tabstop=4 expandtab shiftwidth=4
3.29 */
4.1 --- a/fsaccess/op_list_objects.c Thu Jan 11 19:24:44 2024 +0100
4.2 +++ b/fsaccess/op_list_objects.c Thu Jan 11 19:25:29 2024 +0100
4.3 @@ -107,28 +107,42 @@
4.4 return 0;
4.5 }
4.6
4.7 +/* List an object in the filesystem image. */
4.8 +
4.9 +static int list_object(const char *path)
4.10 +{
4.11 + /* Emit each object's name. */
4.12 +
4.13 + puts(path);
4.14 +
4.15 + /* List individual files or directories. */
4.16 +
4.17 + if (_list_object(path))
4.18 + {
4.19 + fprintf(stderr, "Failed to list object: %s\n", path);
4.20 + return 1;
4.21 + }
4.22 +
4.23 + return 0;
4.24 +}
4.25 +
4.26 /* List objects in the filesystem image. */
4.27
4.28 int list_objects(int argc, char *argv[])
4.29 {
4.30 int i;
4.31 - char *path;
4.32 +
4.33 + /* List the top level without any argument. */
4.34 +
4.35 + if (!argc)
4.36 + return list_object("");
4.37 +
4.38 + /* Otherwise, list all specified objects. */
4.39
4.40 for (i = 0; i < argc; i++)
4.41 {
4.42 - path = argv[i];
4.43 -
4.44 - /* Emit each object. */
4.45 -
4.46 - puts(path);
4.47 -
4.48 - /* List individual files or directories. */
4.49 -
4.50 - if (_list_object(path))
4.51 - {
4.52 - fprintf(stderr, "Failed to list object: %s\n", path);
4.53 + if (list_object(argv[i]))
4.54 return 1;
4.55 - }
4.56 }
4.57
4.58 return 0;
5.1 --- a/fsaccess/op_script.c Thu Jan 11 19:24:44 2024 +0100
5.2 +++ b/fsaccess/op_script.c Thu Jan 11 19:25:29 2024 +0100
5.3 @@ -1,7 +1,7 @@
5.4 /*
5.5 * Run a script accessing a filesystem.
5.6 *
5.7 - * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
5.8 + * Copyright (C) 2022, 2024 Paul Boddie <paul@boddie.org.uk>
5.9 *
5.10 * This program is free software; you can redistribute it and/or
5.11 * modify it under the terms of the GNU General Public License as
5.12 @@ -43,38 +43,51 @@
5.13 {
5.14 FILE *fp;
5.15 char buffer[BUFSIZE];
5.16 - struct read_line_state state;
5.17 enum op_results op_result;
5.18 int num_args;
5.19 char *args[MAX_ARGS];
5.20 - int i;
5.21 + int i, use_stdin;
5.22
5.23 for (i = 0; i < argc; i++)
5.24 {
5.25 - fp = fopen(argv[i], "r");
5.26 + /* Test for standard input as a special filename. */
5.27 +
5.28 + use_stdin = !strcmp(argv[i], "-");
5.29 +
5.30 + if (use_stdin)
5.31 + fp = stdin;
5.32 + else
5.33 + fp = fopen(argv[i], "r");
5.34 +
5.35 + while (1)
5.36 + {
5.37 + /* Show a prompt if employing standard input. */
5.38
5.39 - state.buffer = buffer;
5.40 - state.start = buffer;
5.41 - state.end = buffer;
5.42 - state.buffer_size = BUFSIZE;
5.43 - state.remaining = BUFSIZE - 1;
5.44 + if (use_stdin)
5.45 + printf("> ");
5.46 +
5.47 + /* Read and parse the input line, running any specified command. */
5.48
5.49 - while (read_line(fp, &state) != NULL)
5.50 - {
5.51 - parse_line(state.start, state.eolp, &num_args, args, MAX_ARGS);
5.52 + if (read_line(fp, buffer, BUFSIZE) == NULL)
5.53 + break;
5.54
5.55 - if (num_args > 1)
5.56 + parse_line(buffer, buffer + strlen(buffer), &num_args, args, MAX_ARGS);
5.57 +
5.58 + /* Permit commands with and without arguments. */
5.59 +
5.60 + if (num_args >= 1)
5.61 {
5.62 op_result = run_operation(args[0], num_args - 1, &args[1]);
5.63
5.64 - if (handle_op_result(args[0], op_result))
5.65 + if (handle_op_result(args[0], op_result) && !use_stdin)
5.66 return 1;
5.67 }
5.68 -
5.69 - state.start = state.eolp + 1;
5.70 }
5.71
5.72 - fclose(fp);
5.73 + /* Close normal files. */
5.74 +
5.75 + if (!use_stdin)
5.76 + fclose(fp);
5.77 }
5.78
5.79 return 0;