Skip to content
DtxdFPublic

About

Simple, lightweight and effective tool for creating SFX files

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

70 Commits

Folders and files

Repository files navigation

NAME
     appscript - Simple, lightweight and effective tool for creating SFX files

SYNOPSIS
     appscript -v
     appscript [-CLMs] [-A algo] [-a arch] [-c algo] [-I vendorid]
	       [-i sign-key] [-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 mdmfs(8) 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 mdmfs(8) 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).

     APPSCRIPT runs in a new process group, and when its parent process (the
     AppScript executable) receives a handled signal (such as those mentioned
     above), it forwards the signal to the entire APPSCRIPT's process group.

     Although a temporary directory is created, its structure is
     deterministic: <tempdir>/appscript-<euid>/<payload-checksum>. The reason
     for this is to extract the payload only once, even if multiple processes
     are created from the AppScript. To avoid races, flock(2) is used to apply
     an exclusive lock on <tempdir>/appscript-<euid>/<payload-checksum>.lock.
     Subsequent processes will be unable to acquire an exclusive lock and will
     fall back to a shared lock, so they will wait for the first process (or
     the leader) to extract the payload. Once the leader has extracted the
     payload, it will switch to a shared lock, and the other processes will
     continue as normal.  The leader will create a dummy file named
     <tempdir>/appscript-<euid>/<payload-checksum>/.<payload-checksum> to
     indicate whether the extraction failed in a previous process.  To remove
     the temporary directory and the lock, the process will attempt to acquire
     an exclusive lock; if successful, the temporary directory will be
     removed.

     The options are as follows:

     -C   Display the checksum after calculating it during signing.

     -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.

     -M   Keeps code in the first 2 GB but allows data to exceed that limit.
	  Use twice to tell clang(1) to make no assumptions about the
	  addresses or sizes of code and data sections.
	  Useful for very large AppScripts.

     -s   Tells the linker to create a statically linked executable.

     -v   Display version information about appscript.

     -A algo
	  Checksum algorithm to be used when signing the binary. Valid
	  arguments: sha256 (default) and blake3.

	  When using blake3, it is assumed that sysutils/b3sum is installed on
	  your system. Likewise, the target system must have this port
	  installed; otherwise, verification will fail.

     -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.

     -I vendorid
	  Adds a string to a new ELF section named .vendorid to identify the
	  author of the resulting executable.

     -i sign-key
	  Signs the resulting executable and adds the signature to the
	  executable itself.
	  The executable can be verified using appscript-verify(1).

     -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
	  /usr/local/freebsd-sysroot/arch directory only if it exists and if
	  the host's machine architecture is the same as arch; 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 mdmfs(8) at /var/tmp/appscript for very large AppScripts:

	   # /etc/fstab
	   md	/var/tmp/appscript  mfs   rw,-SMnt,-p1777,-s1g,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
     appscript-verify(1) tar(1) libarchive(3) signal(3) sysexits(3) mdmfs(8)

AUTHORS
     Jesus Daniel Colmenares Oviedo <DtxdF@disroot.org>

About

Simple, lightweight and effective tool for creating SFX files

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages