rpmtool 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158
  1. #!/bin/sh
  2. ##
  3. ## rpmtool -- RPM Auxiliary Tool
  4. ## Copyright (c) 2000-2001 Ralf S. Engelschall <rse@engelschall.com>
  5. ##
  6. ## Permission to use, copy, modify, and distribute this software for
  7. ## any purpose with or without fee is hereby granted, provided that
  8. ## the above copyright notice and this permission notice appear in all
  9. ## copies.
  10. ##
  11. ## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  12. ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  13. ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  14. ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
  15. ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  16. ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  17. ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  18. ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  19. ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  20. ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  21. ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  22. ## SUCH DAMAGE.
  23. ##
  24. prog_name="rpmtool"
  25. prog_vers="1.0.2"
  26. prog_date="03-Aug-2001"
  27. if [ $# -eq 0 ]; then
  28. echo "$0:Error: invalid command line" 1>&2
  29. echo "$0:Hint: run \`$0 -h' for usage" 1>&2
  30. exit 1
  31. fi
  32. if [ ".$1" = ".-h" -o ".$1" = ".--help" ]; then
  33. echo "This is $prog_name, version $prog_vers ($prog_date)"
  34. echo "Copyright (c) 2000-2001 Ralf S. Engelschall <rse@engelschall.com>"
  35. echo ''
  36. echo "Usage: $prog_name [<options>] [<cmd-name> [<cmd-options>] [<cmd-args>]]"
  37. echo ''
  38. echo 'Available global <options>:'
  39. echo ' -d, --debug enable internal debugging'
  40. echo ' -v, --version display version information'
  41. echo ' -h, --help display usage help page (this one)'
  42. echo ''
  43. echo 'Available <cmd-name> [<cmd-options>] [<cmd-args>]:'
  44. echo ' platform'
  45. echo ' subst [-v] [-t] [-s] <sed-cmd> [...] -- <file> [...]'
  46. echo ' flags [-m] [-c] [-O] <tool>'
  47. echo ' files [-v] [-o <outfile>] [-r <buildroot>] [<filelist>]'
  48. echo ' user [-c] [-d] [-p <passwd>] [-n <realname>] [-d <homedir>]'
  49. echo ' [-s <shell>] [-u <min-uid>] <username>'
  50. echo ' group [-c] [-d] <groupname> <min-gid> [<username> ...]'
  51. echo ' signal [-v] [-t] [-n] [-c] [-d <delay>] [-p <pid>] [-m <pattern>] <sig> [<sig> ...]'
  52. echo ' config [-v] [-s] [-a] [-r] [-b <ext>] [-p <tagprefix>] [-t <tagname>] [-i <tagid>] <file>'
  53. echo ''
  54. exit 0
  55. fi
  56. if [ ".$1" = ".-v" -o ".$1" = ."--version" ]; then
  57. echo "$prog_name $prog_vers ($prog_date)"
  58. exit 0
  59. fi
  60. if [ ".$1" = ".-d" -o ".$1" = ."--debug" ]; then
  61. shift
  62. set -x
  63. fi
  64. tool="$1"
  65. shift
  66. arg_spec=""
  67. opt_spec=""
  68. gen_tmpfile=no
  69. # configure tool specific option parsing
  70. case $tool in
  71. platform )
  72. str_usage=""
  73. arg_spec="0="
  74. opt_spec=""
  75. ;;
  76. subst )
  77. str_usage="[-v] [-t] [-s] <sed-cmd> [...] -- <file> [...]"
  78. arg_spec="3+"
  79. opt_spec="v.t.s."
  80. opt_v=no
  81. opt_t=no
  82. opt_s=no
  83. gen_tmpfile=yes
  84. ;;
  85. flags )
  86. str_usage="[-m] [-c] [-O] <tool>"
  87. arg_spec="1="
  88. opt_spec="m.c.O."
  89. opt_m=no
  90. opt_c=no
  91. opt_O=no
  92. ;;
  93. files )
  94. gen_tmpfile=yes
  95. str_usage="[-v] [-o <outfile>] [-r <buildroot>] [<filelist>]"
  96. arg_spec="0+"
  97. opt_spec="v.o:r:"
  98. opt_v=no
  99. opt_o=''
  100. opt_r=''
  101. ;;
  102. user )
  103. str_usage="[-a] [-r] [-p <passwd>] [-n <realname>] [-d <homedir>] [-s <shell>] [-u <min-uid>] <username>"
  104. arg_spec="1="
  105. opt_spec="a.r.p:n:d:s:u:"
  106. opt_a=no
  107. opt_r=no
  108. opt_p=''
  109. opt_n=''
  110. opt_d=''
  111. opt_s=''
  112. opt_u=1000
  113. ;;
  114. group )
  115. str_usage="[-a] [-r] [-g <min-gid>] <groupname> [<username> ...]"
  116. arg_spec="1+"
  117. opt_spec="a.r.g:"
  118. opt_a=no
  119. opt_r=no
  120. opt_g=1000
  121. ;;
  122. signal )
  123. str_usage="[-v] [-t] [-n] [-c] [-d <delay>] [-p <pid>] [-m <pattern>] <sig> [<sig> ...]"
  124. arg_spec="1+"
  125. opt_spec="v.t.n.c.d:p:m:"
  126. opt_v=no
  127. opt_t=no
  128. opt_n=no
  129. opt_c=no
  130. opt_d=1
  131. opt_p=""
  132. opt_m=""
  133. ;;
  134. config )
  135. str_usage="[-v] [-s] [-a] [-r] [-b <ext>] [-p <tagprefix>] [-t <tagname>] [-i <tagid>] <file>"
  136. arg_spec="1="
  137. opt_spec="v.s.a.r.b:p:t:i:c:"
  138. opt_v=no
  139. opt_s=no
  140. opt_a=no
  141. opt_r=no
  142. opt_b=""
  143. opt_p="#"
  144. opt_t="OpenPKG"
  145. opt_i=""
  146. gen_tmpfile=yes
  147. ;;
  148. -* )
  149. echo "$prog_name:Error: unknown option \`$tool'" 2>&1
  150. echo "$prog_name:Hint: run \`$0 -h' for usage" 2>&1
  151. exit 1
  152. ;;
  153. * )
  154. echo "$prog_name:Error: unknown command \`$tool'" 2>&1
  155. echo "$prog_name:Hint: run \`$0 -h' for usage" 2>&1
  156. exit 1
  157. ;;
  158. esac
  159. # tool information
  160. toolcmd="$0 $tool"
  161. toolcmdhelp="$prog_name $tool"
  162. msgprefix="$prog_name:$tool"
  163. # parse argument specification string
  164. eval `echo $arg_spec |\
  165. sed -e 's/^\([0-9]*\)\([+=]\)/arg_NUMS=\1; arg_MODE=\2/'`
  166. # parse option specification string
  167. eval `echo h.$opt_spec |\
  168. sed -e 's/\([a-zA-Z0-9]\)\([.:+]\)/opt_MODE_\1=\2;/g'`
  169. # interate over argument line
  170. opt_PREV=''
  171. while [ $# -gt 0 ]; do
  172. # special option stops processing
  173. if [ ".$1" = ".--" ]; then
  174. shift
  175. break
  176. fi
  177. # determine option and argument
  178. opt_ARG_OK=no
  179. if [ ".$opt_PREV" != . ]; then
  180. # merge previous seen option with argument
  181. opt_OPT="$opt_PREV"
  182. opt_ARG="$1"
  183. opt_ARG_OK=yes
  184. opt_PREV=''
  185. else
  186. # split argument into option and argument
  187. case "$1" in
  188. -[a-zA-Z0-9]*)
  189. eval `echo "x$1" |\
  190. sed -e 's/^x-\([a-zA-Z0-9]\)/opt_OPT="\1";/' \
  191. -e 's/";\(.*\)$/"; opt_ARG="\1"/'`
  192. ;;
  193. -[a-zA-Z0-9])
  194. opt_OPT=`echo "x$1" | cut -c3-`
  195. opt_ARG=''
  196. ;;
  197. *)
  198. break
  199. ;;
  200. esac
  201. fi
  202. # eat up option
  203. shift
  204. # determine whether option needs an argument
  205. eval "opt_MODE=\$opt_MODE_${opt_OPT}"
  206. if [ ".$opt_ARG" = . -a ".$opt_ARG_OK" != .yes ]; then
  207. if [ ".$opt_MODE" = ".:" -o ".$opt_MODE" = ".+" ]; then
  208. opt_PREV="$opt_OPT"
  209. continue
  210. fi
  211. fi
  212. # process option
  213. case $opt_MODE in
  214. '.' )
  215. # boolean option
  216. eval "opt_${opt_OPT}=yes"
  217. ;;
  218. ':' )
  219. # option with argument (multiple occurances override)
  220. eval "opt_${opt_OPT}=\"\$opt_ARG\""
  221. ;;
  222. '+' )
  223. # option with argument (multiple occurances append)
  224. eval "opt_${opt_OPT}=\"\$opt_${opt_OPT} \$opt_ARG\""
  225. ;;
  226. * )
  227. echo "$msgprefix:Error: unknown option: \`-$opt_OPT'" 1>&2
  228. echo "$msgprefix:Hint: run \`$toolcmdhelp -h' or \`man $prog_name' for details" 1>&2
  229. exit 1
  230. ;;
  231. esac
  232. done
  233. if [ ".$opt_PREV" != . ]; then
  234. echo "$msgprefix:Error: missing argument to option \`-$opt_PREV'" 1>&2
  235. echo "$msgprefix:Hint: run \`$toolcmdhelp -h' or \`man $prog_name' for details" 1>&2
  236. exit 1
  237. fi
  238. # process help option
  239. if [ ".$opt_h" = .yes ]; then
  240. echo "Usage: $toolcmdhelp $str_usage"
  241. exit 0
  242. fi
  243. # complain about incorrect number of arguments
  244. case $arg_MODE in
  245. '=' )
  246. if [ $# -ne $arg_NUMS ]; then
  247. echo "$msgprefix:Error: invalid number of arguments (exactly $arg_NUMS expected)" 1>&2
  248. echo "$msgprefix:Hint: run \`$toolcmd -h' or \`man $prog_name' for details" 1>&2
  249. exit 1
  250. fi
  251. ;;
  252. '+' )
  253. if [ $# -lt $arg_NUMS ]; then
  254. echo "$msgprefix:Error: invalid number of arguments (at least $arg_NUMS expected)" 1>&2
  255. echo "$msgprefix:Hint: run \`$toolcmd -h' or \`man $prog_name' for details" 1>&2
  256. exit 1
  257. fi
  258. ;;
  259. esac
  260. # establish a temporary file on request
  261. if [ ".$gen_tmpfile" = .yes ]; then
  262. if [ ".$TMPDIR" != . ]; then
  263. tmpdir="$TMPDIR"
  264. elif [ ".$TEMPDIR" != . ]; then
  265. tmpdir="$TEMPDIR"
  266. else
  267. tmpdir="/tmp"
  268. fi
  269. tmpfile="$tmpdir/.$prog_name.$$"
  270. rm -f $tmpfile >/dev/null 2>&1
  271. touch $tmpfile
  272. fi
  273. # provide a few useful variables
  274. NL="
  275. "
  276. TAB=" "
  277. DIFS=" ${TAB}${NL}"
  278. # determine platform information
  279. platform_machine=`(uname -m) 2>/dev/null` ||\
  280. platform_machine=`(uname -p) 2>/dev/null` ||\
  281. platform_machine='unknown'
  282. platform_release=`(uname -r) 2>/dev/null` ||\
  283. platform_release='unknown'
  284. platform_system=`(uname -s) 2>/dev/null` ||\
  285. platform_system='unknown'
  286. platform_version=`(uname -v) 2>/dev/null` ||\
  287. platform_version='unknown'
  288. platform="${platform_machine}:${platform_system}:${platform_release}:${platform_version}"
  289. # dispatch into tools
  290. case $tool in
  291. platform )
  292. # provide unique platform id
  293. m=`echo "$platform_machine" | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
  294. s=`echo "$platform_system" | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
  295. r=`echo "$platform_release" | sed -e 's;-.*$;;'`
  296. echo "${m}-${s}${r}"
  297. ;;
  298. subst )
  299. # substitute variables (in-place)
  300. ops=""
  301. files=""
  302. isop=1
  303. for arg
  304. do
  305. if [ ".$arg" = ".--" ]; then
  306. isop=0
  307. continue
  308. fi
  309. if [ ".$isop" = .1 ]; then
  310. ops="$ops%$arg"
  311. else
  312. files="$files%$arg"
  313. fi
  314. done
  315. cmd='sed'
  316. OIFS="$IFS"; IFS="%"
  317. for op in $ops; do
  318. test ".$op" = . && continue
  319. cmd="$cmd -e '$op'"
  320. done
  321. IFS="$OIFS"
  322. for file in `IFS="%"; echo $files`; do
  323. test ".$file" = . && continue
  324. if [ ! -f $file ]; then
  325. echo "$msgprefix:Warning: file \`$file' not found" 1>&2
  326. continue
  327. fi
  328. if [ ".$opt_v" = .yes ]; then
  329. echo "patching file \`$file'" 1>&2
  330. fi
  331. if [ ".$opt_t" = .yes ]; then
  332. echo "\$ cp -p $file $file.orig"
  333. echo "\$ $cmd <$file.orig >$file"
  334. fi
  335. cp -p $file $file.orig
  336. eval "$cmd <$file.orig >$file"
  337. if [ ".$opt_s" = .yes ]; then
  338. if [ ".$opt_t" = .yes ]; then
  339. echo "\$ touch -r $file.orig $file"
  340. fi
  341. touch -r $file.orig $file
  342. fi
  343. done
  344. ;;
  345. flags )
  346. tool="$1"
  347. if [ ".$opt_m" = .yes ]; then
  348. isgmake=no
  349. if [ ".`$tool -v 2>/dev/null | grep 'GNU Make'`" != . ]; then
  350. isgmake=yes
  351. fi
  352. mflags=''
  353. if [ ".$isgmake" = .yes ]; then
  354. mflags="--no-print-directory"
  355. fi
  356. if [ ".$opt_O" = .yes ]; then
  357. case $platform in
  358. *:SunOS:5.*:* | *:OSF1:*:* )
  359. if [ ".$isgmake" = .yes ]; then
  360. n=`(/bin/uname -X) 2>/dev/null | grep -i NumCPU | awk '{ print $3; }'`
  361. if [ ".$n" != . ]; then
  362. if [ $n -gt 1 ]; then
  363. n=`expr $n \* 2`
  364. mflags="$mflags -j$n"
  365. fi
  366. fi
  367. fi
  368. ;;
  369. *:FreeBSD:4.*:* )
  370. n=`/sbin/sysctl hw.ncpu | awk '{ print $2; }'`
  371. if [ ".$n" != . ]; then
  372. if [ $n -gt 1 ]; then
  373. n=`expr $n \* 2`
  374. mflags="$mflags -j$n"
  375. if [ ".$isgmake" = .no ]; then
  376. mflags="$mflags -B"
  377. fi
  378. fi
  379. fi
  380. ;;
  381. *:NetBSD:1.5*:* )
  382. n=`/sbin/sysctl hw.ncpu | awk '{ print $3; }'`
  383. if [ ".$n" != . ]; then
  384. if [ $n -gt 1 ]; then
  385. n=`expr $n \* 2`
  386. mflags="$mflags -j$n"
  387. if [ ".$isgmake" = .no ]; then
  388. mflags="$mflags -B"
  389. fi
  390. fi
  391. fi
  392. ;;
  393. *:Linux:*:* )
  394. n=`cat /proc/cpuinfo | grep processor | wc -l | awk '{ print $1; }'`
  395. if [ ".$n" != . ]; then
  396. if [ $n -gt 1 ]; then
  397. n=`expr $n \* 2`
  398. mflags="$mflags -j$n"
  399. fi
  400. fi
  401. ;;
  402. *:HP-UX:*:* )
  403. n=1 # FIXME
  404. ;;
  405. esac
  406. fi
  407. echo "$mflags"
  408. elif [ ".$opt_c" = .yes ]; then
  409. isgcc=no
  410. if [ ".`$tool --version 2>/dev/null | egrep '(2.[789]|3.[01])'`" != . ]; then
  411. isgcc=yes
  412. fi
  413. cflags=''
  414. if [ ".$opt_O" = .yes ]; then
  415. if [ ".$isgcc" = .yes ]; then
  416. cflags="-O2 -pipe"
  417. else
  418. cflags="-O"
  419. fi
  420. fi
  421. echo "$cflags"
  422. fi
  423. ;;
  424. files )
  425. # if a Perl interpreter is available, we perform the operation
  426. # with it because Perl is a magnitude (factor 10!) faster than
  427. # what we can do here in Bourne-Shell.
  428. perl=''
  429. for dir in `echo $PATH | sed -e 's/:/ /g'` .; do
  430. for tool in perl5 perl miniperl; do
  431. if [ -f "$dir/$tool" ]; then
  432. perl="$dir/$tool"
  433. break
  434. fi
  435. done
  436. if [ ".$perl" != . ]; then
  437. break
  438. fi
  439. done
  440. if [ ".$perl" != . ]; then
  441. cat >$tmpfile <<'EOT'
  442. ##
  443. ## PERL IMPLEMENTATION (FAST)
  444. ##
  445. my $opt_v = 0;
  446. my $opt_o = '';
  447. my $opt_r = '';
  448. while ($ARGV[0] =~ m|^-(.)(.*)$|) {
  449. my ($opt, $arg) = ($1, $2);
  450. shift(@ARGV);
  451. unshift(@ARGV, $arg) if ($arg ne '');
  452. $opt_v = 1 if ($opt eq 'v');
  453. $opt_o = shift(@ARGV) if ($opt eq 'o');
  454. $opt_r = shift(@ARGV) if ($opt eq 'r');
  455. }
  456. # remember the build root in a reasonable short variable ;)
  457. my $br = "$opt_r";
  458. # read input file list
  459. my @L = ();
  460. if ($#ARGV == -1 or ($#ARGV == 0 and $ARGV[0] eq "-")) {
  461. # read file list from stdin
  462. while (<STDIN>) {
  463. s/\n$//s;
  464. push(@L, $_);
  465. }
  466. }
  467. else {
  468. # read file list from argument line
  469. @L = @ARGV;
  470. }
  471. # PASS 1: PREPARATION AND SYNTACTICAL EXPANSION
  472. if ($opt_v == 1) {
  473. print STDERR "rpmtool:files: pass 1 (preparation and syntactical expansions)\n";
  474. }
  475. my @T = ();
  476. my $l;
  477. foreach $l (@L) {
  478. # replace tabs with spaces, reduce multiple spaces to single
  479. # spaces, and remove leading and trailing spaces
  480. $l =~ s|[ \t\n]+| |sg;
  481. $l =~ s|^[ \t]+||sg;
  482. $l =~ s|[ \t]+$||sg;
  483. # move tags to end of entry for easier parsing
  484. 1 while ($l =~ s|^(%\S+) (.+)|$2 $1|);
  485. # use `:' as a dummy path for tag-only entries (like `%defattr')
  486. # to avoid special cases in the later processing
  487. if ($l =~ m|^%.+|) {
  488. $l = ": $l";
  489. }
  490. # split entry into path and optional tags
  491. my ($p, $t) = ($l =~ m|^(\S+)(.*)$|);
  492. # expand `{foo,bar,quux}' constructs in path (silent
  493. # assumtion to make life easier is that the constructs
  494. # occurs only once in a path!)
  495. if ($p =~ m|^(.*)\{([^\}]+)\}(.*)$|) {
  496. # split path into prolog, the set construct, and the epilog
  497. my ($pro, $set, $epi) = ($1, $2, $3);
  498. # repeat prolog and epilog for all elements in set
  499. my $x;
  500. foreach $x (split(/,/, $set)) {
  501. push(@T, "${pro}${x}${epi}${t}");
  502. }
  503. }
  504. else {
  505. # else just take over the entry as is
  506. push(@T, $l);
  507. }
  508. }
  509. @L = @T;
  510. # PASS 2: FILESYSTEM-BASED EXPANSIONS
  511. if ($opt_v == 1) {
  512. print STDERR "rpmtool:files: pass 2 (filesystem-based expansions)\n";
  513. }
  514. @T = ();
  515. foreach $l (@L) {
  516. # split entry into path and optional tags
  517. my ($p, $t) = ($l =~ m|^(\S*)(.*)$|);
  518. # expand...
  519. if (-d "$br$p" and $t !~ m|.*%dir.*|) {
  520. # expand path because it is not tagged with %dir
  521. my @X = `cd "$br$p" && find . -print`;
  522. my $x;
  523. foreach $x (@X) {
  524. $x =~ s|\n$||s;
  525. $x =~ s|^\.|$p|s;
  526. push(@T, "${x}${t}");
  527. }
  528. }
  529. else {
  530. # expand path wildcards (`*' and `[..]')
  531. # (if not wildcards are present, this doesn't harm)
  532. my @X = glob("$br$p");
  533. my $x;
  534. foreach $x (@X) {
  535. my $brqm = quotemeta($br);
  536. $x =~ s|^$brqm||s;
  537. push(@T, "${x}${t}");
  538. }
  539. }
  540. }
  541. @L = @T;
  542. # PASS 3: DUPLICATION REMOVAL AND CLEANUP
  543. if ($opt_v == 1) {
  544. print STDERR "rpmtool:files: pass 3 (duplication removal and cleanup)\n";
  545. }
  546. @T = ();
  547. foreach $l (@L) {
  548. # split entry into path and optional tags
  549. my ($p, $t) = ($l =~ m|^(\S*)(.*)$|);
  550. # add %dir tag if entry is a directory, but still not
  551. # tagged as such (else RPM would again expand it recursively)
  552. if (-d "$br$p") {
  553. if ($t !~ m|%dir|) {
  554. $t .= " %dir";
  555. }
  556. }
  557. # remove duplicate entries in already processed part
  558. # (but make sure we keep the entries with the dummy tags)
  559. if ($p ne ":") {
  560. my @T2 = ();
  561. foreach $t (@T) {
  562. my $pqm = quotemeta($p);
  563. next if ($t =~ m|^$pqm | or $t eq $p);
  564. push(@T2, $t);
  565. }
  566. @T = @T2;
  567. }
  568. # keep entry only if no %not tag is present
  569. # (else all entries are removed)
  570. if ($t !~ m|.*%not.*|) {
  571. push(@T, "${p}${t}");
  572. }
  573. }
  574. @L = @T;
  575. # write out new file list
  576. @T = ();
  577. foreach $l (@L) {
  578. $l =~ s|^(\S+) (.*)$|$2 $1|sg;
  579. $l =~ s|^\s+||s;
  580. $l =~ s|\s+$||s;
  581. $l =~ s|\s+:$||s;
  582. push(@T, $l);
  583. }
  584. @L = @T;
  585. if ($opt_o eq '' or $opt_o eq '-') {
  586. print STDOUT join("\n", @L)."\n";
  587. }
  588. else {
  589. open(FP, ">$opt_o");
  590. print FP join("\n", @L)."\n";
  591. close(FP);
  592. }
  593. EOT
  594. cmd="$perl $tmpfile";
  595. if [ ".$opt_v" = .yes ]; then
  596. cmd="$cmd -v"
  597. fi
  598. if [ ".$opt_o" != . ]; then
  599. cmd="$cmd -o \"$opt_o\""
  600. fi
  601. if [ ".$opt_r" != . ]; then
  602. cmd="$cmd -r \"$opt_r\""
  603. fi
  604. for arg
  605. do
  606. cmd="$cmd \"$arg\""
  607. done
  608. eval $cmd
  609. else
  610. ##
  611. ## BOURNE-SHELL IMPLEMENTATION (PORTABLE)
  612. ##
  613. # remember the build root in a reasonable short variable ;)
  614. br="$opt_r"
  615. # make sure filename expansion is disabled per default
  616. set -f
  617. # read input file list
  618. L=''
  619. if [ $# -eq 0 ] || [ $# -eq 1 -a ".$1" = ".-" ]; then
  620. # read file list from stdin
  621. L=`cat`
  622. else
  623. # read file list from argument line
  624. for arg
  625. do
  626. L="$L$NL$arg"
  627. done
  628. fi
  629. # PASS 1: PREPARATION AND SYNTACTICAL EXPANSION
  630. if [ ".$opt_v" = .yes ]; then
  631. echo "rpmtool:files: pass 1 (preparation and syntactical expansions)" 1>&2
  632. fi
  633. T=''
  634. OIFS="$IFS"; IFS="$NL"
  635. for l in $L; do
  636. [ ".$l" = . ] && continue
  637. # replace tabs with spaces, reduce multiple spaces to single
  638. # spaces, and remove leading and trailing spaces
  639. l=`echo "$l" | sed -e "s;${TAB}; ;g" -e 's; *; ;g' -e 's;^ *;;' -e 's; *$;;'`
  640. # move tags to end of entry for easier parsing
  641. while [ ".`echo \"$l\" | grep '^%[^ ]* .*'`" != . ]; do
  642. l=`echo "$l" | sed -e 's;^\(%[^ ]*\) \(.*\);\2 \1;'`
  643. done
  644. # use `:' as a dummy path for tag-only entries (like `%defattr')
  645. # to avoid special cases in the later processing
  646. if [ ".`echo \"$l\" | grep '^%.*'`" != . ]; then
  647. l=": $l"
  648. fi
  649. # split entry into path and optional tags
  650. eval `echo ".$l" | sed -e 's;^\.\([^ ]*\)\(.*\)$;p="\1" t="\2";'`
  651. # expand `{foo,bar,quux}' constructs in path (silent
  652. # assumtion to make life easier is that the constructs
  653. # occurs only once in a path!)
  654. if [ ".`echo \".$p\" | grep '^\..*{[^}]*}.*$'`" != . ]; then
  655. # split path into prolog, the set construct, and the epilog
  656. eval `echo ".$p" | sed -e 's;^\.\(.*\){\([^}]*\)}\(.*\)$;pro="\1" set="\2" epi="\3";'`
  657. # repeat prolog and epilog for all elements in set
  658. OIFS2="$IFS"; IFS=","
  659. for x in $set; do
  660. T="$T$NL${pro}${x}${epi}${t}"
  661. done
  662. IFS="$OIFS2"
  663. else
  664. # else just take over the entry as is
  665. T="$T$NL$l"
  666. fi
  667. done
  668. L="$T"
  669. IFS="$OIFS"
  670. # PASS 2: FILESYSTEM-BASED EXPANSIONS
  671. if [ ".$opt_v" = .yes ]; then
  672. echo "rpmtool:files: pass 2 (filesystem-based expansions)" 1>&2
  673. fi
  674. T=''
  675. OIFS="$IFS"; IFS="$NL"
  676. for l in $L; do
  677. [ ".$l" = . ] && continue
  678. # split entry into path and optional tags
  679. eval `echo ".$l" | sed -e 's;^\.\([^ ]*\)\(.*\)$;p="\1" t="\2";'`
  680. # expand...
  681. if [ -d "$br$p" -a ".`expr \".$t\" : '\..*%dir.*'`" = .0 ]; then
  682. # expand path because it is not tagged with %dir
  683. OIFS2="$IFS"; IFS="$DIFS"
  684. for x in `cd "$br$p" && find . -print | sed -e "s;^\\.;$p;"`; do
  685. T="$T$NL${x}${t}"
  686. done
  687. IFS="$OIFS2"
  688. else
  689. # expand path wildcards (`*' and `[..]')
  690. # (if not wildcards are present, this doesn't harm)
  691. OIFS2="$IFS"; IFS="$DIFS"
  692. for x in `(set +f; echo $br$p) | sed -e "s;^$br;;" -e "s; $br; ;g"`; do
  693. T="$T$NL${x}${t}"
  694. done
  695. IFS="$OIFS2"
  696. fi
  697. done
  698. IFS="$OIFS"
  699. L="$T"
  700. # PASS 3: DUPLICATION REMOVAL AND CLEANUP
  701. if [ ".$opt_v" = .yes ]; then
  702. echo "rpmtool:files: pass 3 (duplication removal and cleanup)" 1>&2
  703. fi
  704. T=''
  705. OIFS="$IFS"; IFS="$NL"
  706. for l in $L; do
  707. [ ".$l" = . ] && continue
  708. # split entry into path and optional tags
  709. eval `echo ".$l" | sed -e 's;^\.\([^ ]*\)\(.*\)$;p="\1" t="\2";'`
  710. # add %dir tag if entry is a directory, but still not
  711. # tagged as such (else RPM would again expand it recursively)
  712. if [ -d "$br$p" ]; then
  713. if [ ".`expr \".$t\" : '\..*%dir.*'`" = .0 ]; then
  714. t="$t %dir"
  715. fi
  716. fi
  717. # remove duplicate entries in already processed part
  718. # (but make sure we keep the entries with the dummy tags)
  719. if [ ".$p" != ".:" ]; then
  720. T=`echo "$T" | grep -v "^$p " | grep -v "^$p\$"`
  721. fi
  722. # keep entry only if no %not tag is present
  723. # (else all entries are removed)
  724. if [ ".`expr \".$t\" : '\..*%not.*'`" = .0 ]; then
  725. T="$T$NL${p}${t}"
  726. fi
  727. done
  728. IFS="$OIFS"
  729. L="$T"
  730. # write out new file list
  731. if [ ".$opt_o" = . -o ".$opt_o" = ".-" ]; then
  732. outcmd="cat"
  733. else
  734. outcmd="cat > $opt_o"
  735. fi
  736. echo "$L" |\
  737. sed -e '/^$/d' \
  738. -e 's;^\([^ ]*\) *\(.*\)$;\2 \1;g' \
  739. -e 's;^ *;;' \
  740. -e 's; *$;;' \
  741. -e 's; *:$;;' | eval $outcmd
  742. fi
  743. ;;
  744. user )
  745. # calling convention
  746. if [ ".$opt_a" = .no -a ".$opt_r" = .no ]; then
  747. echo "$msgprefix:Error: either -a or -r has to be given" 1>&2
  748. exit 1
  749. fi
  750. if [ ".$opt_a" = .yes -a ".$opt_r" = .yes ]; then
  751. echo "$msgprefix:Error: only -a or -r can be given" 1>&2
  752. exit 1
  753. fi
  754. user=$1
  755. # default values
  756. if [ ".$opt_n" = . ]; then
  757. opt_n="$user"
  758. fi
  759. if [ ".$opt_s" = . ]; then
  760. opt_s=`which false 2>/dev/null`
  761. if [ ".$opt_s" = . ]; then
  762. opt_s="/bin/false"
  763. fi
  764. fi
  765. if [ ".$opt_d" = . ]; then
  766. opt_d="/nowhere"
  767. fi
  768. # add user
  769. if [ ".$opt_a" = .yes ]; then
  770. exists=`grep "^$user:" /etc/passwd`
  771. if [ ".$exists" != . ]; then
  772. echo "$msgprefix:Error: user $user already exists" 1>&2
  773. exit 1
  774. fi
  775. # seek for next free uid
  776. uid=$opt_u
  777. ok=0
  778. while [ ".$ok" = .0 ]; do
  779. u_exists=`grep "^[^:]*:[^:]*:$uid:" /etc/passwd`
  780. g_exists=`grep "^[^:]*:[^:]*:$uid:" /etc/group`
  781. if [ ".$u_exists" = . -a ".$g_exists" = . ]; then
  782. ok=1
  783. break
  784. fi
  785. uid=`expr $uid + 1`
  786. done
  787. # add entry to passwd database
  788. case "$platform" in
  789. *:FreeBSD:[456].*:* | *:NetBSD:1.*:* )
  790. echo "${user}:*:${uid}:${uid}::0:0:${opt_n}:${opt_d}:${opt_s}" >>/etc/master.passwd
  791. (PATH="$PATH:/usr/sbin"; pwd_mkdb -p /etc/master.passwd)
  792. ;;
  793. *:Linux:2.*:* )
  794. echo "${user}:*:${uid}:${uid}::${opt_n}:${opt_d}:${opt_s}" >>/etc/passwd
  795. (PATH="$PATH:/usr/sbin"; pwconv)
  796. ;;
  797. *:SunOS:5.*:* )
  798. echo "${user}:*:${uid}:${uid}:${opt_n}:${opt_d}:${opt_s}" >>/etc/passwd
  799. (PATH="$PATH:/usr/sbin"; pwconv)
  800. ;;
  801. *:OSF1:5.*:* )
  802. echo "${user}:*:${uid}:${uid}:${opt_n}:${opt_d}:${opt_s}" >>/etc/passwd
  803. (PATH="$PATH:/usr/sbin"; mkpasswd /etc/passwd)
  804. ;;
  805. *:HP-UX:*:* )
  806. echo "${user}:*:${uid}:${uid}:${opt_n}:${opt_d}:${opt_s}" >>/etc/passwd
  807. ;;
  808. esac
  809. # add corresponding entry to group database
  810. echo "${user}:*:${uid}:${user}" >>/etc/group
  811. # remove user
  812. elif [ ".$opt_r" = .yes ]; then
  813. exists=`grep "^$user:" /etc/passwd`
  814. if [ ".$exists" = . ]; then
  815. echo "$msgprefix:Error: user $user does not exist" 1>&2
  816. exit 1
  817. fi
  818. # remove entry from passwd database
  819. case "$platform" in
  820. *:FreeBSD:[456].*:* | *:NetBSD:1.*:* )
  821. cp /etc/master.passwd /etc/master.passwd.old
  822. grep -v "^${user}:" /etc/master.passwd.old >/etc/master.passwd
  823. (PATH="$PATH:/usr/sbin"; pwd_mkdb -p /etc/master.passwd)
  824. rm -f /etc/master.passwd.old
  825. ;;
  826. *:Linux:2.*:* | *:SunOS:5.*:* )
  827. cp /etc/passwd /etc/passwd.old
  828. grep -v "^${user}:" /etc/passwd.old >/etc/passwd
  829. (PATH="$PATH:/usr/sbin"; pwconv)
  830. rm -f /etc/passwd.old
  831. ;;
  832. *:OSF1:5.*:* )
  833. cp /etc/passwd /etc/passwd.old
  834. grep -v "^${user}:" /etc/passwd.old >/etc/passwd
  835. (PATH="$PATH:/usr/sbin"; mkpasswd /etc/passwd)
  836. rm -f /etc/passwd.old
  837. ;;
  838. *:HP-UX:*:* )
  839. cp /etc/passwd /etc/passwd.old
  840. grep -v "^${user}:" /etc/passwd.old >/etc/passwd
  841. rm -f /etc/passwd.old
  842. ;;
  843. esac
  844. # remove corresponding entry from group database
  845. cp /etc/group /etc/group.old
  846. grep -v "^${user}:" /etc/group.old >/etc/group
  847. rm -f /etc/group.old
  848. fi
  849. ;;
  850. group )
  851. if [ ".$opt_a" = .no -a ".$opt_r" = .no ]; then
  852. echo "$msgprefix:Error: either -a or -r has to be given" 1>&2
  853. exit 1
  854. fi
  855. if [ ".$opt_a" = .yes -a ".$opt_r" = .yes ]; then
  856. echo "$msgprefix:Error: only -a or -r can be given" 1>&2
  857. exit 1
  858. fi
  859. group=$1
  860. # add group
  861. if [ ".$opt_a" = .yes ]; then
  862. exists=`grep "^$group:" /etc/group`
  863. if [ ".$exists" != . ]; then
  864. echo "$msgprefix:Error: group $group already exists" 1>&2
  865. exit 1
  866. fi
  867. # seek for next free gid
  868. gid=$opt_g
  869. ok=0
  870. while [ ".$ok" = .0 ]; do
  871. exists=`grep "^[^:]*:[^:]*:$gid:" /etc/group`
  872. if [ ".$exists" = . ]; then
  873. ok=1
  874. break
  875. fi
  876. gid=`expr $gid + 1`
  877. done
  878. # add entry to group database
  879. echo "${group}:*:${gid}:$*" >>/etc/group
  880. # remove group
  881. elif [ ".$opt_r" = .yes ]; then
  882. exists=`grep "^$group:" /etc/group`
  883. if [ ".$exists" = . ]; then
  884. echo "$msgprefix:Error: group $group does not exist" 1>&2
  885. exit 1
  886. fi
  887. # remove entry from group database
  888. cp /etc/group /etc/group.old
  889. grep -v "^${group}:" /etc/group.old >/etc/group
  890. rm -f /etc/group.old
  891. fi
  892. ;;
  893. signal )
  894. if [ ".$opt_p" = . -a ".$opt_m" = . ]; then
  895. echo "$msgprefix:Error: either option -p or -m has to be specified" 1>&2
  896. exit 1
  897. fi
  898. case "$platform" in
  899. *:FreeBSD:*:* | *:NetBSD:*:* )
  900. cmd0="ps -ax -o pid"
  901. cmd1="ps -ax -o command"
  902. cmd2="ps -ax -o pid,command"
  903. cmd3="ps -ax -o pid,ppid"
  904. ;;
  905. *:Linux:*:* | *:OSF1:5.*:* )
  906. cmd0="ps axo pid"
  907. cmd1="ps axo cmd"
  908. cmd2="ps axo pid,cmd"
  909. cmd3="ps axo pid,ppid"
  910. ;;
  911. *:SunOS:5.*:* )
  912. cmd0="ps -ef -o pid"
  913. cmd1="ps -ef -o args"
  914. cmd2="ps -ef -o pid,args"
  915. cmd3="ps -ef -o pid,ppid"
  916. ;;
  917. *:HP-UX:*:* )
  918. cmd0="ps -ef" # FIXME
  919. cmd1="ps -ef" # FIXME
  920. cmd2="ps -ef" # FIXME
  921. cmd3="ps -ef" # FIXME
  922. ;;
  923. esac
  924. # try all signals in order
  925. i=$#
  926. for sig in "$@"; do
  927. # check whether program is still running/active
  928. active=""
  929. if [ ".$opt_p" != . ]; then
  930. active=`$cmd0 | grep "$opt_p" | grep -v grep | grep -v rpmtool`
  931. elif [ ".$opt_m" != . ]; then
  932. active=`$cmd1 | grep "$opt_m" | grep -v grep | grep -v rpmtool`
  933. fi
  934. if [ ".$active" = . ]; then
  935. break
  936. fi
  937. # send signal to program
  938. if [ ".$opt_p" != . ]; then
  939. pids="$opt_p"
  940. elif [ ".$opt_m" != . ]; then
  941. pids=`$cmd2 | sed -e "s;^[ ${TAB}]*;;" | egrep "[0-9]* .*$opt_m" |\
  942. grep -v grep | grep -v rpmtool |\
  943. awk '{ printf("%s\n", $1); }'`
  944. fi
  945. for pid in $pids; do
  946. if [ ".$opt_v" = .yes ]; then
  947. echo "sending $sig signal to process $pid"
  948. fi
  949. if [ ".$opt_t" = .yes ]; then
  950. echo "kill -$sig $pid"
  951. fi
  952. if [ ".$opt_n" = .no ]; then
  953. eval "kill -$sig $pid"
  954. fi
  955. done
  956. # optionally send signal to childs of program
  957. if [ ".$opt_c" = .yes ]; then
  958. for pid in $pids; do
  959. cpids=`$cmd3 | sed -e "s;^[ ${TAB}]*;;" | egrep "[0-9]* $pid" |\
  960. grep -v grep | grep -v rpmtool |\
  961. awk '{ printf("%s\n", $1); }'`
  962. for cpid in $cpids; do
  963. if [ ".$opt_v" = .yes ]; then
  964. echo "sending $sig signal to child process $cpid"
  965. fi
  966. if [ ".$opt_t" = .yes ]; then
  967. echo "kill -$sig $cpid"
  968. fi
  969. if [ ".$opt_n" = .no ]; then
  970. eval "kill -$sig $cpid >/dev/null 2>&1"
  971. fi
  972. done
  973. done
  974. fi
  975. # perform optional delay
  976. i=`expr $i - 1`
  977. if [ $i -gt 0 ]; then
  978. if [ ".$opt_d" != . -a ".$opt_d" != . ]; then
  979. sleep $opt_d
  980. fi
  981. fi
  982. done
  983. ;;
  984. config )
  985. # usage consistency
  986. if [ ".$opt_a" = .no -a ".$opt_r" = .no ]; then
  987. echo "$msgprefix:Error: either option -a or -r has to be specified" 1>&2
  988. exit 1
  989. fi
  990. configfile="$1"
  991. # determine block markers
  992. block_start="${opt_p}<${opt_t}"
  993. if [ ".$opt_i" != . ]; then
  994. block_start="${block_start} id=\"${opt_i}\""
  995. fi
  996. block_start="${block_start}>"
  997. block_end="${opt_p}</${opt_t}>"
  998. # slash-escaped versions of block markers (for sed(3) call)
  999. block_start_esc=`echo "$block_start" | sed -e 's;/;\\\\/;g'`
  1000. block_end_esc=`echo "$block_end" | sed -e 's;/;\\\\/;g'`
  1001. # determine backup extension
  1002. case "X$opt_b" in
  1003. X ) ext=".bak" ;;
  1004. X.* ) ext="$opt_b" ;;
  1005. X* ) ext=".$opt_b" ;;
  1006. esac
  1007. # check for block in config file
  1008. if [ -f $configfile ]; then
  1009. check=`grep "^${block_start}" $configfile`
  1010. else
  1011. touch $configfile
  1012. check=""
  1013. fi
  1014. # add entry
  1015. if [ ".$opt_a" = .yes ]; then
  1016. if [ ".$check" != . ]; then
  1017. if [ ".$opt_s" = .yes ]; then
  1018. exit 0
  1019. else
  1020. echo "$msgprefix:Error: config entry already exists" 1>&2
  1021. exit 1
  1022. fi
  1023. fi
  1024. cp $configfile $configfile$ext
  1025. echo "${block_start}" >$tmpfile
  1026. cat >>$tmpfile
  1027. echo "${block_end}" >>$tmpfile
  1028. cat $tmpfile >>$configfile
  1029. # remove entry
  1030. elif [ ".$opt_r" = .yes ]; then
  1031. if [ ".$check" = . ]; then
  1032. if [ ".$opt_s" = .yes ]; then
  1033. exit 0
  1034. else
  1035. echo "$msgprefix:Error: config entry does not exist" 1>&2
  1036. exit 1
  1037. fi
  1038. fi
  1039. cp $configfile $configfile$ext
  1040. sed -e "/^${block_start_esc}/,/^${block_end_esc}/d" \
  1041. <$configfile$ext >$configfile
  1042. fi
  1043. # verbosity
  1044. if [ ".$opt_v" = .yes ]; then
  1045. (diff -u1 $configfile$ext $configfile >$tmpfile) 2>/dev/null
  1046. if [ ".`cat $tmpfile`" = . ]; then
  1047. (diff -C1 $configfile$ext $configfile >$tmpfile) 2>/dev/null
  1048. if [ ".`cat $tmpfile`" = . ]; then
  1049. if [ ".$opt_s" = .no ]; then
  1050. echo "$msgprefix:Warning: unable to show difference for config file \`$configfile'" 1>&2
  1051. fi
  1052. fi
  1053. fi
  1054. echo "editing $configfile:"
  1055. cat $tmpfile
  1056. fi
  1057. # optionally remove backup file
  1058. if [ ".$opt_b" = . ]; then
  1059. rm -f $configfile$ext
  1060. fi
  1061. ;;
  1062. esac
  1063. # cleanup
  1064. if [ ".$gen_tmpfile" = .yes ]; then
  1065. rm -f $tmpfile >/dev/null 2>&1
  1066. fi
  1067. # die gracefully ;)
  1068. exit 0