Skip to content

Commit 3d2d04b

Browse files
committed
Make cli commands yoinkable into cosmo shell
This lets our system() and popen() commands function sort of like BusyBox and ToyBox. By default the Cosmopolitan Shell is lightweight. But if you use STATIC_YOINK then you can pull the individual commands you want into the linkage, and they'll be included in a single binary. For example the demo binary embeds `tr` and `sed` and ends up ~140kb.
1 parent 5af19b7 commit 3d2d04b

File tree

32 files changed

+897
-276
lines changed

32 files changed

+897
-276
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ include ape/ape.mk # │
127127
include libc/fmt/fmt.mk #
128128
include libc/vga/vga.mk #─┘
129129
include libc/calls/calls.mk #─┐
130+
include third_party/getopt/getopt.mk #
130131
include libc/runtime/runtime.mk # ├──SYSTEMS RUNTIME
131132
include libc/crt/crt.mk # │ You can issue system calls
132133
include third_party/nsync/nsync.mk #
@@ -150,7 +151,6 @@ include dsp/mpeg/mpeg.mk # │
150151
include dsp/dsp.mk #
151152
include third_party/zlib/gz/gz.mk #
152153
include third_party/musl/musl.mk #
153-
include third_party/getopt/getopt.mk #
154154
include libc/libc.mk #─┘
155155
include libc/sock/sock.mk #─┐
156156
include dsp/tty/tty.mk # ├──ONLINE RUNTIME
@@ -171,6 +171,7 @@ include third_party/maxmind/maxmind.mk
171171
include net/finger/finger.mk
172172
include third_party/double-conversion/test/test.mk
173173
include third_party/lua/lua.mk
174+
include third_party/tr/tr.mk
174175
include third_party/sed/sed.mk
175176
include third_party/awk/awk.mk
176177
include third_party/make/make.mk

examples/examples.mk

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,12 @@ EXAMPLES_DIRECTDEPS = \
4949
LIBC_LOG \
5050
LIBC_MEM \
5151
LIBC_NEXGEN32E \
52+
LIBC_NT_ADVAPI32 \
5253
LIBC_NT_IPHLPAPI \
5354
LIBC_NT_KERNEL32 \
5455
LIBC_NT_NTDLL \
5556
LIBC_NT_USER32 \
5657
LIBC_NT_WS2_32 \
57-
LIBC_NT_ADVAPI32 \
5858
LIBC_RUNTIME \
5959
LIBC_SOCK \
6060
LIBC_STDIO \
@@ -71,6 +71,7 @@ EXAMPLES_DIRECTDEPS = \
7171
LIBC_ZIPOS \
7272
NET_HTTP \
7373
NET_HTTPS \
74+
THIRD_PARTY_AWK \
7475
THIRD_PARTY_COMPILER_RT \
7576
THIRD_PARTY_DLMALLOC \
7677
THIRD_PARTY_DOUBLECONVERSION \
@@ -84,7 +85,9 @@ EXAMPLES_DIRECTDEPS = \
8485
THIRD_PARTY_NSYNC \
8586
THIRD_PARTY_NSYNC_MEM \
8687
THIRD_PARTY_QUICKJS \
88+
THIRD_PARTY_SED \
8789
THIRD_PARTY_STB \
90+
THIRD_PARTY_TR \
8891
THIRD_PARTY_XED \
8992
THIRD_PARTY_ZLIB \
9093
TOOL_BUILD_LIB \

examples/system.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,20 @@
77
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
88
╚─────────────────────────────────────────────────────────────────*/
99
#endif
10-
#include "libc/dce.h"
10+
#include "libc/runtime/runtime.h"
1111
#include "libc/stdio/stdio.h"
1212

13+
/**
14+
* @fileoverview Cosmopolitan Command Interpreter Demo
15+
* Yes this works on Windows.
16+
*/
17+
18+
STATIC_YOINK("_tr");
19+
STATIC_YOINK("_sed");
20+
1321
int main(int argc, char *argv[]) {
14-
if (IsWindows()) {
15-
system("notepad");
16-
} else {
17-
system("ls | tr a-z A-Z");
18-
}
22+
system("x=world\n"
23+
"echo hello $x |\n"
24+
" tr a-z A-Z |\n"
25+
" sed 's/\\(.\\)/\\1 /g'");
1926
}

libc/log/err.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,12 @@ verrc(int eval, int code, const char *fmt, va_list ap)
9494
{
9595
if (err_file == NULL)
9696
err_set_file(NULL);
97-
fprintf(err_file, "%s: ", program_invocation_name);
97+
(fprintf)(err_file, "%s: ", program_invocation_name);
9898
if (fmt != NULL) {
99-
vfprintf(err_file, fmt, ap);
100-
fprintf(err_file, ": ");
99+
(vfprintf)(err_file, fmt, ap);
100+
(fprintf)(err_file, ": ");
101101
}
102-
fprintf(err_file, "%s\n", _strerdoc(code));
102+
(fprintf)(err_file, "%s\n", _strerdoc(code));
103103
if (err_exit)
104104
err_exit(eval);
105105
exit(eval);
@@ -119,10 +119,10 @@ verrx(int eval, const char *fmt, va_list ap)
119119
{
120120
if (err_file == NULL)
121121
err_set_file(NULL);
122-
fprintf(err_file, "%s: ", program_invocation_name);
122+
(fprintf)(err_file, "%s: ", program_invocation_name);
123123
if (fmt != NULL)
124-
vfprintf(err_file, fmt, ap);
125-
fprintf(err_file, "\n");
124+
(vfprintf)(err_file, fmt, ap);
125+
(fprintf)(err_file, "\n");
126126
if (err_exit)
127127
err_exit(eval);
128128
exit(eval);
@@ -160,12 +160,12 @@ vwarnc(int code, const char *fmt, va_list ap)
160160
saved_errno = errno;
161161
if (err_file == NULL)
162162
err_set_file(NULL);
163-
fprintf(err_file, "%s: ", program_invocation_name);
163+
(fprintf)(err_file, "%s: ", program_invocation_name);
164164
if (fmt != NULL) {
165-
vfprintf(err_file, fmt, ap);
166-
fprintf(err_file, ": ");
165+
(vfprintf)(err_file, fmt, ap);
166+
(fprintf)(err_file, ": ");
167167
}
168-
fprintf(err_file, "%s\n", strerror(code));
168+
(fprintf)(err_file, "%s\n", strerror(code));
169169
errno = saved_errno;
170170
}
171171

@@ -186,9 +186,9 @@ vwarnx(const char *fmt, va_list ap)
186186
saved_errno = errno;
187187
if (err_file == NULL)
188188
err_set_file(NULL);
189-
fprintf(err_file, "%s: ", program_invocation_name);
189+
(fprintf)(err_file, "%s: ", program_invocation_name);
190190
if (fmt != NULL)
191-
vfprintf(err_file, fmt, ap);
192-
fprintf(err_file, "\n");
191+
(vfprintf)(err_file, fmt, ap);
192+
(fprintf)(err_file, "\n");
193193
errno = saved_errno;
194194
}

libc/mem/mem.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ struct mallinfo {
5252
struct mallinfo mallinfo(void);
5353

5454
void malloc_stats(void);
55-
bool32 mallopt(int, int);
5655
size_t malloc_footprint(void);
5756
size_t malloc_max_footprint(void);
5857
size_t malloc_footprint_limit(void);

libc/runtime/cocmd.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,17 @@
2626
#include "libc/fmt/itoa.h"
2727
#include "libc/fmt/magnumstrs.internal.h"
2828
#include "libc/intrin/bits.h"
29+
#include "libc/intrin/weaken.h"
2930
#include "libc/macros.internal.h"
3031
#include "libc/runtime/runtime.h"
3132
#include "libc/str/str.h"
3233
#include "libc/sysv/consts/o.h"
3334
#include "libc/sysv/consts/s.h"
3435
#include "libc/sysv/consts/sig.h"
3536
#include "libc/sysv/consts/timer.h"
37+
#include "third_party/awk/cmd.h"
38+
#include "third_party/sed/cmd.h"
39+
#include "third_party/tr/cmd.h"
3640

3741
/**
3842
* @fileoverview Cosmopolitan Command Interpreter
@@ -48,6 +52,7 @@
4852
#define STATE_QUOTED_VAR 4
4953
#define STATE_WHITESPACE 5
5054

55+
#define TOMBSTONE ((char *)-1)
5156
#define READ24(s) READ32LE(s "\0")
5257

5358
struct Env {
@@ -62,6 +67,7 @@ static int envi;
6267
static int vari;
6368
static size_t n;
6469
static char *cmd;
70+
static char *assign;
6571
static char var[32];
6672
static int lastchild;
6773
static int exitstatus;
@@ -175,7 +181,14 @@ static void Append(int c) {
175181
static char *Finish(void) {
176182
char *s = r;
177183
Append(0);
178-
return r = q, s;
184+
r = q;
185+
if (!assign) {
186+
return s;
187+
} else {
188+
PutEnv(envs, s);
189+
assign = 0;
190+
return TOMBSTONE;
191+
}
179192
}
180193

181194
static int True(void) {
@@ -347,6 +360,19 @@ static int Test(void) {
347360
return 1;
348361
}
349362

363+
static int Fake(int main(int, char **)) {
364+
int exitstatus, ws, pid;
365+
if ((pid = fork()) == -1) SysExit(21, "vfork", prog);
366+
if (!pid) {
367+
// TODO(jart): Maybe nuke stdio state somehow?
368+
environ = envs;
369+
exit(main(n, args));
370+
}
371+
if (waitpid(pid, &ws, 0) == -1) SysExit(22, "waitpid", prog);
372+
exitstatus = WIFEXITED(ws) ? WEXITSTATUS(ws) : 128 + WTERMSIG(ws);
373+
return n = 0, exitstatus;
374+
}
375+
350376
static int TryBuiltin(void) {
351377
if (!n) return 0;
352378
if (!strcmp(args[0], "exit")) Exit();
@@ -362,6 +388,9 @@ static int TryBuiltin(void) {
362388
if (!strcmp(args[0], "false")) return False();
363389
if (!strcmp(args[0], "usleep")) return Usleep();
364390
if (!strcmp(args[0], "toupper")) return Toupper();
391+
if (_weaken(_tr) && !strcmp(args[0], "tr")) return Fake(_weaken(_tr));
392+
if (_weaken(_sed) && !strcmp(args[0], "sed")) return Fake(_weaken(_sed));
393+
if (_weaken(_awk) && !strcmp(args[0], "awk")) return Fake(_weaken(_awk));
365394
return -1;
366395
}
367396

@@ -477,6 +506,9 @@ static char *Tokenize(void) {
477506
} else if (*p == '\\') {
478507
if (!p[1]) UnsupportedSyntax(*p);
479508
Append(*++p);
509+
} else if (*p == '=') {
510+
if (!n && q > r) assign = r;
511+
Append(*p);
480512
} else if (*p == '|') {
481513
if (q > r) {
482514
return Finish();
@@ -492,7 +524,7 @@ static char *Tokenize(void) {
492524
Pipe();
493525
t = STATE_WHITESPACE;
494526
}
495-
} else if (*p == ';') {
527+
} else if (*p == ';' || *p == '\n') {
496528
if (q > r) {
497529
return Finish();
498530
} else {
@@ -595,6 +627,7 @@ int _cocmd(int argc, char **argv, char **envp) {
595627
unsupported[i] = true;
596628
}
597629
unsupported['\t'] = false;
630+
unsupported['\n'] = false;
598631
unsupported[0177] = true;
599632
unsupported['~'] = true;
600633
unsupported['`'] = true;
@@ -633,6 +666,7 @@ int _cocmd(int argc, char **argv, char **envp) {
633666
n = 0;
634667
r = q = argbuf;
635668
while ((arg = Tokenize())) {
669+
if (arg == TOMBSTONE) continue;
636670
if (n + 1 < ARRAYLEN(args)) {
637671
if (isdigit(arg[0]) && arg[1] == '>' && arg[2] == '&' &&
638672
isdigit(arg[3])) {

test/libc/mem/malloc_test.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "libc/mem/gc.h"
2828
#include "libc/mem/gc.internal.h"
2929
#include "libc/mem/mem.h"
30+
#include "libc/runtime/internal.h"
3031
#include "libc/runtime/memtrack.internal.h"
3132
#include "libc/runtime/runtime.h"
3233
#include "libc/runtime/sysconf.h"
@@ -143,10 +144,12 @@ void MallocFree(void) {
143144
}
144145

145146
BENCH(bulk_free, bench) {
146-
EZBENCH2("free(malloc(16))", donothing, MallocFree());
147147
EZBENCH2("free() bulk", BulkFreeBenchSetup(), FreeBulk());
148148
EZBENCH2("bulk_free()", BulkFreeBenchSetup(),
149149
bulk_free(bulk, ARRAYLEN(bulk)));
150+
EZBENCH2("free(malloc(16)) ST", donothing, MallocFree());
151+
__enable_threads();
152+
EZBENCH2("free(malloc(16)) MT", donothing, MallocFree());
150153
}
151154

152155
#define ITERATIONS 10000

third_party/awk/awk.mk

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,14 @@
33

44
PKGS += THIRD_PARTY_AWK
55

6-
THIRD_PARTY_AWK_SRCS = $(THIRD_PARTY_AWK_A_SRCS)
7-
THIRD_PARTY_AWK_HDRS = $(THIRD_PARTY_AWK_A_HDRS)
8-
THIRD_PARTY_AWK_INCS = $(THIRD_PARTY_AWK_A_INCS)
9-
THIRD_PARTY_AWK_BINS = $(THIRD_PARTY_AWK_COMS) $(THIRD_PARTY_AWK_COMS:%=%.dbg)
10-
THIRD_PARTY_AWK_COMS = o/$(MODE)/third_party/awk/awk.com
11-
126
THIRD_PARTY_AWK_ARTIFACTS += THIRD_PARTY_AWK_A
137
THIRD_PARTY_AWK = $(THIRD_PARTY_AWK_A_DEPS) $(THIRD_PARTY_AWK_A)
148
THIRD_PARTY_AWK_A = o/$(MODE)/third_party/awk/awk.a
15-
THIRD_PARTY_AWK_A_FILES := $(wildcard third_party/awk/*)
16-
THIRD_PARTY_AWK_A_HDRS = $(filter %.h,$(THIRD_PARTY_AWK_A_FILES))
17-
THIRD_PARTY_AWK_A_INCS = $(filter %.inc,$(THIRD_PARTY_AWK_A_FILES))
18-
THIRD_PARTY_AWK_A_SRCS = $(filter %.c,$(THIRD_PARTY_AWK_A_FILES))
19-
THIRD_PARTY_AWK_A_OBJS = $(THIRD_PARTY_AWK_A_SRCS:%.c=o/$(MODE)/%.o)
9+
THIRD_PARTY_AWK_FILES := $(wildcard third_party/awk/*)
10+
THIRD_PARTY_AWK_HDRS = $(filter %.h,$(THIRD_PARTY_AWK_FILES))
11+
THIRD_PARTY_AWK_INCS = $(filter %.inc,$(THIRD_PARTY_AWK_FILES))
12+
THIRD_PARTY_AWK_SRCS = $(filter %.c,$(THIRD_PARTY_AWK_FILES))
13+
THIRD_PARTY_AWK_OBJS = $(THIRD_PARTY_AWK_SRCS:%.c=o/$(MODE)/%.o)
2014

2115
THIRD_PARTY_AWK_A_DIRECTDEPS = \
2216
LIBC_FMT \
@@ -36,22 +30,22 @@ THIRD_PARTY_AWK_A_DIRECTDEPS = \
3630
THIRD_PARTY_AWK_A_DEPS := \
3731
$(call uniq,$(foreach x,$(THIRD_PARTY_AWK_A_DIRECTDEPS),$($(x))))
3832

39-
THIRD_PARTY_AWK_A_CHECKS = \
33+
THIRD_PARTY_AWK_CHECKS = \
4034
$(THIRD_PARTY_AWK_A).pkg \
41-
$(THIRD_PARTY_AWK_A_HDRS:%=o/$(MODE)/%.ok)
35+
$(THIRD_PARTY_AWK_HDRS:%=o/$(MODE)/%.ok)
4236

4337
$(THIRD_PARTY_AWK_A): \
4438
third_party/awk/ \
4539
$(THIRD_PARTY_AWK_A).pkg \
46-
$(THIRD_PARTY_AWK_A_OBJS)
40+
$(THIRD_PARTY_AWK_OBJS)
4741

4842
$(THIRD_PARTY_AWK_A).pkg: \
49-
$(THIRD_PARTY_AWK_A_OBJS) \
43+
$(THIRD_PARTY_AWK_OBJS) \
5044
$(foreach x,$(THIRD_PARTY_AWK_A_DIRECTDEPS),$($(x)_A).pkg)
5145

5246
o/$(MODE)/third_party/awk/awk.com.dbg: \
5347
$(THIRD_PARTY_AWK) \
54-
o/$(MODE)/third_party/awk/main.o \
48+
o/$(MODE)/third_party/awk/cmd.o \
5549
o/$(MODE)/third_party/awk/README.zip.o \
5650
$(CRT) \
5751
$(APE_NO_MODIFY_SELF)
@@ -61,10 +55,9 @@ o/$(MODE)/third_party/awk/README.zip.o: \
6155
ZIPOBJ_FLAGS = \
6256
-B
6357

64-
THIRD_PARTY_AWK_LIBS = $(foreach x,$(THIRD_PARTY_AWK_ARTIFACTS),$($(x)))
65-
THIRD_PARTY_AWK_SRCS = $(foreach x,$(THIRD_PARTY_AWK_ARTIFACTS),$($(x)_SRCS))
66-
THIRD_PARTY_AWK_CHECKS = $(foreach x,$(THIRD_PARTY_AWK_ARTIFACTS),$($(x)_CHECKS))
67-
THIRD_PARTY_AWK_OBJS = $(foreach x,$(THIRD_PARTY_AWK_ARTIFACTS),$($(x)_OBJS))
58+
THIRD_PARTY_AWK_BINS = $(THIRD_PARTY_AWK_COMS) $(THIRD_PARTY_AWK_COMS:%=%.dbg)
59+
THIRD_PARTY_AWK_COMS = o/$(MODE)/third_party/awk/awk.com
60+
THIRD_PARTY_AWK_LIBS = $(THIRD_PARTY_AWK_A)
6861
$(THIRD_PARTY_AWK_OBJS): $(BUILD_FILES) third_party/awk/awk.mk
6962

7063
.PHONY: o/$(MODE)/third_party/awk

third_party/awk/awkgram.tab.c

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,5 @@
11
// clang-format off
2-
#include "libc/mem/alg.h"
3-
#include "libc/fmt/conv.h"
42
#include "libc/mem/mem.h"
5-
#include "libc/stdio/rand.h"
6-
#include "libc/runtime/runtime.h"
7-
#include "libc/stdio/temp.h"
8-
#include "libc/sysv/consts/exit.h"
9-
#include "third_party/gdtoa/gdtoa.h"
10-
#include "libc/mem/alg.h"
113
#include "libc/str/str.h"
124
#define YYBYACC 1
135
#define YYMAJOR 1
@@ -19,13 +11,6 @@
1911
#define YYRECOVERING() (yyerrflag!=0)
2012
#define YYPREFIX "yy"
2113
#line 26 "awkgram.y"
22-
#include "libc/calls/calls.h"
23-
#include "libc/fmt/fmt.h"
24-
#include "libc/stdio/lock.internal.h"
25-
#include "libc/stdio/stdio.h"
26-
#include "libc/stdio/temp.h"
27-
#include "libc/mem/alg.h"
28-
#include "libc/str/str.h"
2914
#include "third_party/awk/awk.h"
3015

3116
void checkdup(Node *list, Cell *item);

0 commit comments

Comments
 (0)