Re: [PATCH 2/3] more: support for long options

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Jan 30, 2011 at 08:38:25PM +0100, Sami Kerola wrote:
> This fix will also introduce warning. More has been setting
> option --no-scroll on if binary is has been called `page'. Since
> this was not documented, and rather well hide to the source, the
> functionality should be removed in future.

 I don't think that we need the warning here. The feature is there for
 years and would be better to improve documentation than print an
 unexpected warning.

> Environment variable PAGE is after this commit examined by

 $MORE

> getopt_long, which will mean that some previously broken ways to
> execute the command now work. For example one bellow.
> 
> MORE='+10' more /etc/services

[...]

> +char short_opt_lines[] = "--lines";

 why not:

  char *short_opt_lines = "--lines";

> +char short_opt_start_line[] = "--start-line";
> +char short_opt_search[] = "--search";
> +	fprintf(out,
> +		_("Options:\n"
> +		  "  -d,   --visible-bell       display help instead of ring bell \n"
> +		  "  -f,   --logical-count      count logical, rather than screen lines\n"
> +		  "  -l,   --ignore-form-feed   suppress pause after form feed\n"
> +		  "  -p,   --no-scroll          suppress scroll, clean screen and disblay text\n"
> +		  "  -c,   --clean-ends         suppress scroll, display text and clean line ends\n"
> +		  "  -u,   --no-underlining     suppress underlining\n"
> +		  "  -s,   --squeeze            squeeze multiple blank lines into one\n"
> +		  "  -NUM, --lines=NUM          set number of screen lines\n"

 more(1) is also described in POSIX and there is suggested -n <NUM>,
 maybe we can support all three formats (-NUM, -n NUM, --lines NUM)

> +		  "  +NUM, --start-line=NUM     display beginning from line number NUM\n"

 Please, don't use '=' in the usage string, use:

          "  -n, -NUM, --lines NUM      set number of screen lines\n"
 or so.

> +		  "  +/STRING, --search=STRING  display beginning where search match\n"
> +		  "        --help               display this help and exit \n"
> +		  "        --version            output version information and exit\n"));

 Seems like FSFism :-) I think we can use '-h' for help and maybe -v
 or -V for version.

> +int getoptify_old_format(char *argv, char **new_argv, int new_argc, int *new_argc_optsp, int *old_opt_formatp) {

 I don't understand why we need new_argc_optsp and old_opt_formatp
 pointers. What about:

    add_argv_option(char *option, char **argv, int *argc)

 and all without unnecessary new_ prefix.

> +    if (argv[0] == '+') {
> +	if (argv[1] == '/') {
> +	    new_argv[new_argc] = (char *) &short_opt_search;
> +	    new_argc++;
> +	    new_argv[new_argc] = (char *) &argv[2];
> +	    new_argc++;
> +	    ++*old_opt_formatp;
> +	} else {
> +	    new_argv[new_argc] = (char *) &short_opt_start_line;
> +	    new_argc++;
> +	    new_argv[new_argc] = (char *) &argv[1];
> +	    new_argc++;
> +	    ++*old_opt_formatp;
> +	}
> +    } else if (argv[0] == '-' && isdigit(argv[1])) {
> +	new_argv[new_argc] = (char *) &short_opt_lines;
> +	new_argc++;
> +	new_argv[new_argc] = (char *) &argv[1];
> +	new_argc++;
> +    } else {
> +	new_argv[new_argc] = argv;
> +	new_argc++;
> +    }
> +
> +    ++*new_argc_optsp;
> +    return(new_argc);

  return new_argc;

the returns is not function

> +    if (!(strcmp(program_invocation_short_name, "page"))) {
> +	warnx(_("option --no-scroll is set because the binary has name `page'"));
> +	noscroll++;
> +    }

 Please, remove the warning.

> +    /* FIXME make fully dynamic; think about linux/limits.h ARG_MAX */
> +    new_argv = (char **) xmalloc(sizeof(char *) * 256);

 the size of the new_argv is
    + current argv
    + number of strings in $MORE
    + 6 (-NUM, +NUM, +/STRING  are translated to two new options (e.g. "-n" "NUM")

> +    new_argc_optsp = &new_argc_opts;
> +    old_opt_formatp = &old_opt_format;

 It would be better to move all this crazy stuff around argv[] outside
 main(). It's more readable if there is getopt stuff in main() only.

  argv = prepare_argv(argv, &argc);

  while ((c = getopt_long(argc, argv, ..........))) {
    ...
  }

> +
> +    /* Convert environment string to look like option from
> +     * command line. */
> +    s = getenv("MORE");

 if (s)
     s = xstrdup(s);

> +    if (s != NULL) {
> +	int i;
> +	i = 0;
> +	while (s[0] != '\0' && new_argc < 256) {
> +	    if(isblank(s[0])) {
> +		s[0] = '\0';

 man getenv:

 As typically implemented, getenv() returns a pointer to a string
 within the environment list. The caller must take care not to modify
                                           ^^^^^^^^^^^^^^^^^^^^^^^^
 this string, since that would change the environment of the process.

 [...]

> +    /* Make old style arguments to be long options, and copy
> +     * other options to new argv. */
> +    for (int i = 0; i < argc && new_argc < 256; i++) {
> +        if (i == 0) {
> +            new_argv[0] = argv[i];

 it would be better to set argv[0] immediately after allocation and
 care about argc > 0 in the rest of the code

> +        } else {
> +            new_argc = getoptify_old_format(argv[i], new_argv, new_argc, new_argc_optsp, old_opt_formatp);
> +        }
> +    }

[...]

> +    while (1) {
> +	int optind = -1;

 Why? The getopt_long() wasn't called yet, the default setting should
 be enough.

> +	int c = getopt_long (new_argc, new_argv, "dflpcus",
> +		     long_options, &optind);
> +	if (c == -1)
> +	    break;

 IMHO, all this is unnecessary

     while((c = getopt_long( .... 

> +	switch (c) {
> +	    case 'd':
> +		dum_opt = 1;
> +		break;

 You need extra Python lesson :-)

        case 'd':
            dum_opt = 1;
            break;

> +	    case 'l':
> +		stop_opt = 0;
> +		break;

 [...]

>  	}
> -	else break;
>      }
> +    optind -= old_opt_format;

 Why? I expect that our new argv[] array is parsable by getopt_long() 
 without any extra care.

 Note that getopt_long() reorder argv[], so all non-option arguments
 are at the end of the array,

> +    fnames = xmalloc(sizeof(char *) * new_argc - optind);
> +    for (nfiles = 0; optind < new_argc;)
> +	fnames[nfiles++] = argv[optind++];

 is it necessary? The fnames should be a pointer to argv[optind]
 and nfiles = argc - optind.

> -    while (fnum < nfiles) {
> +    while (fnames[fnum] != NULL && fnum < nfiles) {

 unnecessary if nfiles number is correct

    Karel

-- 
 Karel Zak  <kzak@xxxxxxxxxx>
 http://karelzak.blogspot.com
--
To unsubscribe from this list: send the line "unsubscribe util-linux" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux