├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── LICENSE ├── Makefile ├── doc ├── Makefile ├── changelog └── manpage.pod ├── example ├── Makefile ├── _sidebar.sc ├── _template.sc ├── suscipit.sc └── volutpat.sc ├── misc └── shellcat.vim ├── private └── build-source-tarball ├── shellcat.c └── t ├── add-test ├── common.sh ├── generic-test ├── test-all-characters.t ├── test-arguments.in ├── test-arguments.t ├── test-arguments.xout ├── test-bad-shell.t ├── test-bad-shell.xerr ├── test-big-file.t ├── test-code-escape.in ├── test-code-escape.t ├── test-code-escape.xout ├── test-commands.in ├── test-commands.t ├── test-commands.xout ├── test-empty-file.in ├── test-empty-file.t ├── test-empty-file.xout ├── test-hash-only.in ├── test-hash-only.t ├── test-hash-only.xout ├── test-hash.in ├── test-hash.t ├── test-hash.xout ├── test-lfs.t ├── test-lfs.xout ├── test-shebang-without-lf.in ├── test-shebang-without-lf.t ├── test-shebang-without-lf.xout ├── test-shebang.in ├── test-shebang.t ├── test-shebang.xout ├── test-text-escape.in ├── test-text-escape.t ├── test-text-escape.xout ├── test-trailing-lt-dollar.in ├── test-trailing-lt-dollar.t ├── test-trailing-lt-dollar.xout ├── test-trailing-lt.in ├── test-trailing-lt.t ├── test-trailing-lt.xout ├── test-zeros.in ├── test-zeros.t └── test-zeros.xout /.gitattributes: -------------------------------------------------------------------------------- 1 | /example/*.sc linguist-language=HTML 2 | /tests/*.t linguist-language=Shell 3 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | permissions: {} 3 | on: 4 | - push 5 | - pull_request 6 | jobs: 7 | main: 8 | strategy: 9 | matrix: 10 | os: 11 | - ubuntu-22.04 12 | - ubuntu-24.04 13 | cc: 14 | - gcc 15 | - clang 16 | runs-on: ${{matrix.os}} 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: check C compiler version 20 | run: 21 | ${{matrix.cc}} --version 22 | - name: build 23 | run: 24 | make CC=${{matrix.cc}} 25 | - name: build docs 26 | run: 27 | make -C doc 28 | - name: checks docs 29 | run: 30 | make -C doc check 31 | - name: check what /bin/sh points to 32 | run: 33 | readlink -f /bin/sh 34 | - name: run tests 35 | run: | 36 | perl -E 'say $SIG{PIPE} // DEFAULT' 37 | make test 38 | - name: install 39 | run: | 40 | make install PREFIX=~/.local 41 | - name: clean 42 | run: | 43 | make clean 44 | - name: run post-install tests 45 | run: | 46 | make test-installed 47 | cd / 48 | shellcat --version 49 | shellcat --help 50 | export MANPATH=~/.local/share/man MANWIDTH=80 51 | man 1 shellcat | grep -A 10 -w SHELLCAT 52 | - name: set up APT 53 | if: matrix.cc == 'gcc' 54 | run: | 55 | printf 'Apt::Install-Recommends "false";\n' | sudo tee -a /etc/apt/apt.conf 56 | sudo apt-get update 57 | - name: run cppcheck 58 | if: matrix.cc == 'gcc' 59 | run: | 60 | sudo apt-get install cppcheck 61 | cppcheck --error-exitcode=1 *.c 62 | 63 | # vim:ts=2 sts=2 sw=2 et 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /doc/*.1 3 | /example/*.html 4 | /shellcat 5 | /tests/*.err 6 | /tests/*.out 7 | /tests/*.tmp 8 | /tests/*.report 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2001-2024 Jakub Wilk 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the “Software”), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2004-2022 Jakub Wilk 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the “Software”), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | version = $(shell IFS='()' read _ v _ < doc/changelog && echo $$v) 22 | 23 | CFLAGS ?= -g -O2 24 | CFLAGS += -Wall -Wformat -Wextra -pedantic 25 | CFLAGS += -D_FILE_OFFSET_BITS=64 26 | CPPFLAGS += -DVERSION='"$(version)"' 27 | 28 | PREFIX = /usr/local 29 | DESTDIR = 30 | 31 | bindir = $(PREFIX)/bin 32 | mandir = $(PREFIX)/share/man 33 | 34 | .PHONY: all 35 | all: shellcat 36 | 37 | shellcat: shellcat.c 38 | 39 | .PHONY: install 40 | install: shellcat 41 | install -d $(DESTDIR)$(bindir) 42 | install -m755 $(<) $(DESTDIR)$(bindir)/ 43 | ifeq "$(wildcard doc/*.1)" "" 44 | # run "$(MAKE) -C doc" to build the manpage 45 | else 46 | install -d $(DESTDIR)$(mandir)/man1 47 | install -m644 doc/$(<).1 $(DESTDIR)$(mandir)/man1/ 48 | endif 49 | 50 | reset-SIGPIPE = perl -Mautodie=exec -e '$$SIG{PIPE}="DEFAULT"; exec @ARGV' 51 | 52 | .PHONY: test 53 | test: shellcat 54 | $(reset-SIGPIPE) prove -v 55 | 56 | .PHONY: test-installed 57 | test-installed: $(or $(shell command -v shellcat;),$(bindir)/shellcat) 58 | SHELLCAT_TEST_TARGET=shellcat $(reset-SIGPIPE) prove -v 59 | 60 | .PHONY: clean 61 | clean: 62 | rm -f shellcat 63 | cd ./t && rm -f *.err *.out *.tmp 64 | 65 | .error = GNU make is required 66 | 67 | # vim:ts=4 sts=4 sw=4 noet 68 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2013-2023 Jakub Wilk 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the “Software”), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | version = $(shell IFS='()' read _ v _ < changelog && echo $$v) 22 | 23 | .PHONY: all 24 | all: shellcat.1 25 | 26 | shellcat.1: manpage.pod changelog 27 | perl -p -e 's/L<([a-z_-]+)[(]([0-9]+)[)]>/B<\1>(\2)/g' $(<) \ 28 | | pod2man --utf8 -c '' -n SHELLCAT -r 'shellcat $(version)' \ 29 | > $(@).tmp 30 | mv $(@).tmp $(@) 31 | 32 | .PHONY: check 33 | check: check-changelog check-pod 34 | 35 | .PHONY: check-changelog 36 | check-changelog: changelog 37 | dpkg-parsechangelog -l$(<) --all 2>&1 >/dev/null | { ! grep .; } 38 | 39 | .PHONY: check-pod 40 | check-pod: manpage.pod 41 | podchecker -warnings -warnings $(<) 42 | 43 | .PHONY: clean 44 | clean: 45 | rm -f *.1 *.tmp 46 | 47 | .error = GNU make is required 48 | 49 | # vim:ts=4 sts=4 sw=4 noet 50 | -------------------------------------------------------------------------------- /doc/changelog: -------------------------------------------------------------------------------- 1 | shellcat (1.2.2) UNRELEASED; urgency=low 2 | 3 | * 4 | 5 | -- Jakub Wilk Mon, 05 Feb 2024 18:38:25 +0100 6 | 7 | shellcat (1.2.1) unstable; urgency=low 8 | 9 | * Refurbish the test suite. 10 | * Improve the build system: 11 | + Add checks against BSD make. (Only GNU make is supported.) 12 | + Use “command -v” instead of which(1). 13 | + Remove the “check” target. (Use “test” instead.) 14 | + Add the “test-installed” target. 15 | + Add the “bindir” and “mandir” variables. 16 | + Don't set default CC=gcc. 17 | * Refurbish the help message. 18 | * Improve error handling. 19 | 20 | -- Jakub Wilk Tue, 30 Jan 2024 21:25:05 +0100 21 | 22 | shellcat (1.2) unstable; urgency=low 23 | 24 | * Improve error handling: 25 | + Treat lack of arguments as error: 26 | - print usage or stderr (not stdout); 27 | - exit with non-zero status. 28 | + Print error message if shell terminated prematurely. 29 | + Print only program name, not the full path, in error messages. 30 | + Make the signal handler more robust. 31 | * Use uppercase for metavars in the help output. 32 | 33 | -- Jakub Wilk Sat, 19 May 2018 20:53:12 +0200 34 | 35 | shellcat (1.1.1) unstable; urgency=low 36 | 37 | * Improve the build system: 38 | + Honour the LDLIBS variable from environment. 39 | + Enable LFS build flags. 40 | 41 | -- Jakub Wilk Thu, 09 Nov 2017 21:16:25 +0100 42 | 43 | shellcat (1.1) unstable; urgency=low 44 | 45 | * Make --version print to stdout, not stderr. 46 | * Make --help print to stdout, not stderr. 47 | * Fix GCC 7 warnings. 48 | * Improve the build system: 49 | + Fix compatibility with non-GNU install(1) programs. 50 | + Move manpage building code to a separate makefile. 51 | + Add “test” and “check” targets to the main makefile. 52 | + Make the “clean” target in the main makefile also clean the “tests” 53 | subdirectory. 54 | * Improve the test suite. 55 | 56 | -- Jakub Wilk Thu, 31 Aug 2017 13:31:36 +0200 57 | 58 | shellcat (1.0.1) unstable; urgency=low 59 | 60 | * Make the build system honor the CC and CFLAGS environment variables. 61 | * Make the manual page title all uppercase, as per man-pages(7) 62 | recommendation. 63 | * Clarify some wording in the manual page. 64 | 65 | -- Jakub Wilk Sat, 10 Dec 2016 20:32:35 +0100 66 | 67 | shellcat (1.0) unstable; urgency=low 68 | 69 | * Rename the binary as “shellcat”. 70 | * Use named pipes for communication with the shell, instead of using 71 | standard input for this purpose. 72 | * Read input in chunks, instead of loading whole files into memory. 73 | * Provide SHELLCAT environment variable to the subprocesses. 74 | * Improve error handling. 75 | * Improve the makefile: 76 | + Remove compiler-specific hacks. One can now use a different compiler by 77 | overriding the CC variable. 78 | + Provide the “install” target. 79 | * Don't ignore unknown options. 80 | * Change the license to the Expat license. 81 | * Remove Debian packaging. 82 | * Add documentation and examples. 83 | * Add a test suite. 84 | * Add a vim syntax file. 85 | 86 | -- Jakub Wilk Fri, 01 Feb 2013 07:15:46 +0100 87 | 88 | shellcat (0.06) unstable; urgency=low 89 | 90 | * Fix incorrect handling of files that don't end with newline or another 91 | special character. 92 | * Fix issues with backslashes, backticks, control characters, and non-ASCII 93 | characters. 94 | * Add support for busybox shell. 95 | Thanks to Simon Poole. 96 | * The program now works with busybox, ash, dash, bash, ksh, zsh. 97 | * Add support for TinyCC (try “make TCC=1”). 98 | 99 | -- Jakub Wilk Tue, 24 Aug 2004 19:21:19 +0200 100 | 101 | shellcat (0.05) unstable; urgency=low 102 | 103 | * Ignore shebang in the first line. 104 | Thanks to Simon Poole. 105 | * The code is now conforming to C99. 106 | 107 | -- Jakub Wilk Tue, 10 Aug 2004 15:33:53 +0200 108 | 109 | shellcat (0.04) unstable; urgency=low 110 | 111 | * Code cleanup. 112 | * Remove automake and autoconf cruft. 113 | * Remove national language support. 114 | * Fix minor bugs. 115 | * Add the Makefile. 116 | 117 | -- Jakub Wilk Fri, 02 Jan 2004 11:32:57 +0100 118 | 119 | shellcat (0.03) unstable; urgency=low 120 | 121 | * Use automake and autoconf. 122 | 123 | -- Jakub Wilk Fri, 13 Dec 2002 14:44:13 +0100 124 | 125 | shellcat (0.02) unstable; urgency=low 126 | 127 | * Improve error handling. 128 | * Fix minor bugs. 129 | * The “<$-” and “-$>” sequences are now special. 130 | 131 | -- Jakub Wilk Thu, 30 Aug 2001 14:02:00 +0200 132 | 133 | shellcat (0.01) unstable; urgency=low 134 | 135 | * Initial release. 136 | 137 | -- Jakub Wilk Thu, 23 Aug 2001 20:41:03 +0200 138 | -------------------------------------------------------------------------------- /doc/manpage.pod: -------------------------------------------------------------------------------- 1 | =encoding UTF-8 2 | 3 | =head1 NAME 4 | 5 | shellcat - templating system with shell syntax 6 | 7 | =head1 SYNOPSIS 8 | 9 | B [-s I] I