rpmtool 39 KB

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