about summary refs log tree commit diff
path: root/src/misc/getopt.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2014-12-19 23:59:54 -0500
committerRich Felker <dalias@aerifal.cx>2014-12-19 23:59:54 -0500
commit1d8d86aeb54c0c5439eb07a4bc1b03983fb9d6e8 (patch)
treecad0aab0c0fca2c341795c5de18e60b9a722a25d /src/misc/getopt.c
parent7d3512126db7044525cf402255e0a85ac68dc2e9 (diff)
downloadmusl-1d8d86aeb54c0c5439eb07a4bc1b03983fb9d6e8.tar.gz
musl-1d8d86aeb54c0c5439eb07a4bc1b03983fb9d6e8.tar.xz
musl-1d8d86aeb54c0c5439eb07a4bc1b03983fb9d6e8.zip
fix stderr locking and ferror semantics in getopt message printing
if writing the error message fails, POSIX requires that ferror(stderr)
be set. and as a function that operates on a stdio stream, getopt is
required to lock the stream it uses, stderr.

fwrite calls are used instead of fprintf since there is a demand from
some users not to pull in heavy stdio machinery via getopt. this
mimics the original code using write.
Diffstat (limited to 'src/misc/getopt.c')
-rw-r--r--src/misc/getopt.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/src/misc/getopt.c b/src/misc/getopt.c
index e77e460a..104b5f70 100644
--- a/src/misc/getopt.c
+++ b/src/misc/getopt.c
@@ -11,6 +11,17 @@ int optind=1, opterr=1, optopt, __optpos, __optreset=0;
 #define optpos __optpos
 weak_alias(__optreset, optreset);
 
+void __getopt_msg(const char *a, const char *b, const char *c, int l)
+{
+	FILE *f = stderr;
+	flockfile(f);
+	fwrite(a, strlen(a), 1, f)
+	&& fwrite(b, strlen(b), 1, f)
+	&& fwrite(c, l, 1, f)
+	&& putc('\n', f);
+	funlockfile(f);
+}
+
 int getopt(int argc, char * const argv[], const char *optstring)
 {
 	int i;
@@ -66,24 +77,17 @@ int getopt(int argc, char * const argv[], const char *optstring)
 	} while (l && d != c);
 
 	if (d != c) {
-		if (optstring[0] != ':' && opterr) {
-			write(2, argv[0], strlen(argv[0]));
-			write(2, ": illegal option: ", 18);
-			write(2, optchar, k);
-			write(2, "\n", 1);
-		}
+		if (optstring[0] != ':' && opterr)
+			__getopt_msg(argv[0], ": illegal option: ", optchar, k);
 		return '?';
 	}
 	if (optstring[i] == ':') {
 		if (optstring[i+1] == ':') optarg = 0;
 		else if (optind >= argc) {
 			if (optstring[0] == ':') return ':';
-			if (opterr) {
-				write(2, argv[0], strlen(argv[0]));
-				write(2, ": option requires an argument: ", 31);
-				write(2, optchar, k);
-				write(2, "\n", 1);
-			}
+			if (opterr) __getopt_msg(argv[0],
+				": option requires an argument: ",
+				optchar, k);
 			return '?';
 		}
 		if (optstring[i+1] != ':' || optpos) {