-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathpp.front
417 lines (388 loc) · 12.9 KB
/
pp.front
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
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
#
# Polypkg frontend - reads a polypkg file and split it up into the various
# section files that get read by the backend(s).
#
# The output files from frontend() are:
#
# %files.run - required runtime files
# %files.doc - optional documentation files
# %files.dbg - optional debugging files
# %files.dev - optional developer files
#
# Lines in %files.* consist only of:
# [d|f] path mode owner group [v|-]
# s path mode owner group [v|-] target
#
# %post.$cpt - post-install script ($cpt component)
# %preun.$cpt - pre-uninstall script ($cpt component)
# %check.$cpt - pre-install check script ($cpt component)
#
# where $cpt is one of [ run doc dbg dev ]
#
# %service.$svc - service variables
#
# %depend - common package dependencies (one per line)
# %depend.$cpt - $cpt component dependencies
#
# %conflict - common package conflicts (one per line)
# %conflict.$cpt - $cpt component conflicts
#
# Internal file output:
#
# frontend.tmp - result of [platform] prefix removal
#
# Each backend should examine these files and construct the right
# output package.
#
# The frontend also sets the variable $components to be the list of
# file components defined
#
# Each of the %files.* files contains entries of the form
# f mode owner group flags file-path
# d mode owner group flags directory-path
# s mode owner group flags symlink-path symlink-target
#
# The mode/owner/group may be the special symbol '-' which means
# that the platform should choose an appropriate preference based on the
# path (this is usually the 'root' or 'bin' user/group or mode 755 or 644.
#
# If the symlink-target is omitted, then a readlink is performed and
# any $pre_destdir prefix is removed.
#
# The flags is either - or a sequence of letters. The letters mean:
# v - the file is volatile, and expected to change content during use
# m - missingok (do not warn if the file is missing during package removal)
#
pp_if_true=0
pp_if_false=0
#@ pp_frontend_init(): Set variables to their default values
pp_frontend_init () {
name=
version=
build_number=
summary="no summary"
description="No description"
copyright="Copyright 2018 One Identity LLC. ALL RIGHTS RESERVED."
#-- if the user supplied extra arguments on the command line
# then load them now.
pp_debug "pp_opt_init_vars=$pp_opt_init_vars"
test -n "$pp_opt_init_vars" && eval "$pp_opt_init_vars"
}
#@ pp_is_qualifier(): returns true if the arg is a qualifier expression
pp_is_qualifier () {
typeset ret
case "$1" in
"["*"]") ret=true;;
*) ret=false;;
esac
pp_debug "is_qualifier: $* -> $ret"
test $ret = true
}
#@ pp_eval_qualifier(): returns true if plat qual matches current plat
# Platform qualifiers match the following grammar
# '[' '!'? platform ( ',' platform )* ']'
# Returns true if the current platform is in the list of platforms.
# Starting with a '!' reverses the sense of the test.
# Special consequential qualifiers:
# [] - always false
# [!] - always true
pp_eval_qualifier () {
typeset ret
case "$1" in
"[!$pp_platform]"| \
"[!"*",$pp_platform]"| \
"[!$pp_platform,"*"]"| \
"[!"*",$pp_platform,"*"]") ret=false;;
"[!"*"]") ret=true;;
"[$pp_platform]"| \
"["*",$pp_platform]"| \
"[$pp_platform,"*"]"| \
"["*",$pp_platform,"*"]") ret=true;;
"["*"]") ret=false;;
*) pp_die "pp_eval_qualifier: bad qualifier '$1'"
esac
pp_debug "eval: $* -> $ret"
test true = $ret
}
#@ pp_frontend_if(): helper function for %if/%else/%endif logic
# Updates $pp_if_true and $pp_if_false variables which count
# the depth of true or false if/else branches. (Note that this
# counting scheme is unable to support an '%elif' construct,
# which really needs a stack.)
# The '%if' arguments can be by any one of:
# - 1, true, 0, false => explicit true or false
# - [qualifier] => see pp_eval_qualifier()
# - test-expr => given to the shell's test command
# The variables $pp_if_false and $pp_if_true are counters for if nesting.
# If $pp_if_false is non-zero then processing should be suppressed.
pp_frontend_if () {
typeset ifcmd ifret
ifcmd="$1";
shift
case "$ifcmd" in
%if) if test 0 = $pp_if_false; then
case "$*" in
true |1) pp_incr pp_if_true;;
false|0) pp_incr pp_if_false;;
*)
ifret=true
if pp_is_qualifier "$*"; then
pp_eval_qualifier "$*" || ifret=false
else
eval test "$@" || ifret=false
pp_debug "evaluating test $* -> $ifret"
fi
pp_incr pp_if_$ifret
;;
esac
else
pp_incr pp_if_false
fi;;
%else) test $# = 0 || pp_warn "ignoring argument to %else"
if test $pp_if_false -gt 1; then
: no change
elif test $pp_if_false = 1; then
pp_incr pp_if_true
pp_decr pp_if_false
elif test $pp_if_true = 0; then
pp_die "unmatched %else"
else
pp_incr pp_if_false
pp_decr pp_if_true
fi;;
%endif) test $# = 0 || pp_warn "ignoring argument to %endif"
if test $pp_if_false -gt 0; then
pp_decr pp_if_false
elif test $pp_if_true -gt 0; then
pp_decr pp_if_true
else
pp_die "unmatched %endif"
fi;;
*) pp_die "frontend_if: unknown cmd $ifcmd";;
esac
}
#@ pp_frontend()
# Processes a polypkg script on stdin. The output is
# a collection of output files named %*
# This function recognises section tags (eg %preun, %set, etc)
# and directs subsequent lines to the right output file.
# This function also
# - process [platform]/[!platform] tags on lines (eg [AIX])
# - removes comment lines
# - detects %set, %post, %preun etc sections
# - handles %if/%else/%endif logic
pp_frontend () {
typeset section newsection sed_word sed_ws line cpt svc
typeset section_enabled newsection_enabled s sed sed_candidate
section='%_initial'
newsection='%_initial'
section_enabled=:
newsection_enabled=:
sed_word="[a-zA-Z_][a-zA-Z_0-9]*"
sed_ws="[ ]"
#-- not all seds are created equal
sed=
for sed_candidate in ${PP_SED:-sed} /usr/xpg4/bin/sed; do
if echo 'foo' | $sed_candidate -ne '/^\(x\)*foo/p' | grep foo > /dev/null
then
sed="$sed_candidate"
break
fi
done
test -z "$sed" &&
pp_die "sed is broken on this system"
pp_lineno=0
#-- Note: this sed script should perform similar to pp_eval_qualifier()
$sed -e "/^#/s/.*//" \
-e "/^\\[!\\($sed_word,\\)*$pp_platform\\(,$sed_word\\)*\\]/s/.*//" \
-e "s/^\\[\\($sed_word,\\)*$pp_platform\\(,$sed_word\\)*\\]$sed_ws*//" \
-e "s/^\\[!\\($sed_word,\\)*$sed_word\\]$sed_ws*//" \
-e "/^\\[\\($sed_word,\\)*$sed_word\\]/s/.*//" \
-e "s/^%$sed_ws*/%/" \
-e "s/^$sed_ws/%\\\\&/" \
> $pp_wrkdir/frontend.tmp
#-- add an ignore section at the end to force section completion
echo '%ignore' >> $pp_wrkdir/frontend.tmp
echo >> $pp_wrkdir/frontend.tmp
exec 0<$pp_wrkdir/frontend.tmp
: > $pp_wrkdir/tmp
: > $pp_wrkdir/%fixup
while read -r line; do
#-- Convert leading double-% to single-%, or switch sections
pp_incr pp_lineno
pp_debug "line $pp_lineno: $line"
set -f
set -- $line
set +f
#pp_debug "line $pp_lineno: $*"
case "$line" in %*)
case "$1" in
%if|%else|%endif)
pp_debug "processing if directive $1"
pp_frontend_if "$@"
continue;;
esac
test 0 -ne $pp_if_false && continue # ignore lines %if'd out
case "$1" in
%set|%fixup|%ignore)
pp_debug "processing new section $1"
newsection="$1"; shift
newsection_enabled=:
if pp_is_qualifier "$1"; then
pp_eval_qualifier "$1" || newsection_enabled=false
shift
fi
test $# -eq 0 || pp_warn "ignoring extra arguments: $line"
continue;;
%pre|%post|%preun|%postup|%preup|%postun|%files|%depend|%check|%conflict)
pp_debug "processing new component section $*"
s="$1"; shift
if test $# -eq 0 || pp_is_qualifier "$1"; then
cpt=run
else
cpt="$1"
shift
fi
newsection="$s.$cpt"
newsection_enabled=:
if test $# -gt 0 && pp_is_qualifier "$1"; then
pp_eval_qualifier "$1" || newsection_enabled=false
shift
fi
test $# -eq 0 ||
pp_warn "ignoring extra arguments: $line"
case "$cpt" in
run|dbg|doc|dev)
$newsection_enabled && pp_add_component "$cpt";;
x-*) :;; # useful for discarding stuff
*) pp_error "unknown component: $1 $cpt";;
esac
continue;;
%pp)
newsection="%ignore"; shift
if test $# -gt 0; then
pp_set_api_version "$1"
shift
else
pp_error "%pp: missing version"
fi
test $# -gt 0 &&
pp_error "%pp: too many arguments"
continue;;
%service)
pp_debug "processing new service section $1 $2"
s="$1"; shift
if test $# -eq 0 || pp_is_qualifier "$1"; then
pp_error "$s: service name required"
svc=unknown
else
svc="$1"; shift
fi
newsection="$s.$svc"
newsection_enabled=:
if test $# -gt 0 && pp_is_qualifier "$1"; then
pp_eval_qualifier "$1" || newsection_enabled=false
shift
fi
test $# -eq 0 ||
pp_warn "ignoring extra arguments: $line"
$newsection_enabled && pp_add_service "$svc"
continue;;
%\\*)
pp_debug "removing leading %\\"
line="${line#??}"
pp_debug " result is <$line>"
set -f
set -- $line
set +f
;;
%%*)
pp_debug "removing leading %"
line="${line#%}"
set -f
set -- $line
set +f
;;
%*)
pp_error "unknown section $1"
newsection='%ignore'
newsection_enabled=:
continue;;
esac;;
esac
test 0 != $pp_if_false && continue # ignore lines %if'd out
pp_debug "section=$section (enabled=$section_enabled) newsection=$newsection (enabled=$newsection_enabled)"
#-- finish processing a previous section
if test x"$newsection" != x""; then
$section_enabled && case "$section" in
%ignore|%_initial)
pp_debug "leaving ignored section $section"
: ignore # guaranteed to be the last section
;;
%set)
pp_debug "leaving $section: sourcing $pp_wrkdir/tmp"
$pp_opt_debug && cat $pp_wrkdir/tmp >&2
. $pp_wrkdir/tmp
: > $pp_wrkdir/tmp
;;
%pre.*|%preun.*|%post.*|%postup.*|%preup.*|%postun.*|%depend.*|%check.*|%conflict.*|%service.*|%fixup)
pp_debug "leaving $section: substituting $pp_wrkdir/tmp"
# cat $pp_wrkdir/tmp >&2 # debugging
$pp_opt_debug && pp_substitute < $pp_wrkdir/tmp >&2
pp_substitute < $pp_wrkdir/tmp > $pp_wrkdir/tmp.sh
. $pp_wrkdir/tmp.sh >> $pp_wrkdir/$section ||
pp_error "shell error in $section"
rm -f $pp_wrkdir/tmp.sh
: > $pp_wrkdir/tmp
;;
esac
section="$newsection"
section_enabled="$newsection_enabled"
newsection=
fi
#-- ignore section content that is disabled
$section_enabled || continue
#-- process some lines in-place
case "$section" in
%_initial)
case "$line" in "") continue;; esac # ignore non-section blanks
pp_die "Ignoring text before % section introducer";;
%set|%pre.*|%preun.*|%post.*|%postup.*|%preup.*|%postun.*|%check.*|%service.*|%fixup)
pp_debug "appending line to \$pp_wrkdir/tmp"
echo "$line" >> $pp_wrkdir/tmp
;;
%files.*)
test $# -eq 0 && continue;
pp_files_expand "$@" >> $pp_wrkdir/$section
;;
%depend.*)
pp_debug "Adding explicit dependency $@ to $cpt"
echo "$@" >> $pp_wrkdir/%depend.$cpt
;;
%conflict.*)
pp_debug "Adding explicit conflict $@ to $cpt"
echo "$@" >> $pp_wrkdir/%conflict.$cpt
;;
esac
done
exec <&-
if test $pp_if_true != 0 -o $pp_if_false != 0; then
pp_die "missing %endif at end of file"
fi
pp_lineno=
pp_debug " name = $name"
pp_debug " version = $version"
pp_debug " summary = $summary"
pp_debug " description = $description"
pp_debug " copyright = $copyright"
pp_debug ""
pp_debug "\$pp_components: $pp_components"
pp_debug "\$pp_services: $pp_services"
}
#@ pp_set_api_version($v): change pp's behaviour to match the desired version
pp_set_api_version() {
case "$1" in
1.0) : ;;
*) pp_error "This version of polypackage is too old";;
esac
}