From 61b9677c050f47995ae5e7a7fe57de991f28259f Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Tue, 6 Jun 2023 09:12:30 -0700 Subject: [PATCH] Make improvements - Get mprotect_test working on aarch64 - Get completion working on python.com repl again - Improve quality of printvideo.com and printimage.com - Fix bug in openpty() so examples/script.c works again --- dsp/scale/magikarp.c | 10 +- libc/calls/openpty.c | 2 +- libc/runtime/mprotect.c | 4 +- libc/runtime/runtime.h | 2 +- libc/str/unicode.h | 2 +- libc/str/wcsnwidth.c | 2 +- test/dsp/scale/magikarp_test.c | 28 +++--- test/dsp/scale/scale_test.c | 138 +++++++++------------------ test/libc/runtime/mprotect_test.c | 34 ++++--- third_party/python/runpythonmodule.c | 5 +- tool/viz/printvideo.c | 14 ++- 11 files changed, 107 insertions(+), 134 deletions(-) diff --git a/dsp/scale/magikarp.c b/dsp/scale/magikarp.c index 95858403d..50b65a63d 100644 --- a/dsp/scale/magikarp.c +++ b/dsp/scale/magikarp.c @@ -38,11 +38,11 @@ signed char g_magikarp[8]; const signed char kMagikarp[8][8] = { - {-1, -3, 3, 17, 17, 3, -3, -1}, /* 1331+161 derived w/ one off cas */ - {-1, -3, 6, 28, 6, -3, -1, 0}, /* no due to the convolution theorem? */ - {0, 0, -11, 53, -11, 0, 0, 0}, /* no plus, some random experimenting */ - {-2, -6, 2, 22, 22, 2, -6, -2}, /* one a line please clang-format? */ - {-3, -9, 1, 27, 27, 1, -9, -3}, + {-1, -1, 3, 15, 15, 3, -1, -1}, // magic kernel sharp + {-1, -3, 6, 28, 6, -3, -1, 0}, // + {0, 0, -11, 53, -11, 0, 0, 0}, // + {-2, -6, 2, 22, 22, 2, -6, -2}, // + {-3, -9, 1, 27, 27, 1, -9, -3}, // }; signed char g_magkern[8]; diff --git a/libc/calls/openpty.c b/libc/calls/openpty.c index f2c68367b..b2d2ae1ca 100644 --- a/libc/calls/openpty.c +++ b/libc/calls/openpty.c @@ -99,7 +99,7 @@ int openpty(int *mfd, int *sfd, char *name, // return efault(); } BLOCK_CANCELLATIONS; - rc = openpty(mfd, sfd, name, tio, wsz); + rc = openpty_impl(mfd, sfd, name, tio, wsz); ALLOW_CANCELLATIONS; return rc; } diff --git a/libc/runtime/mprotect.c b/libc/runtime/mprotect.c index 09e42f5e5..93d84e866 100644 --- a/libc/runtime/mprotect.c +++ b/libc/runtime/mprotect.c @@ -35,8 +35,8 @@ */ int mprotect(void *addr, size_t size, int prot) { int64_t rc; - if (SupportsWindows() && (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | - PROT_GROWSDOWN | PROT_GROWSUP))) { + if (prot & + ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_GROWSDOWN | PROT_GROWSUP)) { errno = EINVAL; // unix checks prot before checking size rc = -1; } else if (!size) { diff --git a/libc/runtime/runtime.h b/libc/runtime/runtime.h index 8e76eeb0d..9870e658b 100644 --- a/libc/runtime/runtime.h +++ b/libc/runtime/runtime.h @@ -70,7 +70,7 @@ int __cxa_atexit(void *, void *, void *) libcesque; int atfork(void *, void *) libcesque; int atexit(void (*)(void)) libcesque; char *getenv(const char *) nosideeffect libcesque; -int putenv(char *) paramsnonnull(); +int putenv(char *); int setenv(const char *, const char *, int); int unsetenv(const char *); int clearenv(void); diff --git a/libc/str/unicode.h b/libc/str/unicode.h index 85e5c6c6f..07bb280ff 100644 --- a/libc/str/unicode.h +++ b/libc/str/unicode.h @@ -32,7 +32,7 @@ struct lconv { int wcwidth(wchar_t) pureconst; int wcswidth(const wchar_t *, size_t) strlenesque; -int wcsnwidth(const wchar_t *, size_t, int) strlenesque; +int wcsnwidth(const wchar_t *, size_t, size_t) strlenesque; struct lconv *localeconv(void); COSMOPOLITAN_C_END_ diff --git a/libc/str/wcsnwidth.c b/libc/str/wcsnwidth.c index 6ba9d935b..0fd76a322 100644 --- a/libc/str/wcsnwidth.c +++ b/libc/str/wcsnwidth.c @@ -21,7 +21,7 @@ /** * Returns monospace display width of wide character string. */ -int wcsnwidth(const wchar_t *pwcs, size_t n, int o) { +int wcsnwidth(const wchar_t *pwcs, size_t n, size_t o) { int w, width = 0; for (; *pwcs && n-- > 0; pwcs++) { if ((w = wcwidth(*pwcs)) < 0) { diff --git a/test/dsp/scale/magikarp_test.c b/test/dsp/scale/magikarp_test.c index efe764218..a29ba606d 100644 --- a/test/dsp/scale/magikarp_test.c +++ b/test/dsp/scale/magikarp_test.c @@ -23,9 +23,9 @@ #include "libc/fmt/bing.internal.h" #include "libc/log/check.h" #include "libc/math.h" +#include "libc/mem/gc.internal.h" #include "libc/mem/mem.h" #include "libc/nexgen32e/x86feature.h" -#include "libc/mem/gc.internal.h" #include "libc/str/str.h" #include "libc/testlib/ezbench.h" #include "libc/testlib/testlib.h" @@ -124,21 +124,21 @@ TEST(magikarp, testHalfYX) { Magikarp2xX(32, 61, M, 16, 61); EXPECT_STREQ(u"\n\ nooppppqqqqqqqqqqqqqqqqqpppooon\n\ -opppqqqqqppppoppoppppqqqqqppppo\n\ -ppqqqqpppooooommmoooopppqqqqppp\n\ -pqqqppponmmllllllllmmmnpppqqqqp\n\ -qqqppoomllllllllllllllmnoppqqqq\n\ -qqppoomlllllllmmmllllllmnoppqqq\n\ -qppponlllllmoqttspnlllllmnoppqq\n\ -qpponmllllmosyzz{vqnllllmmoppqq\n\ -qpponmllllmorwzzyupnllllmmoppqq\n\ -qqpponlllllloprrqomlllllmnoppqq\n\ +opppqqqqqpppppoooppppqqqqqppppo\n\ +ppqqqqpppoooonnnnnooopppqqqqppp\n\ +pqqqppponnmllllllllmnnnoppqqqqp\n\ +qqqppoommlllllllllllllmnoppqqqq\n\ +qqpponmllllllmmmmllllllmnoppqqq\n\ +qppponlllllmoqttspolllllmnoppqq\n\ +qpponmllllmosxzzyvqnllllmmoppqq\n\ +qpponmllllmorwyyyupnllllmmoppqq\n\ +qqpponllllllnprrqomlllllmnoppqq\n\ qqpponnmlllllllllllllllmnnppqqq\n\ -qqqppponmlllllllllllllnooppqqqp\n\ -pqqqqpppoommmlllllmmmoopppqqqpp\n\ -pppqqqqpppooooooooooppppqqqqppp\n\ +qqqppponmllllllllllllmmooppqqqp\n\ +pqqqqppoonmmmlllllmmnoopppqqqpp\n\ +pppqqqqpppooooooooooopppqqqqppp\n\ oopppqqqqqqpppppppppqqqqqqpppoo\n\ -noopopppqqqqqqqqqqqqqqqppoooonn", +noooopppqqqqqqqqqqqqqqqppoooonn", gc(bingblit(32, 61, M, 16, 31))); } diff --git a/test/dsp/scale/scale_test.c b/test/dsp/scale/scale_test.c index 3b9c3e0bf..1f53e50a3 100644 --- a/test/dsp/scale/scale_test.c +++ b/test/dsp/scale/scale_test.c @@ -16,15 +16,15 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "dsp/scale/scale.h" #include "dsp/core/c1331.h" #include "dsp/core/c161.h" #include "dsp/core/core.h" #include "dsp/core/half.h" -#include "dsp/scale/scale.h" #include "libc/fmt/bing.internal.h" #include "libc/macros.internal.h" -#include "libc/mem/mem.h" #include "libc/mem/gc.internal.h" +#include "libc/mem/mem.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" #include "libc/testlib/ezbench.h" @@ -196,41 +196,23 @@ pqpppppppppppppppppoooooooooooooooooooooooppppppppppppppppprp", Magikarp2xY(32, 61, M[0], 32, 61); AbsoluteDifference(16, 61, D[0], 16, 61, G[0], 16, 61, M[0]); EXPECT_STREQ(u"\n\ -pnpppppppppppppppoooooooooooooooooooooooooooppppppppppppppprp\n\ -ppppppppppooooonnnnmmmmmmmmmmmmmmmmmmmmmmmnnnnooooopppppppppp\n\ +popppppppppppppppooooooonnnnnnnnnnnnnooooooopppppppppppppppqp\n\ +ppppppppppooooonnnnnmmmmmmmmmmmmmmmmmmmmmnnnnnooooopppppppppp\n\ ppppppoononnnmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnnnonoopppppp\n\ pppoononnmmmmmmmmmmmmmmmmmnnnnnnnnnmmmmmmmmmmmmmmmmmnnonooppp\n\ poonnnnmmmmmmmmmmmnnnnoooppppqqqppppooonnnnmmmmmmmmmmmnnnnoop\n\ oonnnnmmmmmmmmmnooppqqrrsstttttttttssrrqqppoonmmmmmmmmmnnnnoo\n\ -onnnnmmmmmmmnnnoppqrsttuvvwwwwwwwwwvvuttsrqpponnnmmmmmmmnnnno\n\ +onnnnmmmmmmmnnnoppqqsttuvvwwwwwwwwwvvuttsqqpponnnmmmmmmmnnnno\n\ onnnmmmmmmmmnnoopqrsttuvwwxxyyyyyxxwwvuttsrqpoonnmmmmmmmmnnno\n\ onnnmmmmmmmmnnoopqrsstuvwwxxyyyyyxxwwvutssrqpoonnmmmmmmmmnnno\n\ oonnnmmmmmmmmnnoopprrsttuuvvwwwwwvvuuttsrrppoonnmmmmmmmmnnnoo\n\ ooonnmmmmmmmmmmmnoopoqqqrrsssssssssrrqqqopoonmmmmmmmmmmmnnooo\n\ -pooonnnmmmmmmmmmmmmmnnnnoooopppppoooonnnnmmmmmmmmmmmmmnnnooop\n\ +pooonnnmmmmmmmmmmmnmnnnoopoopppppoopoonnnmnmmmmmmmmmmmnnnooop\n\ ppppoononnmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnnonoopppp\n\ pppppppoonoonnmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnnoonooppppppp\n\ -pppppppppppoooooonnnnmmmmmmmmmmmmmmmmmmmnnnnooooooppppppppppp\n\ +pppppppppppoooooonnnnnnmmmmmmmmmmmmmmmnnnnnnooooooppppppppppp\n\ pqpppppppppppppppppoooooooooooooooooooooooppppppppppppppppprp", gc(bingblit(16, 61, M[0], 16, 61))); - EXPECT_STREQ(u"\n\ - ☺                                                         ☺ \n\ -             ☺     ☺                     ☺     ☺             \n\ -                                                             \n\ -                                                             \n\ -                                                             \n\ -                                                             \n\ -                   ☺                     ☺                   \n\ -                                                             \n\ -                                                             \n\ -                                                             \n\ -                   ☺      ☺       ☺      ☺                   \n\ -                         ☺         ☺                         \n\ -                                                             \n\ -                                                             \n\ -                     ☺☺               ☺☺                   ☺ \n\ -                                                             ", - gc(bingblit(16, 61, D[0], 16, 61))); } TEST(Magikarp2xX, testDecimateX) { @@ -274,7 +256,7 @@ ppppppppppooooooooooopppppppppp", Magikarp2xX(32, 61, M[0], 32, 61); EXPECT_STREQ(u"\n\ pppppppppoooooooooooooppppppppp\n\ -nppppppooonnnnnnnnnnooooppppprp\n\ +oppppppooonnnnnnnnnnoooopppppqp\n\ pppppooonnnnmmmmmmnnnnooopppppp\n\ ppppooonnnmmmmmmmmmmmnnnooppppp\n\ pppoonnnmmmmmmmmmmmmmmmnnoopppp\n\ @@ -286,13 +268,13 @@ oonnmmmmnoopqqrrqqpponmmmmmnnoo\n\ onnmmmmmnopqrsssssrqpnnmmmmnnoo\n\ onmmmmmnopqstuuuutsrqoommmmmnoo\n\ onnmmmmnpqrtuvvvvvtsrponmmmmnno\n\ -onmmmmnnpqtuvwxxwwutsponmmmmmno\n\ -onmmmmnoqrsvwxyyxxvurronmmmmmno\n\ -onmmmmnopstvwxyyyxwutronmmmmmno\n\ -onmmmmnopssvwxyyyxwtsronmmmmmno\n\ -onmmmmnopqtuvxxxxwvurqpnmmmmmno\n\ -onmmmmmnorsuvwwwwvutrqonmmmmmno\n\ -onmmmmmnoqrstuvvvutrqpnnmmmmnoo\n\ +onmmmmnopqsuvwxxwwutsqonmmmmmno\n\ +onmmmmnoqrsuwxyyxwvusqpnmmmmmno\n\ +onmmmmnopstvwxyyyxvusrpnmmmmmno\n\ +onmmmmnoprtvwxyyyxwtsrpnmmmmmno\n\ +onmmmmnoprtuvxxxxwvtrqpnmmmmmno\n\ +onmmmmmnpqstvwwwwvutrqonmmmmmno\n\ +onmmmmmnoqrstuvvvutrqponmmmmnoo\n\ onmmmmmnnoqrsttttssqponmmmmmnoo\n\ oonmmmmmnooqrrrrrrqpoommmmmmnoo\n\ oonmmmmmnnnoppqqqpponnmmmmmnooo\n\ @@ -307,40 +289,6 @@ qpppppppoooonnnnnnnoooopppppprp\n\ ppppppppppooooooooooopppppppppp", gc(bingblit(32, 61, M[0], 32, 31))); AbsoluteDifference(32, 31, D, 32, 31, G[0], 32, 61, M[0]); - EXPECT_STREQ(u"\n\ -                               \n\ -☺                              \n\ -                  ☺            \n\ -         ☺                     \n\ -       ☺                 ☺     \n\ -      ☺                        \n\ -                 ☺             \n\ -          ☺  ☺                 \n\ -                 ☺ ☺ ☺         \n\ -                   ☺           \n\ -                  ☺☺☺          \n\ -                               \n\ -                               \n\ -       ☺             ☺         \n\ -                    ☺☺☺        \n\ -                               \n\ -          ☺           ☺        \n\ -         ☺                     \n\ -        ☺☺                     \n\ -                      ☺        \n\ -                               \n\ -                               \n\ -        ☺       ☺ ☺            \n\ -                  ☺ ☺          \n\ -           ☺                   \n\ -                        ☺      \n\ -                       ☺       \n\ -        ☺                      \n\ -          ☺                    \n\ -                               \n\ -                               \n\ -                               ", - gc(bingblit(32, 31, D, 32, 31))); } TEST(magikarp_vs_gyarados, testHalf) { @@ -352,22 +300,22 @@ TEST(magikarp_vs_gyarados, testHalf) { Magikarp2xX(32, 61, M[0], 16, 61); AbsoluteDifference(16, 31, D, 16, 31, G[0], 32, 61, M[0]); EXPECT_STREQ(u"\n\ -oppppppppooooooooooooopppppppqp\n\ -pppppooonnmmmmmmmmmmmnnoopppppp\n\ -ppponnmmmmmmmmmmmmmmmmmmnnnpppp\n\ -ppnommmmmmmmmnnnnnmmmmmmmmnoopp\n\ +pppppppppooonnnnnnooooppppppppp\n\ +pppppooonnmmmmmmmmmmnnnoopppppp\n\ +ppponnmmmmmmmmmmmmmmmmmmnnopppp\n\ +pponmmmmmmmmmnnnnnmmmmmmmmnoopp\n\ pnnnmmmmmnnoppqqpponnnmmmmmnnop\n\ -onnmmmmmopqrstttttsrqpnmmmmnnoo\n\ -onnmmmnnpqtuvwwwwwutsponmmmmnno\n\ -onmmmmnopstvwxyyyxwutronmmmmmno\n\ -onmmmmnopssvwxyyyxwtsronmmmmmno\n\ +onnmmmmnopqrstttttsrqpnmmmmnnoo\n\ +onnmmmnopqsuvwwwwwutrponmmmmnno\n\ +onmmmmnopstvwxyyyxvusrpnmmmmmno\n\ +onmmmmnoprtvwxyyyxwtsrpnmmmmmno\n\ onmmmmmooqstuvwwwvusrponmmmmnoo\n\ -oommmmmmnopqrsssssqqpommmmmmnoo\n\ -ponmmmmmmmnnoopppoonnmmmmmmnoop\n\ -ppoonmmmmmmmmmmmmmmmmmmmmmonppp\n\ -ppppnonmmmmmmmmmmmmmmmmmooopppp\n\ -ppppppooonnmmmmmmmmmnnooopppppp\n\ -qpppppppppoooooooooooppppppppqp", +oommmmmmnopqrsssssrqponmmmmmnoo\n\ +ponmmmmmmnnopoppooonnmmmmmmnoop\n\ +ppoonmmmmmmmmmmmmmmmmmmmmmnoppp\n\ +ppppoonmmmmmmmmmmmmmmmmmooopppp\n\ +ppppppooonnnmmmmmmmnnnooopppppp\n\ +ppppppppppoooooooooooppppppppqp", gc(bingblit(32, 61, M[0], 16, 31))); EXPECT_STREQ(u"\n\ ppppppppooooooooooooooopppppppp\n\ @@ -388,22 +336,22 @@ pppppooonnnmmmmmmmmmnnnoooppppp\n\ pppppppppoooooooooooooppppppppq", gc(bingblit(16, 31, G[0], 16, 31))); EXPECT_STREQ(u"\n\ -☺       ☺             ☺      ☺ \n\ -       ☺               ☺ ☺     \n\ -    ☺ ☺                   ☺☺   \n\ - ☺☺☺☺                      ☺ ☺ \n\ +        ☺   ☺☺☺☺☺☺    ☺        \n\ +       ☺            ☺  ☺ ☺     \n\ +    ☺ ☺                    ☺   \n\ + ☺  ☺                      ☺ ☺ \n\ ☺☺              ☺ ☺☺          ☺\n\ -       ☺☺☺           ☺ ☺   ☺ ☺ \n\ -  ☺       ☺☺☺        ☺☺ ☺   ☺  \n\ -         ☺ ☺   ☺      ☺☺☺      \n\ -         ☺ ☺       ☺  ☺☺☺      \n\ +        ☺☺           ☺ ☺   ☺ ☺ \n\ +  ☺    ☺   ☺☺       ☺☺☺ ☺   ☺  \n\ +         ☺ ☺   ☺  ☺ ☺  ☺☺      \n\ +          ☺☺       ☺   ☺☺      \n\        ☺  ☺        ☺ ☺      ☺☺ \n\ - ☺☺               ☺   ☺      ☺ \n\ -☺  ☺                        ☺ ☺\n\ -                          ☺☺☺  \n\ -   ☺☺☺                  ☺☺ ☺   \n\ -     ☺  ☺             ☺  ☺     \n\ -☺        ☺           ☺       ☺☺", + ☺☺                          ☺ \n\ +☺  ☺     ☺ ☺☺   ☺           ☺ ☺\n\ +                            ☺  \n\ +   ☺ ☺                  ☺☺ ☺   \n\ +     ☺  ☺  ☺       ☺  ☺  ☺     \n\ +         ☺           ☺       ☺☺", gc(bingblit(16, 31, D, 16, 31))); } diff --git a/test/libc/runtime/mprotect_test.c b/test/libc/runtime/mprotect_test.c index ca4add027..d9de99f48 100644 --- a/test/libc/runtime/mprotect_test.c +++ b/test/libc/runtime/mprotect_test.c @@ -35,18 +35,36 @@ #include "libc/x/x.h" #include "third_party/xed/x86.h" -#ifdef __x86_64__ - volatile bool gotsegv; volatile bool gotbusted; struct sigaction old[2]; char testlib_enable_tmp_setup_teardown; +#ifdef __x86_64__ +static const char kRet31337[] = { + 0xb8, 0x69, 0x7a, 0x00, 0x00, // mov $31337,%eax + 0xc3, // ret +}; +#elif defined(__aarch64__) +static const uint32_t kRet31337[] = { + 0x528f4d20, // mov w0,#31337 + 0xd65f03c0, // ret +}; +#else +#error "unsupported architecture" +#endif + void SkipOverFaultingInstruction(struct ucontext *ctx) { +#ifdef __x86_64__ struct XedDecodedInst xedd; xed_decoded_inst_zero_set_mode(&xedd, XED_MACHINE_MODE_LONG_64); xed_instruction_length_decode(&xedd, (void *)ctx->uc_mcontext.rip, 15); ctx->uc_mcontext.rip += xedd.length; +#elif defined(__aarch64__) + ctx->uc_mcontext.pc += 4; +#else +#error "unsupported architecture" +#endif } void OnSigSegv(int sig, struct siginfo *si, void *vctx) { @@ -125,7 +143,7 @@ TEST(mprotect, testSegfault_writeToReadOnlyAnonymous) { TEST(mprotect, testExecOnly_canExecute) { char *p = _mapanon(FRAMESIZE); void (*f)(void) = (void *)p; - p[0] = 0xC3; // RET + memcpy(p, kRet31337, sizeof(kRet31337)); ASSERT_SYS(0, 0, mprotect(p, FRAMESIZE, PROT_EXEC | PROT_READ)); f(); // On all supported platforms, PROT_EXEC implies PROT_READ. There is @@ -146,11 +164,6 @@ TEST(mprotect, testProtNone_cantEvenRead) { EXPECT_NE(-1, mprotect(p, GUARDSIZE, PROT_READ | PROT_WRITE)); } -static const char kRet31337[] = { - 0xb8, 0x69, 0x7a, 0x00, 0x00, // mov $31337,%eax - 0xc3, // ret -}; - TEST(mprotect, testExecJit_actuallyWorks) { int (*p)(void) = gc(memalign(GUARDSIZE, GUARDSIZE)); memcpy(p, kRet31337, sizeof(kRet31337)); @@ -162,7 +175,8 @@ TEST(mprotect, testExecJit_actuallyWorks) { } TEST(mprotect, testRwxMap_vonNeumannRules) { - if (IsOpenbsd()) return; // boo + if (IsOpenbsd()) return; // boo + if (IsXnuSilicon()) return; // boo int (*p)(void) = gc(memalign(GUARDSIZE, GUARDSIZE)); memcpy(p, kRet31337, sizeof(kRet31337)); EXPECT_NE(-1, mprotect(p, GUARDSIZE, PROT_READ | PROT_WRITE | PROT_EXEC)); @@ -216,5 +230,3 @@ TEST(mprotect, testZeroSize_doesNothing) { EXPECT_FALSE(gotsegv); EXPECT_FALSE(gotbusted); } - -#endif /* __x86_64__ */ diff --git a/third_party/python/runpythonmodule.c b/third_party/python/runpythonmodule.c index 7131d5bd2..333dedbfc 100644 --- a/third_party/python/runpythonmodule.c +++ b/third_party/python/runpythonmodule.c @@ -215,7 +215,10 @@ Complete(const char *p, linenoiseCompletions *c) static void TerminalCompletion(const char *p, linenoiseCompletions *c) { - // Complete(p, c); + PyGILState_STATE gilstate; + gilstate = PyGILState_Ensure(); + Complete(p, c); + PyGILState_Release(gilstate); if (PyErr_Occurred()) { PyErr_Clear(); } diff --git a/tool/viz/printvideo.c b/tool/viz/printvideo.c index fbada5c86..83b078e10 100644 --- a/tool/viz/printvideo.c +++ b/tool/viz/printvideo.c @@ -1533,6 +1533,7 @@ static void TryToOpenFrameBuffer(void) { int main(int argc, char *argv[]) { sigset_t wut; + const char *s; gamma_ = 2.4; volscale_ -= 2; dither_ = true; @@ -1546,8 +1547,17 @@ int main(int argc, char *argv[]) { if (!tuned_) PickDefaults(); if (optind == argc) PrintUsage(EX_USAGE, stderr); patharg_ = argv[optind]; - sox_ = strdup(commandvenv("SOX", "sox")); - ffplay_ = strdup(commandvenv("FFPLAY", "ffplay")); + s = commandvenv("SOX", "sox"); + sox_ = s ? strdup(s) : 0; + s = commandvenv("FFPLAY", "ffplay"); + ffplay_ = s ? strdup(s) : 0; + if (!sox_ && !ffplay_) { + fprintf(stderr, "please install either the " + "`play` (sox) or " + "`ffplay` (ffmpeg) " + "commands, so printvideo.com can play audio\n"); + usleep(10000); + } infd_ = STDIN_FILENO; outfd_ = STDOUT_FILENO; if (!setjmp(jb_)) {