pkgsrc-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

pkg/42197: pkg_alternatives portability problems (with patch)



>Number:         42197
>Category:       pkg
>Synopsis:       pkg_alternatives portability problem with delimiter character
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    pkg-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Oct 19 00:05:01 +0000 2009
>Originator:     Louis Guillaume
>Release:        NetBSD 5.0_STABLE
>Organization:
        Zabrico
>Environment:
System: NetBSD maat.zabrico.com 5.0_STABLE NetBSD 5.0_STABLE (GENERIC) #8: Sun 
Oct 11 18:47:13 EDT 2009 
louis%maat.zabrico.com@localhost:/usr/obj/sys/arch/i386/compile/GENERIC i386
Architecture: i386
Machine: i386
>Description:
On some non-netbsd systems (OS X in particular), when pkg_alternatives uses
`tr' to delimit data in many of its functions, it chokes. This is because a
Latin-1 (0xac) character is used as a delimiter. If the locale is not
ISO-8859-1 or C, we end up with an error: "tr: Illegal byte sequence". 

It was discussed for a while on the mailing lists and the discussion went off
on a tangent about efficiency of shell command constructs etc. The thread is
here:

  http://mail-index.netbsd.org/pkgsrc-users/2008/07/20/msg007671.html


I refactored the pkg_alternatives.sh and wrapper.sh to remove the dependency
on the unusual character. I changed them to use awk for parsing the
configuration files. It works now and is no longer encumbered by the strange
use of a Latin-1 character. Hopefully this improves portability.

>How-To-Repeat:
     o Install pkgtools/pkg_alternatives on Mac OS X (Tiger, Leopard,
       Snow Leopard)
     o ensure the locale is en_US.UTF-8
     o try `pkg_alternatives status ruby18'. Most pkg_alternatives commands
       will fail.

>Fix:

Here is a cvs diff. I bumped the revision in the Makefile. Not sure if that
is the correct practice.

cvs diff: Diffing pkgtools/pkg_alternatives
Index: pkgtools/pkg_alternatives/Makefile
===================================================================
RCS file: /cvsroot/pkgsrc/pkgtools/pkg_alternatives/Makefile,v
retrieving revision 1.15
diff -u -r1.15 Makefile
--- pkgtools/pkg_alternatives/Makefile  9 Apr 2009 00:48:12 -0000       1.15
+++ pkgtools/pkg_alternatives/Makefile  18 Oct 2009 23:51:58 -0000
@@ -1,8 +1,8 @@
-# $NetBSD: Makefile,v 1.15 2009/04/09 00:48:12 joerg Exp $
 #
 
 DISTNAME=      pkg_alternatives-1.4
 CATEGORIES=    pkgtools
+PKGREVISION=   1
 MASTER_SITES=  # empty
 DISTFILES=     # empty
 
cvs diff: Diffing pkgtools/pkg_alternatives/files
Index: pkgtools/pkg_alternatives/files/pkg_alternatives.sh
===================================================================
RCS file: /cvsroot/pkgsrc/pkgtools/pkg_alternatives/files/pkg_alternatives.sh,v
retrieving revision 1.6
diff -u -r1.6 pkg_alternatives.sh
--- pkgtools/pkg_alternatives/files/pkg_alternatives.sh 15 Jan 2007 02:50:06 
-0000      1.6
+++ pkgtools/pkg_alternatives/files/pkg_alternatives.sh 18 Oct 2009 23:51:59 
-0000
@@ -56,11 +56,8 @@
     validate_package ${1}
     pkg=${PKG_DBDIR}/${1}*/+ALTERNATIVES
 
-    set -- $(cat ${pkg} | tr ' ' '?')
-    while [ ${#} -gt 0 ]; do
-        action_auto_wrapper $(echo ${1} | cut -d '?' -f 1)
-        shift
-    done
+    eval "$(awk '{ print "action_auto_wrapper " $1 }' $pkg )"
+
 }
 
 # -------------------------------------------------------------------------
@@ -161,11 +158,8 @@
     validate_package ${1}
     pkg=${PKG_DBDIR}/${1}*/+ALTERNATIVES
 
-    set -- $(cat ${pkg} | tr ' ' '?')
-    while [ ${#} -gt 0 ]; do
-        action_manual_wrapper $(echo ${1} | tr '?' ' ')
-        shift
-    done
+    eval "$(awk '{ print "action_manual_wrapper " $0 }' $pkg )"
+
 }
 
 # -------------------------------------------------------------------------
@@ -229,13 +223,10 @@
 # Each line should follow the semantics expected by action_register_wrapper.
 #
 action_register_package() {
+
     validate_args register ${#} -eq 1
+    eval "$(awk '{ print "action_register_wrapper " $0 }' $1 )"
 
-    set -- $(cat ${1} | tr ' ' '?')
-    while [ ${#} -gt 0 ]; do
-        action_register_wrapper $(echo ${1} | tr '?' ' ')
-        shift
-    done
 }
 
 # -------------------------------------------------------------------------
@@ -308,11 +299,10 @@
     validate_package ${1}
     pkg=${PKG_DBDIR}/${1}*/+ALTERNATIVES
 
-    set -- $(cat ${pkg} | tr ' ' '?')
-    while [ ${#} -gt 0 ]; do
-        action_status_wrapper $(echo ${1} | cut -d '?' -f 1)
-        shift
-    done
+    printf "\n    %s\n\n" "Wrapper alternatives for $1"
+    eval "$(awk '{ print "action_status_wrapper " $1 }' $pkg )"
+    echo
+
 }
 
 # -------------------------------------------------------------------------
@@ -322,6 +312,7 @@
 # Shows the current status for the given wrapper.
 #
 action_status_wrapper() {
+
     validate_args status ${#} -eq 1
     validate_wrapper ${1} yes
 
@@ -330,26 +321,28 @@
     sysconf=${Conf_Dir}/${wbase}
     userconf=~/.pkg_alternatives${Prefix}/${wbase}
 
-    [ $(id -un) = @ROOT_USER@ ] && userconf=
-    alts=$(cat ${userconf} ${sysconf} ${dbconf} 2>/dev/null | grep -v '^#' | \
-           tr ' ' '?')
+    flist=
+    [ -f "$userconf" ] && flist="$userconf"
+    [ -f "$sysconf" ]  && flist="$flist $sysconf"
+    [ -f "$dbconf" ]   && flist="$flist $dbconf"
 
-    found=
-    for a in ${alts}; do
-        prog=$(echo ${a} | cut -d '?' -f 1)
-        if [ -x ${prog} ]; then
-            found=$(echo ${a} | tr '?' ' ')
-            break
-        fi
-    done
+    [ $(id -un) = @ROOT_USER@ ] && userconf=
 
-    [ -n "${found}" ] ||
-        err "the wrapper \`${wbase}' exists but has no valid alternatives"
+    awk -v wbase="$wbase" -v prefix="$Prefix" '
+        BEGIN{
+          printf("      %s/%-20s %s ",prefix,wbase,"will actually execute")
+        }
+
+        !/^[ \t]*#/{
+          print
+        }
+
+        END{
+          if ( NR == 0 )
+              print "\n\n        (the wrapper " wbase " exists but has no 
alternatives.)\n\n"
+      }
+    ' $flist
 
-    echo "\`${wbase}' points to \`${found}'"
-    for a in $(echo ${alts} | tr ' ' '\n' | sort | uniq); do
-        echo "    candidate: $(echo ${a} | tr '?' ' ')"
-    done
 }
 
 # -------------------------------------------------------------------------
@@ -360,13 +353,10 @@
 # removes all associated alternatives from their respective wrappers.
 #
 action_unregister_package() {
+
     validate_args unregister ${#} -eq 1
+    eval "$(awk '{ print "action_unregister_wrapper " $0 }' $1 )"
 
-    set -- $(cat ${1} | tr ' ' '?')
-    while [ ${#} -gt 0 ]; do
-        action_unregister_wrapper $(echo ${1} | tr '?' ' ')
-        shift
-    done
 }
 
 # -------------------------------------------------------------------------
@@ -428,37 +418,17 @@
 # given wrapper, returns whether it is accepted or ignored.
 #
 filter() {
+
     [ ! -f @CONFDIR@/filter.conf ] && return 0
 
-    if [ ${Filter_Read} = no ]; then
-        Filter=$(cat @CONFDIR@/filter.conf | grep -v '^#' | tr ' ' '?')
-        Filter_Read=yes
-    fi
-
-    [ -z "${Filter}" ] && return 0
-
-    for f in ${Filter}; do
-        what=$(echo ${f} | cut -d '?' -f 1)
-        case ${what} in
-            accept)
-                name=$(echo ${f} | cut -d '?' -f 2- | tr '?' ' ')
-                if echo ${1} | grep "${name}" >/dev/null; then
-                    info "filter accepts \`${1}'"
-                    return 0
-                fi
-                ;;
-            ignore)
-                name=$(echo ${f} | cut -d '?' -f 2- | tr '?' ' ')
-                if echo ${1} | grep "${name}" >/dev/null; then
-                    info "filter ignores \`${1}'"
-                    return 1
-                fi
-                ;;
-            *)
-                warn "unknown filter type \`${what}'; ignoring"
-                ;;
-        esac
-    done
+    # the second field in filter.conf is a regular expression.
+
+    eval "$(awk '
+      /^[ \t]*#/ || /^[ \t]*$/ { next }
+      !/^accept/ && !/^ignore/ { print "warn No Such Filter Action: " $1 ; 
next }
+      { action=$1 ; sub ( "^" $1 FS "*" , "" ) }
+      to_check ~ $0 { print "info filter " action "s " to_check }
+    ' to_check="$1" @CONFDIR@/filter.conf)"
 
     true
 }
@@ -715,4 +685,3 @@
 
 main "${@}"
 
-# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4
Index: pkgtools/pkg_alternatives/files/wrapper.sh
===================================================================
RCS file: /cvsroot/pkgsrc/pkgtools/pkg_alternatives/files/wrapper.sh,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 wrapper.sh
--- pkgtools/pkg_alternatives/files/wrapper.sh  25 Jan 2005 13:00:46 -0000      
1.1.1.1
+++ pkgtools/pkg_alternatives/files/wrapper.sh  18 Oct 2009 23:51:59 -0000
@@ -1,4 +1,4 @@
-#!__SH__
+#!@SH@
 #
 # $NetBSD: wrapper.sh,v 1.1.1.1 2005/01/25 13:00:46 jmmv Exp $
 #
@@ -44,21 +44,20 @@
 else
     userfile=~/.pkg_alternatives/${wrapper}
 fi
-alternatives=$(cat ${userfile} __CONF_FILE__ __DB_FILE__ 2>/dev/null | \
-               grep -v "^#" | tr ' ' '?')
 
-found=
-for a in ${alternatives}; do
-    prog=$(echo ${a} | cut -d '?' -f 1)
-    if [ -x ${prog} ]; then
-        found=$(echo ${a} | tr '?' ' ')
-       break
-    fi
-done
+flist=
+[ -f "$userfile" ] && flist="$userfile"
+[ -f "__CONF_FILE__" ] && flist="$flist __CONF_FILE__"
+[ -f "__DB_FILE__" ]   && flist="$flist __DB_FILE__"
+
+eval "$(awk '{
+  cmd=$0
+  if ( "test -x " $1 " && echo 1" | getline ) {
+    print "exec " cmd " $@"
+    exit
+  }
+}' $flist )"
+    
 
-if [ -z "${found}" ]; then
-    echo "${progname}: no alternatives found" 1>&2
-    exit 1
-fi
-
-exec ${found} "${@}"
+echo "${progname}: no alternatives found" >&2
+exit 1

        



Home | Main Index | Thread Index | Old Index