[PATCH 2/3] getopt: fixes to exit codes, free allocations at exit, progname and version output

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

 



Use symbolic exit codes, including new defines for non-standard
return values. Allocations are made free according valgrind
output. In output where program name was referred is now string
to exectable name, expect at version output which is more like
other util-linux version print outs.

Signed-off-by: Sami Kerola <kerolasa@xxxxxx>
---
 getopt/getopt.c |  107 +++++++++++++++++++++++++++++++-----------------------
 1 files changed, 61 insertions(+), 46 deletions(-)

diff --git a/getopt/getopt.c b/getopt/getopt.c
index fbcfb05..39805f8 100644
--- a/getopt/getopt.c
+++ b/getopt/getopt.c
@@ -45,7 +45,9 @@
 #include <unistd.h>
 #include <ctype.h>
 #include <getopt.h>
+#include <errno.h>
 
+#include "config.h"
 #include "nls.h"
 
 /* NON_OPT is the code that is returned when a non-option is found in '+' 
@@ -54,10 +56,22 @@
 /* LONG_OPT is the code that is returned when a long option is found. */
 #define LONG_OPT 2
 
+/* Exit codes:
+ *   0) No errors, succesful operation (EXIT_SUCCESS from stdlib.h)
+ *   1) getopt(3) returned an error (EXIT_FAILURE from stdlib.h)
+ *   2) A problem with parameter parsing for getopt(1).
+ *   3) Internal error, out of memory
+ *   4) Returned for -T
+ */
+#define EXIT_PARSING 2
+#define EXIT_INTERNAL_ERROR 3
+#define EXIT_TESTING 4
+
 /* The shells recognized. */
 typedef enum {BASH,TCSH} shell_t;
 
-
+/* Command invocation name. */
+const char *progname;
 /* Some global variables that tells us how to parse. */
 shell_t shell=BASH; /* The shell we generate output for. */
 int quiet_errors=0; /* 0 is not quiet. */
@@ -68,7 +82,7 @@ int alternative=0; /* 0 is getopt_long, 1 is getopt_long_only */
 /* Function prototypes */
 void *our_malloc(size_t size);
 void *our_realloc(void *ptr, size_t size);
-const char *normalize(const char *arg);
+void normalize(const char *arg);
 int generate_output(char * argv[],int argc,const char *optstr,
                     const struct option *longopts);
 int main(int argc, char *argv[]);
@@ -83,8 +97,8 @@ void *our_malloc(size_t size)
 {
 	void *ret=malloc(size);
 	if (! ret) {
-		fprintf(stderr,_("%s: Out of memory!\n"),"getopt");
-		exit(3);
+		fprintf(stderr,_("%s: Out of memory!\n"),progname);
+		exit(EXIT_INTERNAL_ERROR);
 	}
 	return(ret);
 }
@@ -93,22 +107,20 @@ void *our_realloc(void *ptr, size_t size)
 {
 	void *ret=realloc(ptr,size);
 	if (! ret && size) {
-		fprintf(stderr,_("%s: Out of memory!\n"),"getopt");
-		exit(3);
+		fprintf(stderr,_("%s: Out of memory!\n"),progname);
+		exit(EXIT_INTERNAL_ERROR);
 	}
 	return(ret);
 }
 
 /*
  * This function 'normalizes' a single argument: it puts single quotes around
- * it and escapes other special characters. If quote is false, it just
- * returns its argument.
+ * it and escapes other special characters.
  * Bash only needs special treatment for single quotes; tcsh also recognizes
  * exclamation marks within single quotes, and nukes whitespace.
- * This function returns a pointer to a buffer that is overwritten by 
- * each call.
+ # At the end print normalized argument.
  */
-const char *normalize(const char *arg)
+void normalize(const char *arg)
 {
 	static char *BUFFER=NULL;
 	const char *argptr=arg;
@@ -117,10 +129,7 @@ const char *normalize(const char *arg)
 	free(BUFFER);
 
 	if (!quote) { /* Just copy arg */
-		BUFFER=our_malloc(strlen(arg)+1);
-			
-		strcpy(BUFFER,arg);
-		return BUFFER;
+		printf (" %s", arg);
 	}
 
 	/* Each character in arg may take upto four characters in the result:
@@ -162,7 +171,8 @@ const char *normalize(const char *arg)
 	}
 	*bufptr++='\'';
 	*bufptr++='\0';
-	return BUFFER;
+	printf(" %s", BUFFER);
+	free(BUFFER);
 }
 
 /* 
@@ -175,7 +185,7 @@ const char *normalize(const char *arg)
 int generate_output(char * argv[],int argc,const char *optstr,
                     const struct option *longopts)
 {
-	int exit_code = 0; /* We assume everything will be OK */
+	int exit_code = EXIT_SUCCESS; /* We assume everything will be OK */
 	int opt;
 	int longindex;
 	const char *charptr;
@@ -189,29 +199,27 @@ int generate_output(char * argv[],int argc,const char *optstr,
 	              getopt_long(argc,argv,optstr,longopts,&longindex))) 
                != EOF) 
 		if (opt == '?' || opt == ':' )
-			exit_code = 1;
+			exit_code = EXIT_FAILURE;
 		else if (!quiet_output) 
 		{
 			if (opt == LONG_OPT) {
 				printf(" --%s",longopts[longindex].name);
 				if (longopts[longindex].has_arg) 
-					printf(" %s",
-					       normalize(optarg?optarg:""));
+					normalize(optarg?optarg:"");
 			} else if (opt == NON_OPT) 
-				printf(" %s",normalize(optarg)); 
+				normalize(optarg);
 			else {
 				printf(" -%c",opt);
 				charptr = strchr(optstr,opt);
 				if (charptr != NULL && *++charptr == ':')
-					printf(" %s",
-					       normalize(optarg?optarg:""));
+					normalize(optarg?optarg:"");
 			}
 		}
 	
 	if (! quiet_output) {
 		printf(" --");
 		while (optind < argc) 
-			printf(" %s",normalize(argv[optind++]));
+			normalize(argv[optind++]);
 		printf("\n");
 	}
 	return exit_code;
@@ -225,9 +233,9 @@ int generate_output(char * argv[],int argc,const char *optstr,
 void parse_error(const char *message)
 {
 	if (message)
-		fprintf(stderr,"getopt: %s\n",message);
-	fputs(_("Try `getopt --help' for more information.\n"),stderr);
-	exit(2);
+		fprintf(stderr,"%s: %s\n",progname,message);
+	fprintf(stderr,_("Try `%s --help' for more information.\n"),progname);
+	exit(EXIT_PARSING);
 }
 
 static struct option *long_options=NULL;
@@ -317,9 +325,9 @@ void set_shell(const char *new_shell)
 
 void print_help(void)
 {
-	fputs(_("Usage: getopt optstring parameters\n"),stderr);
-	fputs(_("       getopt [options] [--] optstring parameters\n"),stderr);
-	fputs(_("       getopt [options] -o|--options optstring [options] [--]\n"),stderr);
+	fprintf(stderr,_("Usage: %s optstring parameters\n"),progname);
+	fprintf(stderr,_("       %s [options] [--] optstring parameters\n"),progname);
+	fprintf(stderr,_("       %s [options] -o|--options optstring [options] [--]\n"),progname);
 	fputs(_("              parameters\n"),stderr);
 	fputs(_("  -a, --alternative            Allow long options starting with single -\n"),stderr);
 	fputs(_("  -h, --help                   This small usage guide\n"),stderr);
@@ -332,17 +340,8 @@ void print_help(void)
 	fputs(_("  -T, --test                   Test for getopt(1) version\n"),stderr);
 	fputs(_("  -u, --unqote                 Do not quote the output\n"),stderr);
 	fputs(_("  -V, --version                Output version information\n"),stderr);
-	exit(2);
 }
 	
-/* Exit codes:
- *   0) No errors, succesful operation.
- *   1) getopt(3) returned an error.
- *   2) A problem with parameter parsing for getopt(1).
- *   3) Internal error, out of memory
- *   4) Returned for -T
- */
-
 static struct option longopts[]={ {"options",required_argument,NULL,'o'},
                                   {"longoptions",required_argument,NULL,'l'},
                                   {"quiet",no_argument,NULL,'q'},
@@ -364,9 +363,14 @@ int main(int argc, char *argv[])
 {
 	char *optstr=NULL;
 	char *name=NULL;
+	int exit_code;
 	int opt;
 	int compatible=0;
 
+	progname = program_invocation_short_name;
+	if (!*progname)
+		progname = "getopt";
+
 	setlocale(LC_ALL,"");
 	bindtextdomain(PACKAGE, LOCALEDIR);
 	textdomain(PACKAGE);
@@ -382,7 +386,7 @@ int main(int argc, char *argv[])
 			/* For some reason, the original getopt gave no error
                            when there were no arguments. */
 			printf(" --\n");
-			exit(0);
+			exit(EXIT_SUCCESS);
 		}
 		else
 			parse_error(_("missing optstring argument"));
@@ -393,7 +397,8 @@ int main(int argc, char *argv[])
 		optstr=our_malloc(strlen(argv[1])+1);
 		strcpy(optstr,argv[1]+strspn(argv[1],"-+"));
 		argv[1]=argv[0];
-		exit(generate_output(argv+1,argc-1,optstr,long_options));
+		exit_code = generate_output(argv+1,argc-1,optstr,long_options);
+		exit(exit_code);
 	}
 	
 	while ((opt=getopt_long(argc,argv,shortopts,longopts,NULL)) != EOF) 
@@ -403,7 +408,7 @@ int main(int argc, char *argv[])
 			break;
 		case 'h':
 			print_help();
-			exit(0);
+			exit(EXIT_SUCCESS);
 		case 'o':
 			free(optstr);
 			optstr=our_malloc(strlen(optarg)+1);
@@ -427,13 +432,13 @@ int main(int argc, char *argv[])
 			set_shell(optarg);
 			break;
 		case 'T':
-			exit(4);
+			exit(EXIT_TESTING);
 		case 'u':
 			quote=0;
 			break;
 		case 'V':
-			printf(_("getopt (enhanced) 1.1.4\n"));
-			exit(0);
+			printf(_("getopt (%s)\n"),progname,PACKAGE_STRING);
+			exit(EXIT_SUCCESS);
 		case '?':
 		case ':':
 			parse_error(NULL);
@@ -455,5 +460,15 @@ int main(int argc, char *argv[])
 		argv[optind-1]=name;
 	else
 		argv[optind-1]=argv[0];
-	exit(generate_output(argv+optind-1,argc-optind+1,optstr,long_options));
+	exit_code = generate_output(argv+optind-1,argc-optind+1,optstr,long_options);
+	if (optstr)
+		free(optstr);
+	if (name)
+		free(name);
+	if (0 < long_options_nr) {
+		for (int i = long_options_nr; 0 <= i; i--)
+			free((void *) long_options[i].name);
+		free(long_options);
+	}
+	exit(exit_code);
 }
-- 
1.7.3.4

--
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