https://github.com/dtxdf/appscript
Very lightweight script to create self-extractable archives
https://github.com/dtxdf/appscript
Last synced: 20 days ago
JSON representation
Very lightweight script to create self-extractable archives
- Host: GitHub
- URL: https://github.com/dtxdf/appscript
- Owner: DtxdF
- License: bsd-3-clause
- Created: 2026-03-30T18:51:36.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-03-31T04:41:31.000Z (3 months ago)
- Last Synced: 2026-03-31T07:08:05.479Z (3 months ago)
- Language: Roff
- Size: 8.79 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.txt
- License: LICENSE
Awesome Lists containing this project
README
NAME
appscript - Simple, lightweight and effective tool for creating SFX files
SYNOPSIS
appscript -v
appscript [-L] [-a arch] [-c algo] [-o filename] [-S sysroot] directory
DESCRIPTION
appscript is a very lightweight and easy-to-use tool for creating self-
extracting executables.
From the developer's perspective, tar(1) is used to compress a directory
into a tarball, known as the "payload," which is stored in the .rodata
section, objcopy(1) to convert the payload into a valid elf(3) object
file, and then clang(1) to compile the payload with the C-written stub.
And from the user's perspective, it just need to run the executable file,
and the magic happens behind the scenes: the AppScript (the SFX file)
reads the addresses where the payload is located and uses libarchive(3)
to extract the files to a temporary directory, finally executing an
executable file named APPSCRIPT. The user can pass any environment
variables and arguments to the AppScript, and the APPSCRIPT executable
can handle them just like any other program or script.
However, an AppScript does much more than what has been described above.
First, it sets handlers for SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGXCPU,
and SIGXFSZ to stop the AppScript when it's running. SIGALRM, SIGVTALRM,
SIGPROF, SIGUSR1, and SIGUSR2 are ignored. Next, it checks if the
/var/tmp/appscript directory exists and, if so, uses it to create
temporary directories; otherwise, /tmp is used as fallback. The reason
/var/tmp/appscript is preferred is that a system administrator can
configure this location to mount a tmpfs(4) filesystem to improve the
performance of very large AppScripts. This is more secure than setting
"vfs.usermount=1" and letting the user (or, in this case, the user's
process) mount a tmpfs(4) filesystem. Regardless of the directory used,
it must have file mode 1777; otherwise, an EX_NOPERM error will be
returned. After initial checks, the tarball is extracted to a temporary
location determined by the directories mentioned above. The AppScript
will refuse to extract absolute paths and entries containing periods, and
will apply basic protection against symbolic links (see
ARCHIVE_EXTRACT_SECURE_SYMLINKS in archive_write_disk(3) for details).
Finally, if no signal is received and no errors are detected during the
files extraction, the AppScript will attempt to execute the APPSCRIPT
file. For this to succeed, the file must have the execute bit set and the
owner must be the same as the effective uid, which should be the case
since the uid and gid are changed to the caller when the files are
extracted. As a final task, the temporary directory is recursively
removed in a similar way to the -r and -f flags in rm(1).
-L All symbolic links will be followed.
Normally, symbolic links are archived as such. With this option, the
target of the link will be archived instead.
-s Tells the linker to create a statically linked executable.
-v Display version information about appscript.
-a arch
Specifies an architecture for the binary other than the default,
which is the same as the host. Valid arguments are: amd64, aarch64,
armv7, i386, riscv64, powerpc, powerpc64, and powerpc64le.
-c algo
Compression algorithm to be used to compress the directory. Valid
arguments: gzip, xz, and zstd. The default is zstd.
-o filename
Name of the resulting executable. By default, a.AppScript.
-S sysroot
Tells clang(1) to use a specified directory as the logical root
directory for resolving system headers and libraries.
By default, when no argument is specified, it uses the
%%PREFIX%%/freebsd-sysroot/arch directory only if it exists;
otherwise, it falls back to /. If you have installed the
arch-freebsd-sysroot package, this should work correctly, but this
parameter is primarily necessary when you need to cross-compile a
statically linked binary.
directory
Directory to be compressed.
appscript assumes that the APPSCRIPT script is already present and
has the execute bit set.
ENVIRONMENT
APPSCRIPT_PWD
Since APPSCRIPT runs from the current user's working directory, it
does not know the location of the temporary directory. This
environment variable specifies that location.
APPSCRIPT_SCRIPT
Absolute path to the AppScript that is currently running.
EXAMPLES
Improving performance
If you are the sovereign of your system, users will appreciate you if you
enable tmpfs(4) at /var/tmp/appscript for very large AppScripts:
# /etc/fstab
tmpfs /var/tmp/appscript tmpfs rw,size=1G,mode=1777,late 0 0
Then:
# mkdir -p /var/tmp/appscript
# mount /var/tmp/appscript
The "Hello World" example
To create the most basic AppScript all you have to do is create a
directory:
$ mkdir hello-world
Create the APPSCRIPT file:
$ cat << EOF > ./hello-world/APPSCRIPT
#!/bin/sh
echo "Hello, world!"
EOF
And set the execute bit:
$ chmod +x ./hello-world/APPSCRIPT
To finally create the AppScript:
$ appscript ./hello-world
$ ls
./a.AppScript
$ ./a.AppScript
Hello, world!
SEE ALSO
tar(1) libarchive(3) signal(3) sysexits(3)
AUTHORS
Jesus Daniel Colmenares Oviedo