mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
10fd8bdb70
This change resurrects ae5d06dc53
124 lines
4.3 KiB
C
124 lines
4.3 KiB
C
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
|
│ │
|
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
|
│ any purpose with or without fee is hereby granted, provided that the │
|
|
│ above copyright notice and this permission notice appear in all copies. │
|
|
│ │
|
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
#include "libc/assert.h"
|
|
#include "libc/calls/calls.h"
|
|
#include "libc/errno.h"
|
|
#include "libc/mem/mem.h"
|
|
#include "libc/runtime/gc.internal.h"
|
|
#include "libc/runtime/runtime.h"
|
|
#include "libc/str/str.h"
|
|
#include "libc/sysv/consts/o.h"
|
|
#include "libc/x/x.h"
|
|
#include "tool/args/args.h"
|
|
|
|
STATIC_YOINK("zip_uri_support");
|
|
|
|
static struct ZipArgs {
|
|
bool initialized;
|
|
bool loaded;
|
|
int oldargc;
|
|
char *data;
|
|
char **args;
|
|
char **oldargv;
|
|
} g_zipargs;
|
|
|
|
static void AddZipArg(int *argc, char ***argv, char *arg) {
|
|
*argv = xrealloc(*argv, (++(*argc) + 1) * sizeof(*(*argv)));
|
|
(*argv)[*argc - 1] = arg;
|
|
(*argv)[*argc - 0] = 0;
|
|
}
|
|
|
|
void FreeZipArgs(void) {
|
|
if (g_zipargs.loaded) {
|
|
free(g_zipargs.data);
|
|
free(g_zipargs.args);
|
|
__argc = g_zipargs.oldargc;
|
|
__argv = g_zipargs.oldargv;
|
|
g_zipargs.loaded = false;
|
|
}
|
|
}
|
|
|
|
int LoadZipArgsImpl(int *argc, char ***argv, char *data) {
|
|
int i, n, fd;
|
|
bool founddots;
|
|
char *arg, **args, *state, *start;
|
|
assert(!g_zipargs.loaded);
|
|
if (_chomp(data)) {
|
|
n = 0;
|
|
args = 0;
|
|
start = data;
|
|
founddots = false;
|
|
AddZipArg(&n, &args, (*argv)[0]);
|
|
while ((arg = strtok_r(start, "\r\n", &state))) {
|
|
if (!strcmp(arg, "...")) {
|
|
founddots = true;
|
|
for (i = 1; i < *argc; ++i) {
|
|
AddZipArg(&n, &args, (*argv)[i]);
|
|
}
|
|
} else {
|
|
AddZipArg(&n, &args, arg);
|
|
}
|
|
start = 0;
|
|
}
|
|
if (founddots || *argc <= 1) {
|
|
if (!g_zipargs.initialized) {
|
|
atexit(FreeZipArgs);
|
|
g_zipargs.oldargc = __argc;
|
|
g_zipargs.oldargv = __argv;
|
|
g_zipargs.initialized = true;
|
|
}
|
|
g_zipargs.loaded = true;
|
|
g_zipargs.data = data;
|
|
g_zipargs.args = args;
|
|
*argc = n;
|
|
*argv = args;
|
|
__argc = n;
|
|
__argv = args;
|
|
} else {
|
|
free(data);
|
|
free(args);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Replaces argument list with `/zip/.args` contents if it exists.
|
|
*
|
|
* Your `.args` file should have one argument per line.
|
|
*
|
|
* If the special argument `...` is *not* encountered, then the
|
|
* replacement will only happen if *no* CLI args are specified.
|
|
*
|
|
* If the special argument `...` *is* encountered, then it'll be
|
|
* replaced with whatever CLI args were specified by the user.
|
|
*
|
|
* @return 0 on success, or -1 if not found w/o errno clobber
|
|
*/
|
|
int LoadZipArgs(int *argc, char ***argv) {
|
|
int e;
|
|
char *p;
|
|
e = errno;
|
|
if ((p = xslurp("/zip/.args", 0))) {
|
|
return LoadZipArgsImpl(argc, argv, p);
|
|
} else {
|
|
errno = e;
|
|
return -1;
|
|
}
|
|
}
|