Repository navigation
Expand file tree
/
Copy pathappscript.1
More file actions
286 lines (285 loc) · 9.7 KB
/
Copy pathappscript.1
File metadata and controls
286 lines (285 loc) · 9.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
.\"Copyright (c) 2026, Jesús Daniel Colmenares Oviedo <DtxdF@disroot.org>
.\"All rights reserved.
.\"
.\"Redistribution and use in source and binary forms, with or without
.\"modification, are permitted provided that the following conditions are met:
.\"
.\"* Redistributions of source code must retain the above copyright notice, this
.\" list of conditions and the following disclaimer.
.\"
.\"* Redistributions in binary form must reproduce the above copyright notice,
.\" this list of conditions and the following disclaimer in the documentation
.\" and/or other materials provided with the distribution.
.\"
.\"* Neither the name of the copyright holder nor the names of its
.\" contributors may be used to endorse or promote products derived from
.\" this software without specific prior written permission.
.\"
.\"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\"IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
.\"DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
.\"FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\"DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
.\"SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
.\"CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
.\"OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
.\"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.Dd September 27, 2026
.Dt APPSCRIPT 1
.Os
.Sh NAME
.Nm appscript
.Nd Simple, lightweight and effective tool for creating SFX files
.Sh SYNOPSIS
.Nm
.Fl v
.Nm
.Op Fl CLMs
.Op Fl A Ar algo
.Op Fl a Ar arch
.Op Fl c Ar algo
.Op Fl I Ar vendorid
.Op Fl i Ar sign-key
.Op Fl o Ar filename
.Op Fl S Ar sysroot
.Ar directory
.Sh DESCRIPTION
.Nm
is a very lightweight and easy-to-use tool for creating self-extracting executables.
.Pp
From the developer's perspective,
.Xr tar 1
is used to compress a directory into a tarball, known as the
.Dq payload,
which is stored in the .rodata section,
.Xr objcopy 1
to convert the payload into a valid
.Xr elf 3 object file, and then
.Xr 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
.Pq the SFX file
reads the addresses where the payload is located and uses
.Xr libarchive 3
to extract the files to a temporary directory, finally executing an executable file named
.Sy APPSCRIPT Ns "."
The user can pass any environment variables and arguments to the AppScript, and the
.Sy APPSCRIPT
executable can handle them just like any other program or script.
.Pp
However, an AppScript does much more than what has been described above. First,
it sets handlers for
.Em SIGHUP Ns , Em SIGINT Ns , Em SIGQUIT Ns , Em SIGTERM Ns , Em SIGXCPU Ns , and Em SIGXFSZ
to stop the AppScript when it's running.
.Em SIGALRM Ns , Em SIGVTALRM Ns , Em SIGPROF Ns , Em SIGUSR1 Ns , and Em SIGUSR2
are ignored. Next, it checks if the
.Pa /var/tmp/appscript
directory exists and, if so, uses it to create temporary directories; otherwise,
.Pa /tmp
is used as fallback. The reason
.Pa /var/tmp/appscript
is preferred is that a system administrator can configure this location
to mount a
.Xr mdmfs 8
filesystem to improve the performance of very large AppScripts. This is
more secure than setting
.Dq vfs.usermount=1
and letting the user
.Pq or, in this case, the user's process
mount a
.Xr mdmfs 8
filesystem. Regardless of the directory used, it must have file mode 1777; otherwise, an
.Sy 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
.Po see ARCHIVE_EXTRACT_SECURE_SYMLINKS in Xr archive_write_disk 3 No for details Pc Ns "."
Finally, if no signal is received and no errors are detected during the
files extraction, the AppScript will attempt to execute the
.Sy 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
.Fl r
and
.Fl f
flags in
.Xr rm 1 Ns "."
.Pp
.Sy APPSCRIPT
runs in a new process group, and when its parent process
.Pq the AppScript executable
receives a handled signal
.Po such as those mentioned above Pc Ns , it forwards the signal to the entire
.Sy APPSCRIPT Ns 's process group.
.Pp
Although a temporary directory is created, its structure is deterministic:
.Sy <tempdir> Ns /appscript- Ns Sy <euid> Ns / Ns Sy <payload-checksum> Ns "."
The reason for this is to extract the payload only once, even if multiple
processes are created from the AppScript. To avoid races,
.Xr flock 2
is used to apply an exclusive lock on
.Sy <tempdir> Ns /appscript- Ns Sy <euid> Ns / Ns Sy <payload-checksum> Ns .lock Ns "."
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
.Pq 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
.Sy <tempdir> Ns /appscript- Ns Sy <euid> Ns / Ns Sy <payload-checksum> Ns / Ns Sy .<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.
.Pp
The options are as follows:
.Pp
.Bl -tag -width xxx
.It Fl C
Display the checksum after calculating it during signing.
.It Fl L
All symbolic links will be followed.
.br
Normally, symbolic links are archived as such. With this option, the
target of the link will be archived instead.
.It Fl M
Keeps code in the first 2 GB but allows data to exceed that limit.
.br
Use twice to tell
.Xr clang 1
to make no assumptions about the addresses or sizes of code and data sections.
.br
Useful for very large AppScripts.
.It Fl s
Tells the linker to create a statically linked executable.
.It Fl v
Display version information about
.Nm Ns .
.It Fl A Ar algo
Checksum algorithm to be used when signing the binary. Valid arguments:
.Sy sha256 Po default Pc No and No Sy blake3 Ns "."
.Pp
When using
.Sy blake3 Ns , it is assumed that
.Em sysutils/b3sum
is installed on your system. Likewise, the target system must have this
port installed; otherwise, verification will fail.
.It Fl a Ar arch
Specifies an architecture for the binary other than the default, which
is the same as the host. Valid arguments are:
.Sy amd64 Ns , Sy aarch64 Ns , Sy armv7 Ns , Sy i386 Ns , Sy riscv64
.Ns , Sy powerpc Ns , Sy powerpc64 Ns , and Sy powerpc64le Ns "."
.It Fl c Ar algo
Compression algorithm to be used to compress the directory. Valid
arguments:
.Sy gzip Ns , Sy xz Ns , and Sy zstd Ns "."
The default is
.Sy zstd Ns "."
.It Fl I Ar vendorid
Adds a string to a new ELF section named
.Sy ".vendorid"
to identify the author of the resulting executable.
.It Fl i Ar sign-key
Signs the resulting executable and adds the signature to the executable itself.
.br
The executable can be verified using
.Xr appscript-verify 1 "."
.It Fl o Ar filename
Name of the resulting executable. By default,
.Sy a.AppScript Ns "."
.It Fl S Ar sysroot
Tells
.Xr clang 1
to use a specified directory as the logical root directory for resolving
system headers and libraries.
.Pp
By default, when no argument is specified, it uses the
.Ns Pa %%PREFIX%%/freebsd-sysroot/ Ns Ar arch
directory only if it exists and if the host's machine architecture is
the same as
.Ar arch Ns ; otherwise, it falls back to
.Pa / Ns "."
If you have installed the
.Ar arch Ns -freebsd-sysroot
package, this should work correctly, but this parameter is primarily
necessary when you need to cross-compile a statically linked binary.
.It Ar directory
Directory to be compressed.
.Pp
.Nm
assumes that the
.Sy APPSCRIPT
script is already present and has the execute bit set.
.El
.Sh ENVIRONMENT
.Bl -tag -width xxx
.It Ev APPSCRIPT_PWD
Since
.Sy 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.
.It Ev APPSCRIPT_SCRIPT
Absolute path to the AppScript that is currently running.
.El
.Sh EXAMPLES
.Ss Improving performance
If you are the sovereign of your system, users will appreciate you if you enable
.Xr mdmfs 8
at
.Pa /var/tmp/appscript
for very large AppScripts:
.Bd -literal -offset indent
# /etc/fstab
md /var/tmp/appscript mfs rw,-SMnt,-p1777,-s1g,late 0 0
.Ed
.Pp
Then:
.Bd -literal -offset indent
# mkdir -p /var/tmp/appscript
# mount /var/tmp/appscript
.Ed
.Ss The Do Hello World Dc example
To create the most basic AppScript all you have to do is create a directory:
.Bd -literal -offset indent
$ mkdir hello-world
.Ed
.Pp
Create the
.Sy APPSCRIPT
file:
.Bd -literal -offset indent
$ cat << EOF > \&./hello-world/APPSCRIPT
#!/bin/sh
echo "Hello, world!"
EOF
.Ed
.Pp
And set the execute bit:
.Bd -literal -offset indent
$ chmod +x \&./hello-world/APPSCRIPT
.Ed
.Pp
To finally create the AppScript:
.Bd -literal -offset indent
$ appscript \&./hello-world
$ ls
\&./a.AppScript
$ \&./a.AppScript
Hello, world!
.Ed
.Sh SEE ALSO
.Xr appscript-verify 1
.Xr tar 1
.Xr libarchive 3
.Xr signal 3
.Xr sysexits 3
.Xr mdmfs 8
.Sh AUTHORS
.An Jesús Daniel Colmenares Oviedo Aq Mt DtxdF@disroot.org