[PATCH] portmaster with SU_CMD

Stefan Sperling stsp at stsp.name
Sun Nov 11 14:36:52 PST 2007


Hi Doug,

here is a patch to make portmaster usable together with the
SU_CMD feature in /etc/make.conf.

I have the following setup:

	* directories in /usr/obj are writable by group "wobj"
	* directories in /usr/ports are writable by group "wports"
	* my user is in both of these groups (a single group could
	  be used for both directories as well, it would not make
	  a difference)
	* my user is in group wheel and sudoers allows users
	  in that group to run anything

In /etc/make.conf, I have: SU_CMD=/usr/local/sbin/sucmd.sh

This script contains:

	#!/bin/sh

	if [ -x /usr/local/bin/sudo ]
	then
		/usr/local/bin/sudo /bin/sh -c "$1"
	else
		/usr/bin/su root -c "$1"
	fi

I use that script so I don't have to change the SU_CMD setting
to update sudo, otherwise you get a chicken-and-egg problem.

A setup like this works fine with portupgrade, because it has
a -s switch that makes it run 'sudo' for all commands that
need root privileges.

On day, when portupgrade started segfaulting at me for no
apparent reason while closing its binary port database,
I looked for alternatives and found portmaster.

It looked much nicer than portupgrade to me, but only
supported running entirely as root.

So I hacked the script and added a -S flag that users can
use to specify a command that should be used to run commands
that need root privileges:

	portmaster -S sudo -a

I've been using this for a while now. I think that by now I have
found all places that need a "$SU_CMD" prefix, at least with respect
to my setup. This basically means any command that modifies things
outside of /usr/obj and /usr/ports, i.e. those modifying things in
/usr/local or /var/db/pkg.

It has been working fine for me for a few weeks now, so I thought
I might share it in case you or anyone else is interested.
If you don't want to apply this patch upstream I have no problem
maintaining it in my own tree.

Note though that the patch also fixes two cases where
	'command1 && command2; command3'
is run, while the indention suggests
	'command1 && (command2; command3)'
See patch to files/portmaster.sh.in, hunk  @@ -269,14 +271,13 @@ .
You might want to take a look at this even if you don't care about
the -S flag.

Thanks for a great port management tool!





Index: files/portmaster.8
===================================================================
RCS file: /usr/ncvs/ports/ports-mgmt/portmaster/files/portmaster.8,v
retrieving revision 1.11
diff -u -r1.11 portmaster.8
--- files/portmaster.8	27 May 2007 08:10:54 -0000	1.11
+++ files/portmaster.8	26 Oct 2007 20:27:54 -0000
@@ -35,6 +35,7 @@
 .Op Fl -force-config CGgntvw [B|b] [uf|i] [D|d]
 .Op Fl m Ar arguments for make
 .Op Fl x Ar glob pattern to exclude from building
+.Op Fl S Ar command to use to run commands that need root privileges
 .Nm
 .Op Common Flags
 .Ar full name of port directory in /var/db/pkg
@@ -233,6 +234,9 @@
 avoid building ports as dependencies that match this pattern
 .It Fl p Ar port directory in /usr/ports
 specify the full path to a port directory
+.It Fl S Ar command
+specify a command to use to run commands that need root
+privileges (e.g. su or sudo)
 .It Fl -show-work
 show what dependent ports are, and are not installed (implies
 .Fl t ) .
@@ -327,6 +331,7 @@
 .Dl "portmaster -r fooport-1.23"
 .Dl "portmaster -o emulators/linux_base-fc4 linux_base-8-8.0_15"
 .Dl "portmaster -x cvsup -f -a"
+.Dl "portmaster -S /usr/local/bin/sudo -a"
 .Pp
 .Dl "portmaster -L |"
 .Dl "egrep -B1 'ew version|Aborting|installed|dependencies' |"
Index: files/portmaster.sh.in
===================================================================
RCS file: /usr/ncvs/ports/ports-mgmt/portmaster/files/portmaster.sh.in,v
retrieving revision 1.25
diff -u -r1.25 portmaster.sh.in
--- files/portmaster.sh.in	31 Oct 2007 08:57:03 -0000	1.25
+++ files/portmaster.sh.in	4 Nov 2007 12:10:30 -0000
@@ -34,6 +34,7 @@
 	echo "Common flags: [--force-config] [-CGgntvw B|b uf|i D|d]"
 	echo "    [-m <arguments for make>]"
 	echo "    [-x <glob pattern to exclude from building>]"
+	echo "    [-S <command to use to run commands that need root privileges>]"
 	echo "${0##*/} [Common flags] <full name of port directory in $pdb>"
 	echo "${0##*/} [Common flags] <full path to $pd/foo/bar>"
 	echo "${0##*/} [Common flags] Multiple full names/paths from $pdb|$pd"
@@ -76,6 +77,7 @@
 	echo '-d always clean distfiles'
 	echo "-m <arguments for the 'make' command line>"
 	echo "-x <avoid building ports as dependencies that match this pattern>"
+	echo "-S <command to use to run commands that need root privileges>"
 	echo ''
 	echo '--show-work list what ports are and would be installed'
 	echo ''
@@ -228,7 +230,7 @@
 
 		if [ -n "$RESTART" -o -n "$FORCE" ]; then
 			if [ -z "$TRAP" ]; then
-			find $pdb -type f -name PM_UPGRADE_DONE_FLAG -delete
+			$SU_CMD find $pdb -type f -name PM_UPGRADE_DONE_FLAG -delete
 			fi
 		fi
 
@@ -269,14 +271,13 @@
 	tempfile=`mktemp -t tempfile-${new_port}`
 
 	sed "s/@pkgdep $1/@pkgdep $2/" $dep_port_contents > $tempfile &&
-	    mv $tempfile $pdb/$dep_port/+CONTENTS
-	    chmod 644 $pdb/$dep_port/+CONTENTS
+	    ($SU_CMD mv $tempfile $pdb/$dep_port/+CONTENTS
+	    $SU_CMD chmod 644 $pdb/$dep_port/+CONTENTS)
 
 	if [ -n "$oldportdir" ]; then
 		sed "s%N:${oldportdir}\$%N:${newportdir}%" $dep_port_contents > $tempfile &&
-		    mv $tempfile $pdb/$dep_port/+CONTENTS
-		    chmod 644 $pdb/$dep_port/+CONTENTS
-
+		    ($SU_CMD mv $tempfile $pdb/$dep_port/+CONTENTS
+		    $SU_CMD chmod 644 $pdb/$dep_port/+CONTENTS)
 	fi
 }
 
@@ -875,13 +876,13 @@
 	pkgrep=`make $PM_MAKE_ARGS -f/usr/share/mk/bsd.port.mk -VPKGREPOSITORY`
 	[ -n "$pkgrep" ] || fail 'The value of PKGREPOSITORY cannot be empty'
 	export pkgrep
-	mkdir -p $pkgrep
+	$SU_CMD mkdir -p $pkgrep
 }
 
 backup_package () {
 	echo "===>>> Creating a backup package for old version $1"
 	cd $pkgrep || fail "Cannot cd into the $pkgrep directory for backup"
-	if pkg_create -b $1; then
+	if $SU_CMD pkg_create -b $1; then
 		echo "	===>>> Package can be found in $pkgrep"
 	else
 		local PROCEED
@@ -994,7 +995,7 @@
 fi
 
 # Save switches for potential child processes
-while getopts 'BCDGLRabde:fghilm:nop:r:stuvwx:' COMMAND_LINE_ARGUMENT ; do
+while getopts 'BCDGLRabde:fghilm:nop:r:sS:tuvwx:' COMMAND_LINE_ARGUMENT ; do
 	case "${COMMAND_LINE_ARGUMENT}" in
 	B)	NO_BACKUP=yes; ARGS="-B $ARGS" ;;
 	C)	DONT_PRE_CLEAN=yes; ARGS="-C $ARGS" ;;
@@ -1023,6 +1024,7 @@
 	p)	portdir="${OPTARG#$pd/}" ; portdir=${portdir%/} ;;
 	r)	UPDATE_REQ_BYS=yes; upg_port=$OPTARG ;;
 	s)	CLEAN_STALE=yes ;;
+	S)	SU_CMD=$OPTARG; ARGS="-S $OPTARG $ARGS" ;;
 	t)	RECURSE_THOROUGH=yes; ARGS="-t $ARGS" ;;
 	u)	UNATTENDED=yes; ARGS="-u $ARGS" ;;
 	v)	VERBOSE=yes; ARGS="-v $ARGS" ;;
@@ -1134,8 +1136,8 @@
 
 		find_dl_distfiles $origin
 
-		echo "===>>> Running pkg_delete -f $EXPUNGE"
-		pkg_delete -f $EXPUNGE
+		echo "===>>> Running $SU_CMD pkg_delete -f $EXPUNGE"
+		$SU_CMD pkg_delete -f $EXPUNGE
 		delete_dist_list
 		if [ -z "$DONT_SCRUB_DISTFILES" ]; then
 			delete_all_distfiles $origin
@@ -1184,8 +1186,8 @@
 
 			find_dl_distfiles $origin
 
-			echo "===>>> Running pkg_delete -f $iport"
-			pkg_delete -f ${iport}
+			echo "===>>> Running $SU_CMD pkg_delete -f $iport"
+			$SU_CMD pkg_delete -f ${iport}
 			delete_dist_list
 			if [ -z "$DONT_SCRUB_DISTFILES" ]; then
 				delete_all_distfiles $origin
@@ -1195,7 +1197,7 @@
 		*) echo -n "	===>>> Remove empty +REQUIRED_BY file? [n] "
 			read DELORNOT
 			case "$DELORNOT" in
-			[yY])	rm -f $file ;;
+			[yY])	$SU_CMD rm -f $file ;;
 			*)	do_not_delete="${do_not_delete}${iport}:" ;;
 			esac
 			;;
@@ -1743,25 +1745,25 @@
 
 	if [ -n "$SAVE_SHARED" ]; then
 		ldconfig_out=`mktemp -t f-${PARENT_PID}-ldconfig`
-		ldconfig -r | sed 's#.* ##' |
-		    grep -v ^${PORTS_PREFIX}/lib/compat > $ldconfig_out
+		$SU_CMD /bin/sh -c "ldconfig -r | sed 's#.* ##' | \
+		    grep -v ^${PORTS_PREFIX}/lib/compat > $ldconfig_out"
 
-		mkdir -p ${PORTS_PREFIX}/lib/compat/pkg
+		$SU_CMD mkdir -p ${PORTS_PREFIX}/lib/compat/pkg
 
 		for file in `pkg_info -q -L $upg_port | sort - $ldconfig_out | \
 		    uniq -d`; do
-			cp -p $file ${PORTS_PREFIX}/lib/compat/pkg/
+			$SU_CMD cp -p $file ${PORTS_PREFIX}/lib/compat/pkg/
 		done
-		ldconfig -m ${PORTS_PREFIX}/lib/compat/pkg
+		$SU_CMD ldconfig -m ${PORTS_PREFIX}/lib/compat/pkg
 	fi
 
-	pkg_delete -f $upg_port || fail 'pkg_delete failed'
+	$SU_CMD pkg_delete -f $upg_port || fail 'pkg_delete failed'
 	delete_dist_list
 
 	if [ -n "$REPLACE_ORIGIN" ]; then
 		installed_newport=`iport_from_origin ${newportdir}`
 		if [ -n "$installed_newport" ]; then
-			pkg_delete -f $installed_newport
+			$SU_CMD pkg_delete -f $installed_newport
 			delete_dist_list
 		fi
 	fi
@@ -1783,11 +1785,11 @@
 # Remove saved libs that match newly installed files
 pkg_info -q -L $new_port | while read file; do
 	if [ -e "${PORTS_PREFIX}/lib/compat/pkg/${file##*/}" ]; then
-		unlink ${PORTS_PREFIX}/lib/compat/pkg/${file##*/}
+		$SU_CMD unlink ${PORTS_PREFIX}/lib/compat/pkg/${file##*/}
 	fi
 done
 test -d "${PORTS_PREFIX}/lib/compat/pkg" &&
-    ldconfig -m ${PORTS_PREFIX}/lib/compat/pkg
+    $SU_CMD ldconfig -m ${PORTS_PREFIX}/lib/compat/pkg
 
 allfiles=`make $PM_MAKE_ARGS -V ALLFILES`
 if [ ! "$allfiles" = ' ' ]; then
@@ -1796,16 +1798,16 @@
 	# See http://www.freebsd.org/cgi/query-pr.cgi?pr=106483
 	dist_list=`make BEFOREPORTMK=yes $PM_MAKE_ARGS -V OPTIONSFILE`
 	dist_list="${dist_list%options}distfiles"
-	mkdir -p ${dist_list%/distfiles}
+	$SU_CMD mkdir -p ${dist_list%/distfiles}
 	ds=`make BEFOREPORTMK=yes $PM_MAKE_ARGS -V DIST_SUBDIR`
 	test -n "$ds" && ds="${ds}/"
 	distinfo=`make $PM_MAKE_ARGS -V MD5_FILE`
-	echo '# Added by portmaster' > $dist_list
+	$SU_CMD /bin/sh -c "echo '# Added by portmaster' > $dist_list"
 	for file in $allfiles; do
 		size=`grep "^SIZE (${ds}${file})" $distinfo | cut -f4 -d' '`
 		sha256=`grep "^SHA256 (${ds}${file})" $distinfo | cut -f4 -d' '`
 		md5=`grep "^MD5 (${ds}${file})" $distinfo | cut -f4 -d' '`
-		echo "DISTFILE:${ds}${file}:SIZE=${size}:SHA256=${sha256}:MD5=${md5}" >> $dist_list
+		$SU_CMD /bin/sh -c "echo "DISTFILE:${ds}${file}:SIZE=${size}:SHA256=${sha256}:MD5=${md5}" >> $dist_list"
 	done
 fi
 
@@ -1848,17 +1850,17 @@
 	done < $req_deps
 }
 	update_dep_entries
-	mv $req_deps $pdb/$new_port/+REQUIRED_BY
+	$SU_CMD mv $req_deps $pdb/$new_port/+REQUIRED_BY
 	unset req_deps
-	chmod 644 $pdb/$new_port/+REQUIRED_BY
+	$SU_CMD chmod 644 $pdb/$new_port/+REQUIRED_BY
 
 	if [ -n "$REPLACE_ORIGIN" ]; then
 		req_deps=`mktemp -t req-deps-${short_port}`
 
 		grep -l DEPORIGIN:$newportdir$ $pdb/*/+CONTENTS |
-		    cut -f 5 -d '/' | sort -u > $req_deps
+		    cut -f 5 -d '/' | $SU_CMD sort -u > $req_deps
 		update_dep_entries $new_port
-		cat $req_deps >> $pdb/$new_port/+REQUIRED_BY
+		$SU_CMD cat $req_deps >> $pdb/$new_port/+REQUIRED_BY
 	fi
 fi
 
@@ -1872,7 +1874,7 @@
     DISPLAY_LIST="${DISPLAY_LIST}$new_port/+DISPLAY "
 
 if [ -n "$URB_YES" -o -n "$UPDATE_REQ_BYS" -o -n "$FORCE" ]; then
-	touch $pdb/$new_port/PM_UPGRADE_DONE_FLAG
+	$SU_CMD touch $pdb/$new_port/PM_UPGRADE_DONE_FLAG
 fi
 
 if [ -z "$DONT_SCRUB_DISTFILES" ]; then

-- 
stefan
http://stsp.name                                         PGP Key: 0xF59D25F0
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 187 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-ports/attachments/20071111/8c6b21e2/attachment.pgp


More information about the freebsd-ports mailing list