X-Git-Url: https://git.cworth.org/git?p=tar;a=blobdiff_plain;f=rmt%2Frmt.c;fp=rmt%2Frmt.c;h=fff83b87a57402e048b0cded6732de0d9f84fbd3;hp=a3897eb56f0fc06d91417d8d92ff373d4c44a60f;hb=b414e25de8ca49d7567a92c203d431383ec57c83;hpb=29ece34f44a27750bbfd76154ad9882580453dc7 diff --git a/rmt/rmt.c b/rmt/rmt.c index a3897eb..fff83b8 100644 --- a/rmt/rmt.c +++ b/rmt/rmt.c @@ -61,7 +61,7 @@ FILE *dbgout; } \ } \ while (0) - + static void @@ -74,13 +74,13 @@ trimnl (char *str) str[len-1] = 0; } } - + char *input_buf_ptr = NULL; size_t input_buf_size = 0; -char * +static char * rmt_read (void) { ssize_t rc = getline (&input_buf_ptr, &input_buf_size, stdin); @@ -94,32 +94,34 @@ rmt_read (void) return NULL; } -void +static void rmt_write (const char *fmt, ...) { va_list ap; va_start (ap, fmt); vfprintf (stdout, fmt, ap); + fflush (stdout); VDEBUG (10, "S: ", fmt, ap); } -void +static void rmt_reply (uintmax_t code) { char buf[UINTMAX_STRSIZE_BOUND]; rmt_write ("A%s\n", umaxtostr (code, buf)); } -void +static void rmt_error_message (int code, const char *msg) { DEBUG1 (10, "S: E%d\n", code); DEBUG1 (10, "S: %s\n", msg); DEBUG1 (1, "error: %s\n", msg); fprintf (stdout, "E%d\n%s\n", code, msg); + fflush (stdout); } -void +static void rmt_error (int code) { rmt_error_message (code, strerror (code)); @@ -152,7 +154,7 @@ struct rmt_kw #define RMT_KW(s,v) { #s, sizeof (#s) - 1, v } -int +static int xlat_kw (const char *s, const char *pfx, struct rmt_kw const *kw, int *valp, const char **endp) { @@ -167,7 +169,7 @@ xlat_kw (const char *s, const char *pfx, slen -= pfxlen; } } - + for (; kw->name; kw++) { if (slen >= kw->len @@ -182,7 +184,7 @@ xlat_kw (const char *s, const char *pfx, return 1; } -const char * +static const char * skip_ws (const char *s) { while (*s && c_isblank (*s)) @@ -222,47 +224,60 @@ static struct rmt_kw const open_flag_kw[] = { NULL } }; -int +static int decode_open_flag (const char *mstr, int *pmode) { + int numeric_mode = 0; int mode = 0; + const char *p; - while (mstr) + mstr = skip_ws (mstr); + if (c_isdigit (*mstr)) { - int v; - const char *p; - - mstr = skip_ws (mstr); - if (*mstr == 0) - break; - else if (c_isdigit (*mstr)) - v = strtol (mstr, (char**) &p, 10); - else if (xlat_kw (mstr, "O_", open_flag_kw, &v, &p)) - { - rmt_error_message (EINVAL, "invalid open mode"); - return 1; - } + numeric_mode = strtol (mstr, (char**) &p, 10); + mstr = skip_ws (p); + } - mode |= v; - - if (*p && c_isblank (*p)) - p = skip_ws (p); - if (*p == 0) - break; - else if (*p == '|') - { - /* FIXMEL - if (p[1] == 0) - rmt_error_message (EINVAL, "invalid open mode"); - */ - mstr = p + 1; - } - else + if (*mstr) + { + while (mstr) { - rmt_error_message (EINVAL, "invalid open mode"); - return 1; + int v; + + mstr = skip_ws (mstr); + if (*mstr == 0) + break; + else if (c_isdigit (*mstr)) + v = strtol (mstr, (char**) &p, 10); + else if (xlat_kw (mstr, "O_", open_flag_kw, &v, &p)) + { + rmt_error_message (EINVAL, "invalid open mode"); + return 1; + } + + mode |= v; + + if (*p && c_isblank (*p)) + p = skip_ws (p); + if (*p == 0) + break; + else if (*p == '|') + { + /* FIXMEL + if (p[1] == 0) + rmt_error_message (EINVAL, "invalid open mode"); + */ + mstr = p + 1; + } + else + { + rmt_error_message (EINVAL, "invalid open mode"); + return 1; + } } } + else + mode = numeric_mode; *pmode = mode; return 0; } @@ -271,12 +286,12 @@ decode_open_flag (const char *mstr, int *pmode) /* Syntax ------ O\n\n - + Function -------- Opens the with given . If a device had already been opened, it is closed before opening the new one. - + Arguments --------- - name of the device to open. @@ -288,22 +303,26 @@ decode_open_flag (const char *mstr, int *pmode) 64|512 CREAT|TRUNC + In addition, a compined form is also allowed, i.e. a decimal mode followed + by its symbolic representation. In this case the symbolic representation + is given preference. + Reply ----- - A0\n on success, E\n\n on error. - + A0\n on success, E0\n\n on error. + Extensions ---------- - The BSD version allows only decimal number as . + BSD version allows only decimal number as */ - + static void open_device (char *str) { char *device = xstrdup (str); char *flag_str; int flag; - + flag_str = rmt_read (); if (!flag_str) { @@ -327,7 +346,7 @@ open_device (char *str) /* Syntax ------ C[]\n - + Function -------- Close the currently open device. @@ -335,13 +354,13 @@ open_device (char *str) Arguments --------- Any arguments are silently ignored. - + Reply ----- - A0\n on success, E\n\n on error. + A0\n on success, E0\n\n on error. */ static void -close_device () +close_device (void) { if (close (device_fd) < 0) rmt_error (errno); @@ -355,12 +374,12 @@ close_device () /* Syntax ------ L\n\n - + Function -------- Perform an lseek(2) on the currently open device with the specified parameters. - + Arguments --------- - Where to measure offset from. Valid values are: @@ -370,11 +389,11 @@ close_device () Reply ----- A\n on success. The is the new offset in file. - E\n\n on error. + E0\n\n on error. Extensions ---------- - The BSD version allows only 0,1,2 as . + BSD version allows only 0,1,2 as . */ static struct rmt_kw const seek_whence_kw[] = @@ -384,15 +403,15 @@ static struct rmt_kw const seek_whence_kw[] = RMT_KW(END, SEEK_END), { NULL } }; - -void + +static void lseek_device (const char *str) { char *p; int whence; off_t off; uintmax_t n; - + if (str[0] && str[1] == 0) { switch (str[0]) @@ -427,7 +446,7 @@ lseek_device (const char *str) rmt_error_message (EINVAL, N_("Invalid seek offset")); return; } - + if (n != off || errno == ERANGE) { rmt_error_message (EINVAL, N_("Seek offset out of range")); @@ -444,37 +463,37 @@ lseek_device (const char *str) /* Syntax ------ R\n - + Function -------- Read bytes of data from the current device. - + Arguments --------- - number of bytes to read. - + Reply ----- On success: A\n, followed by bytes of data read from the device. - On error: E\n\n + On error: E0\n\n */ -void +static void read_device (const char *str) { char *p; size_t size; uintmax_t n; size_t status; - + n = size = strtoumax (str, &p, 10); if (*p) { rmt_error_message (EINVAL, N_("Invalid byte count")); return; } - + if (n != size || errno == ERANGE) { rmt_error_message (EINVAL, N_("Byte count out of range")); @@ -495,37 +514,37 @@ read_device (const char *str) /* Syntax ------ W\n followed by bytes of input data. - + Function -------- Write data onto the current device. - + Arguments --------- - number of bytes. - + Reply ----- On success: A\n, where is number of bytes actually written. - On error: E\n\n + On error: E0\n\n */ -void +static void write_device (const char *str) { char *p; size_t size; uintmax_t n; size_t status; - + n = size = strtoumax (str, &p, 10); if (*p) { rmt_error_message (EINVAL, N_("Invalid byte count")); return; } - + if (n != size || errno == ERANGE) { rmt_error_message (EINVAL, N_("Byte count out of range")); @@ -552,30 +571,30 @@ write_device (const char *str) /* Syntax ------ I\n\n - + Function -------- Perform a MTIOCOP ioctl(2) command using the specified paramedters. - + Arguments --------- - MTIOCOP operation code. - mt_count. - + Reply ----- On success: A0\n - On error: E\n\n + On error: E0\n\n */ -void +static void iocop_device (const char *str) { char *p; long opcode; off_t count; uintmax_t n; - + opcode = strtol (str, &p, 10); if (*p) { @@ -589,13 +608,13 @@ iocop_device (const char *str) rmt_error_message (EINVAL, N_("Invalid byte count")); return; } - + if (n != count || errno == ERANGE) { rmt_error_message (EINVAL, N_("Byte count out of range")); return; } - + #ifdef MTIOCTOP { struct mtop mtop; @@ -621,23 +640,23 @@ iocop_device (const char *str) /* Syntax ------ S\n - + Function -------- Return the status of the open device, as obtained with a MTIOCGET ioctl call. - + Arguments --------- None - + Reply ----- On success: A\n followed by bytes of data. - On error: E\n\n + On error: E0\n\n */ -void +static void status_device (const char *str) { if (*str) @@ -661,7 +680,7 @@ status_device (const char *str) rmt_error_message (ENOSYS, N_("Operation not supported")); #endif } - + const char *argp_program_version = "rmt (" PACKAGE_NAME ") " VERSION; @@ -689,13 +708,13 @@ parse_opt (int key, char *arg, struct argp_state *state) case 'd': dbglev = strtol (arg, NULL, 0); break; - + case DEBUG_FILE_OPTION: dbgout = fopen (arg, "w"); if (!dbgout) error (EXIT_FAILURE, errno, _("cannot open %s"), arg); break; - + case ARGP_KEY_FINI: if (dbglev) { @@ -705,13 +724,13 @@ parse_opt (int key, char *arg, struct argp_state *state) else if (dbgout) dbglev = 1; break; - + default: return ARGP_ERR_UNKNOWN; } return 0; } - + static struct argp argp = { options, parse_opt, @@ -742,7 +761,7 @@ main (int argc, char **argv) char *buf; int idx; int stop = 0; - + set_program_name (argv[0]); argp_version_setup ("rmt", rmt_authors); @@ -752,7 +771,7 @@ main (int argc, char **argv) bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); } - + if (argp_parse (&argp, argc, argv, ARGP_IN_ORDER, &idx, NULL)) exit (EXIT_FAILURE); if (idx != argc) @@ -764,7 +783,7 @@ main (int argc, char **argv) error (EXIT_FAILURE, errno, _("cannot open %s"), argv[idx]); dbglev = 1; } - + while (!stop && (buf = rmt_read ()) != NULL) { switch (buf[0]) @@ -773,36 +792,36 @@ main (int argc, char **argv) close_device (); stop = 1; break; - + case 'I': iocop_device (buf + 1); break; - + case 'L': lseek_device (buf + 1); break; - + case 'O': open_device (buf + 1); break; - + case 'R': read_device (buf + 1); break; - + case 'S': status_device (buf + 1); break; - + case 'W': write_device (buf + 1); break; - + default: DEBUG1 (1, "garbage input %s\n", buf); rmt_error_message (EINVAL, N_("Garbage command")); return EXIT_FAILURE; /* exit status used to be 3 */ - } + } } if (device_fd >= 0) close_device ();