commit: 7e4232bcbc5bf2c9fbfcf86a230dbb5f3dc8ae68
parent 1f8bb7cd28421f75fbacba6d691a3ff98054c450
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Sat, 6 Sep 2025 08:24:11 +0200
Merge branch 'getopt-long-all'
Diffstat:
32 files changed, 599 insertions(+), 4 deletions(-)
diff --git a/cmd/base64.c b/cmd/base64.c
@@ -4,6 +4,7 @@
// SPDX-License-Identifier: MPL-2.0 AND BSD-2-Clause
#define _POSIX_C_SOURCE 200809L
+#include "../config.h"
#include "../libutils/getopt_nolong.h"
#include <assert.h> /* assert */
@@ -15,6 +16,9 @@
#include <string.h> /* strerror(), strncmp() */
#include <sys/stat.h> /* fstat */
#include <unistd.h> /* read(), write(), close(), getopt() */
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
// 64(26+26+10+2) + NULL
static const char *b64_encmap = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -263,7 +267,21 @@ base64_main(int argc, char *argv[])
int ret = 0;
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"decode", no_argument, NULL, 'd'},
+ {"wrap", required_argument, NULL, 'w'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:dw:", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":dw:")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/basename.c b/cmd/basename.c
@@ -4,6 +4,7 @@
#define _POSIX_C_SOURCE 200809L
+#include "../config.h"
#include "../libutils/getopt_nolong.h"
#include <libgen.h> // basename
@@ -11,6 +12,9 @@
#include <stdio.h> // puts, perror
#include <string.h> // strlen, strncmp
#include <unistd.h> // getopt
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
const char *argv0 = "basename";
@@ -51,7 +55,22 @@ main(int argc, char *argv[])
char *suffix = NULL;
char delim = '\n';
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"multiple", no_argument, NULL, 'a'},
+ {"suffix", required_argument, NULL, 's'},
+ {"zero", no_argument, NULL, 'z'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:as:z", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":as:z")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/cmp.c b/cmd/cmp.c
@@ -15,6 +15,9 @@
#include <string.h> // strerror
#include <sys/stat.h> // fstat
#include <unistd.h> // getopt
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
static bool opt_s = false, opt_l = false;
static unsigned long max_bytes = 0;
@@ -134,7 +137,23 @@ main(int argc, char *argv[])
{
char *endptr = NULL;
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"verbose", no_argument, NULL, 'l'},
+ {"bytes", required_argument, NULL, 'n'},
+ {"quiet", no_argument, NULL, 's'},
+ {"silent", no_argument, NULL, 's'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:ln:s", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":ln:s")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/cut.c b/cmd/cut.c
@@ -4,6 +4,7 @@
#define _POSIX_C_SOURCE 202405L
+#include "../config.h"
#include "../lib/reallocarray.h"
#include "../libutils/getopt_nolong.h"
@@ -17,6 +18,9 @@
#include <string.h> // strerror
#include <unistd.h> // getopt
#include <wchar.h>
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
#undef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
@@ -381,7 +385,25 @@ main(int argc, char *argv[])
}
errno = 0;
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"bytes", required_argument, NULL, 'b'},
+ {"characters", required_argument, NULL, 'c'},
+ {"delimiter", required_argument, NULL, 'd'},
+ {"fields", required_argument, NULL, 'f'},
+ {"only-delimited", no_argument, NULL, 's'},
+ {"zero-terminated", no_argument, NULL, 'z'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:b:c:d:f:nsz", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":b:c:d:f:nsz")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/df.c b/cmd/df.c
@@ -5,6 +5,7 @@
#define _POSIX_C_SOURCE 202405L
#define _DEFAULT_SOURCE // mntent in glibc 2.19+
+#include "../config.h"
#include "../lib/reallocarray.h"
#include "../libutils/getopt_nolong.h"
#include "../libutils/humanize.h"
@@ -19,6 +20,9 @@
#include <sys/stat.h> // stat, dev_t
#include <sys/statvfs.h>
#include <unistd.h> // getopt
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
#define STR(s) #s
@@ -62,7 +66,26 @@ main(int argc, char *argv[])
size_t only_count = 0;
static char *only[DF_MNT_TYPE_MAX];
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"all", no_argument, NULL, 'a'},
+ {"human-readable", no_argument, NULL, 'h'},
+ {"inodes", no_argument, NULL, 'i'},
+ {"local", no_argument, NULL, 'l'},
+ {"portability", no_argument, NULL, 'P'},
+ {"type", required_argument, NULL, 't'},
+ {"exclude-type", required_argument, NULL, 'x'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:ahilPkTt:x:", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":ahilPkTt:x:")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/head.c b/cmd/head.c
@@ -17,6 +17,9 @@
#include <stdlib.h> // strtoul
#include <string.h> // strerror
#include <unistd.h> // read
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
static const char *header_fmt = "==> %s <==\n";
@@ -254,7 +257,24 @@ main(int argc, char *argv[])
continue;
}
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"bytes", required_argument, NULL, 'c'},
+ {"lines", optional_argument, NULL, 'n'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"silent", no_argument, NULL, 'q'},
+ {"zero-terminated", no_argument, NULL, 'z'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ int c = getopt_long(argc, argv, "+:qvc:n:z", opts, NULL);
+#else
int c = getopt_nolong(argc, argv, ":qvc:n:z");
+#endif
if(c == -1) break;
switch(c)
diff --git a/cmd/id.c b/cmd/id.c
@@ -3,6 +3,7 @@
// SPDX-License-Identifier: MPL-2.0
#define _DEFAULT_SOURCE // getgrouplist (4.4BSD+)
+#include "../config.h"
#include "../libutils/getopt_nolong.h"
#include <grp.h> // getgrgid, getgroups, getgrouplist(glibc)
@@ -12,6 +13,9 @@
#include <stdlib.h> // calloc, free
#include <sys/types.h> // uid_t
#include <unistd.h> // getuid, getgid, getopt, opt*, getgrouplist(FreeBSD, NetBSD)
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
const char *argv0 = "id";
bool name_flag = false;
@@ -190,7 +194,24 @@ main(int argc, char *argv[])
struct passwd pw = {.pw_uid = uid, .pw_gid = gid};
struct passwd epw = {.pw_uid = euid, .pw_gid = egid};
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"group", no_argument, NULL, 'g'},
+ {"groups", no_argument, NULL, 'G'},
+ {"name", no_argument, NULL, 'n'},
+ {"real", no_argument, NULL, 'r'},
+ {"user", no_argument, NULL, 'u'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:Ggunr", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":Ggunr")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/ln.c b/cmd/ln.c
@@ -6,6 +6,7 @@
#define _DEFAULT_SOURCE // due to O_PATH
// Don't define _POSIX_C_SOURCE otherwise FreeBSD hides O_PATH
+#include "../config.h"
#include "../lib/bitmasks.h"
#include "../libutils/getopt_nolong.h"
@@ -18,6 +19,9 @@
#include <string.h> // strerror
#include <sys/stat.h> // fstat
#include <unistd.h> // getopt, symlink, link
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
const char *argv0 = "ln";
@@ -175,7 +179,25 @@ main(int argc, char *argv[])
{
bool verbose = false;
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"force", no_argument, NULL, 'f'},
+ {"logical", no_argument, NULL, 'L'},
+ {"no-dereference", no_argument, NULL, 'n'},
+ {"physical", no_argument, NULL, 'P'},
+ {"symbolic", no_argument, NULL, 's'},
+ {"verbose", no_argument, NULL, 'v'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:fnsLPv", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":fnsLPv")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/mkdir.c b/cmd/mkdir.c
@@ -4,6 +4,7 @@
#define _POSIX_C_SOURCE 200809L
+#include "../config.h"
#include "../libutils/getopt_nolong.h"
#include "../libutils/lib_mkdir.h"
#include "../libutils/mode.h"
@@ -15,6 +16,9 @@
#include <string.h> // strerror
#include <sys/stat.h> // mkdir
#include <unistd.h> // getopt
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
const char *argv0 = "mkdir";
@@ -54,7 +58,22 @@ main(int argc, char *argv[])
const char *errstr = NULL;
// clang-format on
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"mode", required_argument, NULL, 'm'},
+ {"parents", no_argument, NULL, 'p'},
+ {"verbose", no_argument, NULL, 'v'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:pvm:", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":pvm:")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/mkfifo.c b/cmd/mkfifo.c
@@ -4,6 +4,7 @@
#define _POSIX_C_SOURCE 200809L
+#include "../config.h"
#include "../libutils/getopt_nolong.h"
#include "../libutils/mode.h"
@@ -13,6 +14,9 @@
#include <string.h> // strerror
#include <sys/stat.h> // mkfifo
#include <unistd.h> // getopt
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
mode_t filemask;
const char *argv0 = "mkfifo";
@@ -30,7 +34,20 @@ main(int argc, char *argv[])
const char *errstr = NULL;
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"mode", required_argument, NULL, 'm'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:m:", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":m:")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/mknod.c b/cmd/mknod.c
@@ -5,6 +5,7 @@
#define _POSIX_C_SOURCE 200809L
#define _XOPEN_SOURCE 700 // mknod is in XSI
+#include "../config.h"
#include "../libutils/getopt_nolong.h"
#include "../libutils/mode.h"
@@ -15,6 +16,9 @@
#include <sys/stat.h> // mknod
#include <sys/sysmacros.h> // makedev
#include <unistd.h> // getopt
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
mode_t filemask;
const char *argv0 = "mknod";
@@ -54,7 +58,20 @@ main(int argc, char *argv[])
const char *errstr = NULL;
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"mode", required_argument, NULL, 'm'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:m:", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":m:")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/mv.c b/cmd/mv.c
@@ -28,6 +28,9 @@
#include <string.h> // strcmp
#include <sys/stat.h> // stat, S_ISDIR
#include <unistd.h> // getopt
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
// Workaround against GNU glibc
// https://sourceware.org/bugzilla/show_bug.cgi?id=18228
@@ -409,7 +412,24 @@ main(int argc, char *argv[])
.sep = "",
};
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"force", no_argument, NULL, 'f'},
+ {"interactive", no_argument, NULL, 'i'},
+ {"no-clobber", no_argument, NULL, 'n'},
+ {"target-directory", required_argument, NULL, 't'},
+ {"verbose", no_argument, NULL, 'v'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:fint:v", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":fint:v")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/nice.c b/cmd/nice.c
@@ -4,6 +4,7 @@
#define _POSIX_C_SOURCE 200809L
#define _XOPEN_SOURCE 700 // nice() is in XSI
+#include "../config.h"
#include "../libutils/getopt_nolong.h"
#include <assert.h>
@@ -12,6 +13,9 @@
#include <stdlib.h> // abort
#include <string.h> // strerror
#include <unistd.h> // getopt, nice
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
const char *argv0 = "nice";
@@ -26,7 +30,20 @@ main(int argc, char *argv[])
{
long incr = 0;
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"adjustment", required_argument, NULL, 'n'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:n:", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":n:")) != -1;)
+#endif
{
char *endptr = NULL;
diff --git a/cmd/nproc.c b/cmd/nproc.c
@@ -9,12 +9,16 @@
// Sadly {Free,Net}BSD hides _SC_NPROCESSORS_{CONF,ONLN} if _POSIX_C_SOURCE is defined *sigh*
// #define _POSIX_C_SOURCE 202405L
+#include "../config.h"
#include "../libutils/getopt_nolong.h"
#include <errno.h>
#include <stdio.h> // printf
#include <string.h> // strerror
#include <unistd.h> // sysconf, getopt, opt*
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
const char *argv0 = "nproc";
@@ -31,7 +35,20 @@ main(int argc, char *argv[])
int target = _SC_NPROCESSORS_ONLN;
const char *target_str = "_SC_NPROCESSORS_ONLN";
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"all", no_argument, NULL, 'a'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:a", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":a")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/paste.c b/cmd/paste.c
@@ -34,6 +34,7 @@
#define _POSIX_C_SOURCE 200809L
+#include "../config.h"
#include "../libutils/err.h"
#include "../libutils/getopt_nolong.h"
@@ -48,6 +49,9 @@
#include <sys/types.h>
#include <unistd.h>
#include <wchar.h>
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
static wchar_t *delim;
static int delimcnt;
@@ -267,7 +271,22 @@ main(int argc, char *argv[])
int seq = 0;
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"delimiter", required_argument, NULL, 'd'},
+ {"serial", no_argument, NULL, 's'},
+ {"zero-terminated", no_argument, NULL, 'z'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:d:sz", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":d:sz")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/pwd.c b/cmd/pwd.c
@@ -3,6 +3,7 @@
// SPDX-License-Identifier: MPL-2.0
#define _POSIX_C_SOURCE 200809L
+#include "../config.h"
#include "../libutils/getopt_nolong.h"
#include <limits.h> // PATH_MAX
@@ -11,6 +12,9 @@
#include <stdlib.h> // getenv
#include <sys/stat.h>
#include <unistd.h> // getcwd
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
const char *argv0 = "pwd";
@@ -76,7 +80,21 @@ main(int argc, char *argv[])
{
enum pwd mode = PWD_L;
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"logical", no_argument, NULL, 'L'},
+ {"physical", no_argument, NULL, 'P'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:LP", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":LP")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/realpath.c b/cmd/realpath.c
@@ -5,6 +5,7 @@
#define _POSIX_C_SOURCE 200809L
#define _XOPEN_SOURCE 700 // realpath is in XSI
+#include "../config.h"
#include "../libutils/fs.h"
#include "../libutils/getopt_nolong.h"
@@ -15,6 +16,9 @@
#include <stdlib.h> // realpath()
#include <string.h> // strncmp(), strnlen, strerror
#include <unistd.h> // getopt
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
static bool must_exists = false;
static bool offline = false;
@@ -106,7 +110,24 @@ main_realpath(int argc, char *argv[])
int offset_sep = 0;
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"canonicalize-existing", no_argument, NULL, 'e'},
+ {"canonicalize-missing", no_argument, NULL, 'm'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"strip", no_argument, NULL, 's'},
+ {"zero", no_argument, NULL, 'z'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:Eemnszq", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":Eemnszq")) != -1;)
+#endif
{
switch(c)
{
@@ -173,7 +194,24 @@ main_readlink(int argc, char *argv[])
int offset_sep = 0;
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"canonicalize", no_argument, NULL, 'f'},
+ {"canonicalize-existing", no_argument, NULL, 'e'},
+ {"canonicalize-missing", no_argument, NULL, 'm'},
+ {"no-newline", no_argument, NULL, 'n'},
+ {"zero", no_argument, NULL, 'z'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:femnz", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":femnz")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/rm.c b/cmd/rm.c
@@ -9,6 +9,7 @@
#define _NETBSD_SOURCE
#endif
+#include "../config.h"
#include "../libutils/consent.h"
#include "../libutils/getopt_nolong.h"
@@ -25,6 +26,9 @@
#include <string.h> // strerror
#include <sys/stat.h> // chmod, fstatat, S_ISDIR
#include <unistd.h> // unlink, isatty
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
bool opt_d = false, force = false, recurse = false, verbose = false, opt_i = false;
const char *argv0 = "rm";
@@ -172,13 +176,30 @@ do_unlinkat(int fd, char *name, char *acc_path)
static void
usage(void)
{
- fprintf(stderr, "Usage: rm [-firRv] [files ...]\n");
+ fprintf(stderr, "Usage: rm [-dfirRv] [files ...]\n");
}
int
main(int argc, char *argv[])
{
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"dir", no_argument, NULL, 'd'},
+ {"force", no_argument, NULL, 'f'},
+ {"interactive", no_argument, NULL, 'i'},
+ {"recursive", no_argument, NULL, 'r'},
+ {"verbose", no_argument, NULL, 'v'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:dfirRv", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":dfirRv")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/seq.c b/cmd/seq.c
@@ -3,6 +3,7 @@
// SPDX-License-Identifier: MPL-2.0
#define _POSIX_C_SOURCE 200809L
+#include "../config.h"
#include "../libutils/getopt_nolong.h"
#include <ctype.h> // isdigit
@@ -13,6 +14,9 @@
#include <stdlib.h> // exit, strtod
#include <string.h> // strerror
#include <unistd.h> // getopt, optarg, optind
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
const char *argv0 = "seq";
const char *sep = "\n";
@@ -81,7 +85,21 @@ usage(void)
int
main(int argc, char *argv[])
{
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"equal-width", no_argument, NULL, 'w'},
+ {"separator", required_argument, NULL, 's'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:ws:t:", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":ws:t:")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/shuf.c b/cmd/shuf.c
@@ -3,6 +3,7 @@
// SPDX-License-Identifier: MPL-2.0
#define _POSIX_C_SOURCE 200809L
+#include "../config.h"
#include "../libutils/getopt_nolong.h"
#include <errno.h>
@@ -12,6 +13,9 @@
#include <string.h> // strerror, memcpy
#include <time.h> // time
#include <unistd.h> // getopt
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
// Not a full shuffle, if there is more than 512 lines then last lines are never going to be printed first.
// But this allows bounded memory usage.
@@ -98,7 +102,22 @@ main(int argc, char *argv[])
bool e_flag = false;
srand((int)time(NULL));
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"echo", no_argument, NULL, 'e'},
+ {"head-count", required_argument, NULL, 'n'},
+ {"zero-terminated", no_argument, NULL, 'z'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:en:z", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":en:z")) != -1;)
+#endif
{
char *endptr = NULL;
diff --git a/cmd/split.c b/cmd/split.c
@@ -17,6 +17,9 @@
#include <string.h> // strerror
#include <sys/stat.h> // fstat
#include <unistd.h> // getopt
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
const char *argv0 = "split";
@@ -241,7 +244,22 @@ static const char *error_opt_b_l = "%s: error: Options -b and -l are mutually ex
int
main(int argc, char *argv[])
{
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"suffix-length", required_argument, NULL, 'a'},
+ {"bytes", required_argument, NULL, 'b'},
+ {"lines", required_argument, NULL, 'l'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:a:b:l:", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":a:b:l:")) != -1;)
+#endif
{
char *endptr = NULL;
diff --git a/cmd/strings.c b/cmd/strings.c
@@ -3,6 +3,7 @@
// SPDX-License-Identifier: MPL-2.0
#define _POSIX_C_SOURCE 200809L
+#include "../config.h"
#include "../libutils/getopt_nolong.h"
#include <ctype.h> /* isprint() */
@@ -13,6 +14,9 @@
#include <stdlib.h> /* strtol() */
#include <string.h> /* strerror(), strncmp() */
#include <unistd.h> /* read(), write(), close() */
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
const char *argv0 = "strings";
size_t opt_min_strlen = 4;
@@ -98,7 +102,22 @@ usage(void)
int
main(int argc, char *argv[])
{
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"all", no_argument, NULL, 'a'},
+ {"bytes", required_argument, NULL, 'n'},
+ {"radix", required_argument, NULL, 't'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:an:t:z", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":an:t:z")) != -1;)
+#endif
{
char *endptr = NULL;
diff --git a/cmd/sync.c b/cmd/sync.c
@@ -16,6 +16,9 @@
#include <stdlib.h> // abort
#include <string.h> // strerror
#include <unistd.h> // fsync, sync, getopt, syncfs
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
const char *argv0 = "sync";
@@ -25,7 +28,21 @@ main(int argc, char *argv[])
int err = 0;
int (*sync_func)(int) = fsync;
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"data", no_argument, NULL, 'd'},
+ {"file-system", no_argument, NULL, 'f'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:df", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":df")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/tee.c b/cmd/tee.c
@@ -3,6 +3,7 @@
// SPDX-License-Identifier: MPL-2.0
#define _POSIX_C_SOURCE 200809L
+#include "../config.h"
#include "../libutils/getopt_nolong.h"
#include <assert.h> /* assert() */
@@ -12,6 +13,9 @@
#include <stdlib.h> /* calloc(), free(), abort() */
#include <string.h> /* strerror() */
#include <unistd.h> /* getopt(), opt… */
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
const char *argv0 = "tee";
@@ -31,7 +35,21 @@ main(int argc, char *argv[])
FILE **fds = {NULL}; // Shut up GCC
int c;
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"append", required_argument, NULL, 'a'},
+ {"ignore-interrupts", required_argument, NULL, 'i'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:ai", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":ai")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/timeout.c b/cmd/timeout.c
@@ -4,6 +4,7 @@
#define _POSIX_C_SOURCE 200809L
#define _DEFAULT_SOURCE // For NSIG in sys_signame.h, thanks glibc
+#include "../config.h"
#include "../lib/sys_signame.h"
#include "../libutils/getopt_nolong.h"
#include "../libutils/strtodur.h"
@@ -19,6 +20,9 @@
#include <sys/wait.h>
#include <time.h> // nanosleep
#include <unistd.h> // getopt
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
#define CMD_EXIT_TIMEOUT 124
#define CMD_EXIT_FAILURE 125
@@ -61,7 +65,22 @@ main(int argc, char *argv[])
char *arg = NULL;
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"kill-after", required_argument, NULL, 'k'},
+ {"preserve-status", required_argument, NULL, 'p'},
+ {"signal", required_argument, NULL, 's'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:fk:ps:", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":fk:ps:")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/touch.c b/cmd/touch.c
@@ -10,6 +10,7 @@
#define _BSD_SOURCE // O_NOFOLLOW
#endif
+#include "../config.h"
#include "../lib/bitmasks.h" /* FIELD_* */
#include "../libutils/datetime_parse.h" /* datetime_parse */
#include "../libutils/getopt_nolong.h"
@@ -23,6 +24,9 @@
#include <sys/stat.h> /* futimens, stat, utimensat */
#include <time.h> /* mktime */
#include <unistd.h> /* getopt, opt*, close */
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
const char *argv0 = "touch";
@@ -130,7 +134,23 @@ main(int argc, char *argv[])
int open_flags = O_WRONLY | O_CREAT | O_NOCTTY;
int utimensat_flags = 0;
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"no-create", no_argument, NULL, 'c'},
+ {"date", required_argument, NULL, 'd'},
+ {"no-dereference", no_argument, NULL, 'h'},
+ {"reference", required_argument, NULL, 'r'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:acfhmr:t:d:", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":acfhmr:t:d:")) != -1;)
+#endif
{
const char *errstr = NULL;
diff --git a/cmd/tr.c b/cmd/tr.c
@@ -32,6 +32,7 @@
#define _DEFAULT_SOURCE
+#include "../config.h"
#include "../lib/tr_str.h"
#include "../libutils/err.h"
#include "../libutils/getopt_nolong.h"
@@ -42,6 +43,9 @@
#include <strings.h> // bzero
#include <sys/types.h>
#include <unistd.h>
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
int delete[NCHARS], squeeze[NCHARS];
int translate[NCHARS] = {
@@ -78,7 +82,22 @@ main(int argc, char *argv[])
int cflag, dflag, sflag;
cflag = dflag = sflag = 0;
- for(int c = -1; (c = getopt_nolong(argc, argv, "Ccds")) != -1;)
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"complement", no_argument, NULL, 'c'},
+ {"delete", no_argument, NULL, 'd'},
+ {"squeeze-repeats", no_argument, NULL, 's'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:Ccds", opts, NULL)) != -1;)
+#else
+ for(int c = -1; (c = getopt_nolong(argc, argv, ":Ccds")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/truncate.c b/cmd/truncate.c
@@ -4,6 +4,7 @@
#define _POSIX_C_SOURCE 200809L
+#include "../config.h"
#include "../lib/bitmasks.h" // FIELD_CLR
#include "../libutils/getopt_nolong.h"
#include "../libutils/truncation.h" // parse_size
@@ -16,6 +17,9 @@
#include <string.h> // strerror
#include <sys/stat.h>
#include <unistd.h> // getopt
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
const char *argv0 = "truncate";
@@ -37,7 +41,22 @@ main(int argc, char *argv[])
};
char *ref_file = NULL;
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"no-create", no_argument, NULL, 'c'},
+ {"reference", required_argument, NULL, 'r'},
+ {"size", required_argument, NULL, 's'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:cr:s:", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":cr:s:")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/uniq.c b/cmd/uniq.c
@@ -3,6 +3,7 @@
// SPDX-License-Identifier: MPL-2.0
#define _POSIX_C_SOURCE 200809L
+#include "../config.h"
#include "../libutils/getopt_nolong.h"
#include <ctype.h> // isblank
@@ -12,6 +13,9 @@
#include <stdlib.h> // atoi
#include <string.h> // strncmp
#include <unistd.h> // getopt
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
enum uniq_mode
{
@@ -31,7 +35,24 @@ main(int argc, char *argv[])
char *endptr = NULL;
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"count", no_argument, NULL, 'c'},
+ {"repeated", no_argument, NULL, 'd'},
+ {"skip-fields", required_argument, NULL, 'f'},
+ {"skip-chars", required_argument, NULL, 's'},
+ {"unique", no_argument, NULL, 'u'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+:cdf:s:u", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":cdf:s:u")) != -1;)
+#endif
{
switch(c)
{
diff --git a/cmd/which.c b/cmd/which.c
@@ -3,6 +3,7 @@
// SPDX-License-Identifier: MPL-2.0
#define _POSIX_C_SOURCE 200809L
+#include "../config.h"
#include "../libutils/getopt_nolong.h"
#include "../libutils/strchrnul.h"
@@ -13,6 +14,9 @@
#include <stdlib.h> // getenv
#include <string.h> // strcpy, memcpy
#include <unistd.h> // access, getopt
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
const char *argv0 = "which";
@@ -29,7 +33,20 @@ main(int argc, char *argv[])
return 1;
}
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"all", no_argument, NULL, 'a'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ for(int c = -1; (c = getopt_long(argc, argv, "+as", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, "as")) != -1;)
+#endif
{
switch(c)
{
diff --git a/test-cmd/rm.t b/test-cmd/rm.t
@@ -129,7 +129,7 @@ POSIX, -f shouldn't return an error when no operands are passed
$ rm -f
$ rm
rm: error: missing operand
- Usage: rm [-firRv] [files ...]
+ Usage: rm [-dfirRv] [files ...]
[1]
POSIX 2024/D4.1, -d
diff --git a/test-cmd/tee.sh b/test-cmd/tee.sh
@@ -45,5 +45,9 @@ t --exit=1 --input='foo' enoent '/var/empty/e/no/ent' 'tee: error: Failed openin
t_file --infile="${WD}/inputs/all_bytes" doubledash "${WD}/inputs/all_bytes" --
-t --exit=1 --input='foo' tripledash '---' "tee: error: Long options unsupported: '---'
+if grep -q HAS_GETOPT_LONG "${WD}/../config.h"; then
+ skip tripledash
+else
+ t --exit=1 --input='foo' tripledash '---' "tee: error: Long options unsupported: '---'
"
+fi