From b2f0bd198b1116e45389a6628b657b722b4102a4 Mon Sep 17 00:00:00 2001 From: Aaron Plattner Date: Wed, 6 Feb 2013 14:11:23 -0800 Subject: [PATCH] Bug #14118: print usage() to stdout, proper errors for bad arguments Print the usage() text to stdout instead of stderr, and then only if -help is specified. Also allow --help for consistency. For other command line syntax errors, introduce a new helper function argerr() that prints errors of the form xrandr: %s Try './xrandr --help' for more information. and exits. Use that to print proper error messages. Signed-off-by: Aaron Plattner Reviewed-by: Daniel Dadap --- xrandr.c | 297 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 153 insertions(+), 144 deletions(-) diff --git a/xrandr.c b/xrandr.c index 926bc68..a5a9fd0 100644 --- a/xrandr.c +++ b/xrandr.c @@ -92,68 +92,65 @@ static const struct { { NULL, 0 } }; -static void _X_NORETURN +static void usage(void) { - fprintf(stderr, "usage: %s [options]\n", program_name); - fprintf(stderr, " where options are:\n"); - fprintf(stderr, " -display or -d \n"); - fprintf(stderr, " -help\n"); - fprintf(stderr, " -o \n"); - fprintf(stderr, " or --orientation \n"); - fprintf(stderr, " -q or --query\n"); - fprintf(stderr, " -s /x or --size /x\n"); - fprintf(stderr, " -r or --rate or --refresh \n"); - fprintf(stderr, " -v or --version\n"); - fprintf(stderr, " -x (reflect in x)\n"); - fprintf(stderr, " -y (reflect in y)\n"); - fprintf(stderr, " --screen \n"); - fprintf(stderr, " --verbose\n"); - fprintf(stderr, " --current\n"); - fprintf(stderr, " --dryrun\n"); - fprintf(stderr, " --nograb\n"); - fprintf(stderr, " --prop or --properties\n"); - fprintf(stderr, " --fb x\n"); - fprintf(stderr, " --fbmm x\n"); - fprintf(stderr, " --dpi /\n"); - fprintf(stderr, " --output \n"); - fprintf(stderr, " --auto\n"); - fprintf(stderr, " --mode \n"); - fprintf(stderr, " --preferred\n"); - fprintf(stderr, " --pos x\n"); - fprintf(stderr, " --rate or --refresh \n"); - fprintf(stderr, " --reflect normal,x,y,xy\n"); - fprintf(stderr, " --rotate normal,inverted,left,right\n"); - fprintf(stderr, " --left-of \n"); - fprintf(stderr, " --right-of \n"); - fprintf(stderr, " --above \n"); - fprintf(stderr, " --below \n"); - fprintf(stderr, " --same-as \n"); - fprintf(stderr, " --set \n"); - fprintf(stderr, " --scale x\n"); - fprintf(stderr, " --scale-from x\n"); - fprintf(stderr, " --transform ,,,,,,,,\n"); - fprintf(stderr, " --off\n"); - fprintf(stderr, " --crtc \n"); - fprintf(stderr, " --panning x[++[/x++[////]]]\n"); - fprintf(stderr, " --gamma ::\n"); - fprintf(stderr, " --primary\n"); - fprintf(stderr, " --noprimary\n"); - fprintf(stderr, " --newmode \n"); - fprintf(stderr, " \n"); - fprintf(stderr, " \n"); - fprintf(stderr, " [flags...]\n"); - fprintf(stderr, " Valid flags: +HSync -HSync +VSync -VSync\n"); - fprintf(stderr, " +CSync -CSync CSync Interlace DoubleScan\n"); - fprintf(stderr, " --rmmode \n"); - fprintf(stderr, " --addmode \n"); - fprintf(stderr, " --delmode \n"); - fprintf(stderr, " --listproviders\n"); - fprintf(stderr, " --setprovideroutputsource \n"); - fprintf(stderr, " --setprovideroffloadsink \n"); - - exit(1); - /*NOTREACHED*/ + printf("usage: %s [options]\n", program_name); + printf(" where options are:\n"); + printf(" -display or -d \n"); + printf(" --help\n"); + printf(" -o \n"); + printf(" or --orientation \n"); + printf(" -q or --query\n"); + printf(" -s /x or --size /x\n"); + printf(" -r or --rate or --refresh \n"); + printf(" -v or --version\n"); + printf(" -x (reflect in x)\n"); + printf(" -y (reflect in y)\n"); + printf(" --screen \n"); + printf(" --verbose\n"); + printf(" --current\n"); + printf(" --dryrun\n"); + printf(" --nograb\n"); + printf(" --prop or --properties\n"); + printf(" --fb x\n"); + printf(" --fbmm x\n"); + printf(" --dpi /\n"); + printf(" --output \n"); + printf(" --auto\n"); + printf(" --mode \n"); + printf(" --preferred\n"); + printf(" --pos x\n"); + printf(" --rate or --refresh \n"); + printf(" --reflect normal,x,y,xy\n"); + printf(" --rotate normal,inverted,left,right\n"); + printf(" --left-of \n"); + printf(" --right-of \n"); + printf(" --above \n"); + printf(" --below \n"); + printf(" --same-as \n"); + printf(" --set \n"); + printf(" --scale x\n"); + printf(" --scale-from x\n"); + printf(" --transform ,,,,,,,,\n"); + printf(" --off\n"); + printf(" --crtc \n"); + printf(" --panning x[++[/x++[////]]]\n"); + printf(" --gamma ::\n"); + printf(" --primary\n"); + printf(" --noprimary\n"); + printf(" --newmode \n"); + printf(" \n"); + printf(" \n"); + printf(" [flags...]\n"); + printf(" Valid flags: +HSync -HSync +VSync -VSync\n"); + printf(" +CSync -CSync CSync Interlace DoubleScan\n"); + printf(" --rmmode \n"); + printf(" --addmode \n"); + printf(" --delmode \n"); + printf(" --listproviders\n"); + printf(" --setprovideroutputsource \n"); + printf(" --setprovideroffloadsink \n"); } static void _X_NORETURN _X_ATTRIBUTE_PRINTF(1,2) @@ -180,6 +177,20 @@ warning (const char *format, ...) va_end (ap); } +static void _X_NORETURN _X_ATTRIBUTE_PRINTF(1,2) +argerr (const char *format, ...) +{ + va_list ap; + + va_start (ap, format); + fprintf (stderr, "%s: ", program_name); + vfprintf (stderr, format, ap); + fprintf (stderr, "Try '%s --help' for more information.\n", program_name); + va_end (ap); + exit (1); + /*NOTREACHED*/ +} + /* Because fmin requires C99 suppport */ static inline double dmin (double x, double y) { @@ -611,7 +622,7 @@ set_name (name_t *name, char *string, name_kind_t valid) else if (valid & name_string) set_name_string (name, string); else - usage (); + argerr ("invalid name '%s'\n", string); } static int @@ -2226,7 +2237,7 @@ check_strtol(char *s) char *endptr; int result = strtol(s, &endptr, 10); if (s == endptr) - usage(); + argerr ("failed to parse '%s' as a number\n", s); return result; } @@ -2236,7 +2247,7 @@ check_strtod(char *s) char *endptr; double result = strtod(s, &endptr); if (s == endptr) - usage(); + argerr ("failed to parse '%s' as a number\n", s); return result; } @@ -2264,7 +2275,7 @@ property_values_from_string(const char *str, const Atom type, const int format, if (token == endptr || *endptr != '\0') { - usage (); + argerr ("failed to parse '%s' as a number\n", token); } returned_bytes = realloc (returned_bytes, (nitems + 1) * bytes_per_item); @@ -2486,14 +2497,13 @@ main (int argc, char **argv) program_name = argv[0]; for (i = 1; i < argc; i++) { if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) { - if (++i>=argc) usage (); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); display_name = argv[i]; continue; } - if (!strcmp("-help", argv[i])) { + if (!strcmp("-help", argv[i]) || !strcmp("--help", argv[i])) { usage(); - action_requested = True; - continue; + exit(0); } if (!strcmp ("--verbose", argv[i])) { verbose = True; @@ -2514,12 +2524,12 @@ main (int argc, char **argv) } if (!strcmp ("-s", argv[i]) || !strcmp ("--size", argv[i])) { - if (++i>=argc) usage (); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); if (sscanf (argv[i], "%dx%d", &width, &height) == 2) { have_pixel_size = True; } else { size = check_strtol(argv[i]); - if (size < 0) usage(); + if (size < 0) argerr ("--size argument must be nonnegative\n"); } setit = True; action_requested = True; @@ -2530,7 +2540,7 @@ main (int argc, char **argv) !strcmp ("--rate", argv[i]) || !strcmp ("--refresh", argv[i])) { - if (++i>=argc) usage (); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); rate = check_strtod(argv[i]); setit = True; if (output) @@ -2562,9 +2572,9 @@ main (int argc, char **argv) continue; } if (!strcmp ("--screen", argv[i])) { - if (++i>=argc) usage (); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); screen = check_strtol(argv[i]); - if (screen < 0) usage(); + if (screen < 0) argerr ("--screen argument must be nonnegative\n"); continue; } if (!strcmp ("-q", argv[i]) || !strcmp ("--query", argv[i])) { @@ -2573,14 +2583,15 @@ main (int argc, char **argv) } if (!strcmp ("-o", argv[i]) || !strcmp ("--orientation", argv[i])) { char *endptr; - if (++i>=argc) usage (); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); dirind = strtol(argv[i], &endptr, 10); if (argv[i] == endptr) { for (dirind = 0; dirind < 4; dirind++) { if (strcmp (direction[dirind], argv[i]) == 0) break; } } - if ((dirind < 0) || (dirind > 3)) usage(); + if ((dirind < 0) || (dirind > 3)) + argerr ("%s: invalid argument '%s'\n", argv[i-1], argv[i]); rot = dirind; setit = True; action_requested = True; @@ -2597,7 +2608,7 @@ main (int argc, char **argv) continue; } if (!strcmp ("--output", argv[i])) { - if (++i >= argc) usage(); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); output = find_output_by_name (argv[i]); if (!output) { @@ -2610,95 +2621,95 @@ main (int argc, char **argv) continue; } if (!strcmp ("--crtc", argv[i])) { - if (++i >= argc) usage(); - if (!output) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); set_name (&output->crtc, argv[i], name_xid|name_index); output->changes |= changes_crtc; continue; } if (!strcmp ("--mode", argv[i])) { - if (++i >= argc) usage(); - if (!output) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); set_name (&output->mode, argv[i], name_string|name_xid); output->changes |= changes_mode; continue; } if (!strcmp ("--preferred", argv[i])) { - if (!output) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); set_name_preferred (&output->mode); output->changes |= changes_mode; continue; } if (!strcmp ("--pos", argv[i])) { - if (++i>=argc) usage (); - if (!output) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); if (sscanf (argv[i], "%dx%d", &output->x, &output->y) != 2) - usage (); + argerr ("failed to parse '%s' as a position\n", argv[i]); output->changes |= changes_position; continue; } if (!strcmp ("--rotation", argv[i]) || !strcmp ("--rotate", argv[i])) { - if (++i>=argc) usage (); - if (!output) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); for (dirind = 0; dirind < 4; dirind++) { if (strcmp (direction[dirind], argv[i]) == 0) break; } if (dirind == 4) - usage (); + argerr ("%s: invalid argument '%s'\n", argv[i-1], argv[i]); output->rotation &= ~0xf; output->rotation |= 1 << dirind; output->changes |= changes_rotation; continue; } if (!strcmp ("--reflect", argv[i]) || !strcmp ("--reflection", argv[i])) { - if (++i>=argc) usage (); - if (!output) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); for (dirind = 0; dirind < 4; dirind++) { if (strcmp (reflections[dirind], argv[i]) == 0) break; } if (dirind == 4) - usage (); + argerr ("%s: invalid argument '%s'\n", argv[i-1], argv[i]); output->rotation &= ~(RR_Reflect_X|RR_Reflect_Y); output->rotation |= dirind * RR_Reflect_X; output->changes |= changes_reflection; continue; } if (!strcmp ("--left-of", argv[i])) { - if (++i>=argc) usage (); - if (!output) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); output->relation = relation_left_of; output->relative_to = argv[i]; output->changes |= changes_relation; continue; } if (!strcmp ("--right-of", argv[i])) { - if (++i>=argc) usage (); - if (!output) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); output->relation = relation_right_of; output->relative_to = argv[i]; output->changes |= changes_relation; continue; } if (!strcmp ("--above", argv[i])) { - if (++i>=argc) usage (); - if (!output) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); output->relation = relation_above; output->relative_to = argv[i]; output->changes |= changes_relation; continue; } if (!strcmp ("--below", argv[i])) { - if (++i>=argc) usage (); - if (!output) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); output->relation = relation_below; output->relative_to = argv[i]; output->changes |= changes_relation; continue; } if (!strcmp ("--same-as", argv[i])) { - if (++i>=argc) usage (); - if (!output) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); output->relation = relation_same_as; output->relative_to = argv[i]; output->changes |= changes_relation; @@ -2706,8 +2717,8 @@ main (int argc, char **argv) } if (!strcmp ("--panning", argv[i])) { XRRPanning *pan; - if (++i>=argc) usage (); - if (!output) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); pan = &output->panning; switch (sscanf (argv[i], "%dx%d+%d+%d/%dx%d+%d+%d/%d/%d/%d/%d", &pan->width, &pan->height, &pan->left, &pan->top, @@ -2729,32 +2740,32 @@ main (int argc, char **argv) case 12: break; default: - usage (); + argerr ("%s: invalid argument '%s'\n", argv[i-1], argv[i]); } output->changes |= changes_panning; continue; } if (!strcmp ("--gamma", argv[i])) { - if (!output) usage(); - if (++i>=argc) usage (); + if (!output) argerr ("%s must be used after --output\n", argv[i]); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); if (sscanf(argv[i], "%f:%f:%f", &output->gamma.red, &output->gamma.green, &output->gamma.blue) != 3) - usage (); + argerr ("%s: invalid argument '%s'\n", argv[i-1], argv[i]); output->changes |= changes_gamma; setit_1_2 = True; continue; } if (!strcmp ("--brightness", argv[i])) { - if (!output) usage(); - if (++i>=argc) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); if (sscanf(argv[i], "%f", &output->brightness) != 1) - usage (); + argerr ("%s: invalid argument '%s'\n", argv[i-1], argv[i]); output->changes |= changes_gamma; setit_1_2 = True; continue; } if (!strcmp ("--primary", argv[i])) { - if (!output) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); output->changes |= changes_primary; output->primary = True; setit_1_2 = True; @@ -2767,14 +2778,13 @@ main (int argc, char **argv) } if (!strcmp ("--set", argv[i])) { output_prop_t *prop; - if (!output) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); + if (i+2 >= argc) argerr ("%s requires two arguments\n", argv[i]); prop = malloc (sizeof (output_prop_t)); prop->next = output->props; output->props = prop; - if (++i>=argc) usage (); - prop->name = argv[i]; - if (++i>=argc) usage (); - prop->value = argv[i]; + prop->name = argv[++i]; + prop->value = argv[++i]; propit = True; output->changes |= changes_property; setit_1_2 = True; @@ -2783,10 +2793,10 @@ main (int argc, char **argv) if (!strcmp ("--scale", argv[i])) { double sx, sy; - if (!output) usage(); - if (++i>=argc) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); if (sscanf (argv[i], "%lfx%lf", &sx, &sy) != 2) - usage (); + argerr ("failed to parse '%s' as a scaling factor\n", argv[i]); init_transform (&output->transform); output->transform.transform.matrix[0][0] = XDoubleToFixed (sx); output->transform.transform.matrix[1][1] = XDoubleToFixed (sy); @@ -2803,12 +2813,12 @@ main (int argc, char **argv) if (!strcmp ("--scale-from", argv[i])) { int w, h; - if (!output) usage(); - if (++i>=argc) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); if (sscanf (argv[i], "%dx%d", &w, &h) != 2) - usage (); + argerr ("failed to parse '%s' as a scale-from size\n", argv[i]); if (w <=0 || h <= 0) - usage (); + argerr ("--scale-from dimensions must be nonnegative\n"); output->scale_from_w = w; output->scale_from_h = h; output->changes |= changes_transform; @@ -2817,8 +2827,8 @@ main (int argc, char **argv) if (!strcmp ("--transform", argv[i])) { double transform[3][3]; int k, l; - if (!output) usage(); - if (++i>=argc) usage (); + if (!output) argerr ("%s must be used after --output\n", argv[i]); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); init_transform (&output->transform); if (strcmp (argv[i], "none") != 0) { @@ -2827,7 +2837,7 @@ main (int argc, char **argv) &transform[1][0],&transform[1][1],&transform[1][2], &transform[2][0],&transform[2][1],&transform[2][2]) != 9) - usage (); + argerr ("failed to parse '%s' as a transformation\n", argv[i]); init_transform (&output->transform); for (k = 0; k < 3; k++) for (l = 0; l < 3; l++) { @@ -2841,33 +2851,33 @@ main (int argc, char **argv) continue; } if (!strcmp ("--off", argv[i])) { - if (!output) usage(); + if (!output) argerr ("%s must be used after --output\n", argv[i]); set_name_xid (&output->mode, None); set_name_xid (&output->crtc, None); output->changes |= changes_mode; continue; } if (!strcmp ("--fb", argv[i])) { - if (++i>=argc) usage (); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); if (sscanf (argv[i], "%dx%d", &fb_width, &fb_height) != 2) - usage (); + argerr ("failed to parse '%s' as a framebuffer size\n", argv[i]); setit_1_2 = True; action_requested = True; continue; } if (!strcmp ("--fbmm", argv[i])) { - if (++i>=argc) usage (); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); if (sscanf (argv[i], "%dx%d", &fb_width_mm, &fb_height_mm) != 2) - usage (); + argerr ("failed to parse '%s' as a physical size\n", argv[i]); setit_1_2 = True; action_requested = True; continue; } if (!strcmp ("--dpi", argv[i])) { char *strtod_error; - if (++i>=argc) usage (); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); dpi = strtod(argv[i], &strtod_error); if (argv[i] == strtod_error) { @@ -2906,7 +2916,8 @@ main (int argc, char **argv) double clock; ++i; - if (i + 9 >= argc) usage (); + if (i + 9 >= argc) + argerr ("failed to parse '%s' as a mode specification\n", argv[i]); m->mode.name = argv[i]; m->mode.nameLength = strlen (argv[i]); i++; @@ -2945,7 +2956,7 @@ main (int argc, char **argv) { umode_t *m = malloc (sizeof (umode_t)); - if (++i>=argc) usage (); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); set_name (&m->name, argv[i], name_string|name_xid); m->action = umode_destroy; m->next = umodes; @@ -2958,10 +2969,9 @@ main (int argc, char **argv) { umode_t *m = malloc (sizeof (umode_t)); - if (++i>=argc) usage (); - set_name (&m->output, argv[i], name_string|name_xid); - if (++i>=argc) usage(); - set_name (&m->name, argv[i], name_string|name_xid); + if (i+2 >= argc) argerr ("%s requires two arguments\n", argv[i]); + set_name (&m->output, argv[++i], name_string|name_xid); + set_name (&m->name, argv[++i], name_string|name_xid); m->action = umode_add; m->next = umodes; umodes = m; @@ -2973,10 +2983,9 @@ main (int argc, char **argv) { umode_t *m = malloc (sizeof (umode_t)); - if (++i>=argc) usage (); - set_name (&m->output, argv[i], name_string|name_xid); - if (++i>=argc) usage(); - set_name (&m->name, argv[i], name_string|name_xid); + if (i+2 >= argc) argerr ("%s requires two arguments\n", argv[i]); + set_name (&m->output, argv[++i], name_string|name_xid); + set_name (&m->name, argv[++i], name_string|name_xid); m->action = umode_delete; m->next = umodes; umodes = m; @@ -2992,7 +3001,7 @@ main (int argc, char **argv) } if (!strcmp("--setprovideroutputsource", argv[i])) { - if (++i>=argc) usage (); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); set_name (&provider_name, argv[i], name_string|name_xid|name_index); if (++i>=argc) set_name_xid (&output_source_provider_name, 0); @@ -3004,7 +3013,7 @@ main (int argc, char **argv) } if (!strcmp("--setprovideroffloadsink", argv[i])) { - if (++i>=argc) usage (); + if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); set_name (&provider_name, argv[i], name_string|name_xid|name_index); if (++i>=argc) set_name_xid (&offload_sink_provider_name, 0); @@ -3015,7 +3024,7 @@ main (int argc, char **argv) continue; } - usage(); + argerr ("unrecognized option '%s'\n", argv[i]); } if (!action_requested) query = True; -- 2.32.0.93.g670b81a890