Nicolas Williams wrote: > > svcprop(1) does a pretty heroic job of escaping shell metachars from > property values. It's even heroic about newlines in property values > > Unfortunately the way it deals with multiple values ruins that heroism: > > % svcprop -t -c -p config someservice > config/bar astring d\ > \ c e > % > > Quick: how many values is that? > > In my case it was *two*. Bet you couldn't tell. > > I'd rather svcprop(1) had an option to print multiple values like so: > > % svcprop -m -c -p config someservice > config/bar astring d\ > \ c > config/bar astring e > % > > What say ye? I'll file the fasttrack and implement it even. > > BTW, in ksh (93, but this can be trivially adapted to 88) one could then > easily deal with this output via a function like: [snip] > (Yes, Roland can probably trim that doesn quite a bit.) > > % print "config/foobar astring foo\\^Jbar"|readprop > % print "config/foobar astring does it\\^Jwork?"|readprop > % print -r -- "${config.foobar}" > ( > typ=astring > typeset -a val=( > $'foo\nbar' > $'ick\nick' > $'does it\nwork?' > ) > ) > %
Technically it may be easier to add an option to "svcprop" which generates output like the http://svn.genunix.org/repos/on/branches/ksh93/gisburn/scripts/svcproptree1.ksh script. Note that the script has multiple output formats - one being a variable _tree_ and another format shows this tree as a list format (which makes it useable from "awk", "sed" or "perl"). And my idea is to provide a) an interface library (libcompoundvar.so.1) to write and read these two formats and then provide a standalone utility to re-format the data, for example into XML, "perl"'s native variable format... or an array format where the "tree variable name" is an array index etc. the result would be something small, efficient and _very_ flexible. And it would be extensible, too. I've attached two sample output of the script: 1. "svcproptree1_finger_tree_output.txt" is the output of $ svcproptree1.ksh '*finger*' tree # - which is a compound variable 2. "svcproptree1_finger_list_output.txt" is the output of $ svcproptree1.ksh '*finger*' list # - which is the same data in a list format. Technically [1] and [2] can be used directly in shells like "ksh93" and stuff like "perl" ; [2] is more suiteable for "awk"/"sed". And as said we should create an intermediate filter tool to a) filter variables in the tree/list view based on patterns and b) reformat the output into other formats like XML. As a result we would really have something which is one solution which matches all needs listed in this email thread and the matching discussion in sysadmin-discuss@ ---- Bye, Roland -- __ . . __ (o.\ \/ /.o) roland.mainz at nrubsig.org \__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer /O /==\ O\ TEL +49 641 7950090 (;O/ \/ \O;) -------------- next part -------------- svc.proptree[network/finger:default/].properties[general/enabled].datatype=boolean svc.proptree[network/finger:default/].properties[general/enabled].value=true svc.proptree[network/finger:default/].properties[general/enabled].valuelist=false svc.proptree[network/finger:default/].properties[general/entity_stability].datatype=astring svc.proptree[network/finger:default/].properties[general/entity_stability].value=Unstable svc.proptree[network/finger:default/].properties[general/entity_stability].valuelist=false svc.proptree[network/finger:default/].properties[general/restarter].datatype=fmri svc.proptree[network/finger:default/].properties[general/restarter].value=svc:/network/inetd:default svc.proptree[network/finger:default/].properties[general/restarter].valuelist=false svc.proptree[network/finger:default/].properties[inetd_disable/exec].datatype=astring svc.proptree[network/finger:default/].properties[inetd_disable/exec].value=:kill svc.proptree[network/finger:default/].properties[inetd_disable/exec].valuelist=false svc.proptree[network/finger:default/].properties[inetd_disable/timeout_seconds].datatype=count svc.proptree[network/finger:default/].properties[inetd_disable/timeout_seconds].value=0 svc.proptree[network/finger:default/].properties[inetd_disable/timeout_seconds].valuelist=false svc.proptree[network/finger:default/].properties[inetd_disable/type].datatype=astring svc.proptree[network/finger:default/].properties[inetd_disable/type].value=method svc.proptree[network/finger:default/].properties[inetd_disable/type].valuelist=false svc.proptree[network/finger:default/].properties[inetd/endpoint_type].datatype=astring svc.proptree[network/finger:default/].properties[inetd/endpoint_type].value=stream svc.proptree[network/finger:default/].properties[inetd/endpoint_type].valuelist=false svc.proptree[network/finger:default/].properties[inetd/isrpc].datatype=boolean svc.proptree[network/finger:default/].properties[inetd/isrpc].value=false svc.proptree[network/finger:default/].properties[inetd/isrpc].valuelist=false svc.proptree[network/finger:default/].properties[inetd/name].datatype=astring svc.proptree[network/finger:default/].properties[inetd/name].value=finger svc.proptree[network/finger:default/].properties[inetd/name].valuelist=false svc.proptree[network/finger:default/].properties[inetd/proto].datatype=astring svc.proptree[network/finger:default/].properties[inetd/proto].value=tcp6 svc.proptree[network/finger:default/].properties[inetd/proto].valuelist=false svc.proptree[network/finger:default/].properties[inetd/stability].datatype=astring svc.proptree[network/finger:default/].properties[inetd/stability].value=Evolving svc.proptree[network/finger:default/].properties[inetd/stability].valuelist=false svc.proptree[network/finger:default/].properties[inetd_start/exec].datatype=astring svc.proptree[network/finger:default/].properties[inetd_start/exec].value=/usr/sbin/in.fingerd svc.proptree[network/finger:default/].properties[inetd_start/exec].valuelist=false svc.proptree[network/finger:default/].properties[inetd_start/group].datatype=astring svc.proptree[network/finger:default/].properties[inetd_start/group].value=noaccess svc.proptree[network/finger:default/].properties[inetd_start/group].valuelist=false svc.proptree[network/finger:default/].properties[inetd_start/limit_privileges].datatype=astring svc.proptree[network/finger:default/].properties[inetd_start/limit_privileges].value=:default svc.proptree[network/finger:default/].properties[inetd_start/limit_privileges].valuelist=false svc.proptree[network/finger:default/].properties[inetd_start/privileges].datatype=astring svc.proptree[network/finger:default/].properties[inetd_start/privileges].value=:default svc.proptree[network/finger:default/].properties[inetd_start/privileges].valuelist=false svc.proptree[network/finger:default/].properties[inetd_start/project].datatype=astring svc.proptree[network/finger:default/].properties[inetd_start/project].value=:default svc.proptree[network/finger:default/].properties[inetd_start/project].valuelist=false svc.proptree[network/finger:default/].properties[inetd_start/resource_pool].datatype=astring svc.proptree[network/finger:default/].properties[inetd_start/resource_pool].value=:default svc.proptree[network/finger:default/].properties[inetd_start/resource_pool].valuelist=false svc.proptree[network/finger:default/].properties[inetd_start/supp_groups].datatype=astring svc.proptree[network/finger:default/].properties[inetd_start/supp_groups].value=:default svc.proptree[network/finger:default/].properties[inetd_start/supp_groups].valuelist=false svc.proptree[network/finger:default/].properties[inetd_start/timeout_seconds].datatype=count svc.proptree[network/finger:default/].properties[inetd_start/timeout_seconds].value=0 svc.proptree[network/finger:default/].properties[inetd_start/timeout_seconds].valuelist=false svc.proptree[network/finger:default/].properties[inetd_start/type].datatype=astring svc.proptree[network/finger:default/].properties[inetd_start/type].value=method svc.proptree[network/finger:default/].properties[inetd_start/type].valuelist=false svc.proptree[network/finger:default/].properties[inetd_start/use_profile].datatype=boolean svc.proptree[network/finger:default/].properties[inetd_start/use_profile].value=false svc.proptree[network/finger:default/].properties[inetd_start/use_profile].valuelist=false svc.proptree[network/finger:default/].properties[inetd_start/user].datatype=astring svc.proptree[network/finger:default/].properties[inetd_start/user].value=noaccess svc.proptree[network/finger:default/].properties[inetd_start/user].valuelist=false svc.proptree[network/finger:default/].properties[inetd_start/working_directory].datatype=astring svc.proptree[network/finger:default/].properties[inetd_start/working_directory].value=:default svc.proptree[network/finger:default/].properties[inetd_start/working_directory].valuelist=false svc.proptree[network/finger:default/].properties[inetd_state/cur_state].datatype=integer svc.proptree[network/finger:default/].properties[inetd_state/cur_state].value=1 svc.proptree[network/finger:default/].properties[inetd_state/cur_state].valuelist=false svc.proptree[network/finger:default/].properties[inetd_state/next_state].datatype=integer svc.proptree[network/finger:default/].properties[inetd_state/next_state].value=13 svc.proptree[network/finger:default/].properties[inetd_state/next_state].valuelist=false svc.proptree[network/finger:default/].properties[inetd/wait].datatype=boolean svc.proptree[network/finger:default/].properties[inetd/wait].value=false svc.proptree[network/finger:default/].properties[inetd/wait].valuelist=false svc.proptree[network/finger:default/].properties[restarter/auxiliary_state].datatype=astring svc.proptree[network/finger:default/].properties[restarter/auxiliary_state].value=none svc.proptree[network/finger:default/].properties[restarter/auxiliary_state].valuelist=false svc.proptree[network/finger:default/].properties[restarter/next_state].datatype=astring svc.proptree[network/finger:default/].properties[restarter/next_state].value=none svc.proptree[network/finger:default/].properties[restarter/next_state].valuelist=false svc.proptree[network/finger:default/].properties[restarter/state].datatype=astring svc.proptree[network/finger:default/].properties[restarter/state_timestamp].datatype=time svc.proptree[network/finger:default/].properties[restarter/state_timestamp].value=1211525081.044669000 svc.proptree[network/finger:default/].properties[restarter/state_timestamp].valuelist=false svc.proptree[network/finger:default/].properties[restarter/state].value=online svc.proptree[network/finger:default/].properties[restarter/state].valuelist=false svc.proptree[network/finger:default/].properties[tm_common_name/C].datatype=ustring svc.proptree[network/finger:default/].properties[tm_common_name/C].value=finger svc.proptree[network/finger:default/].properties[tm_common_name/C].valuelist=false svc.proptree[network/finger:default/].properties[tm_description/C].datatype=ustring svc.proptree[network/finger:default/].properties[tm_description/C].value='in.fingerd is the remote user information service which implementsserver side of the Name/Finger protocol. This protocol provides aremote interface to programs which display information on systemstatus and individual users.' svc.proptree[network/finger:default/].properties[tm_description/C].valuelist=false svc.proptree[network/finger:default/].properties[tm_man_fingerd/manpath].datatype=astring svc.proptree[network/finger:default/].properties[tm_man_fingerd/manpath].value=/usr/share/man svc.proptree[network/finger:default/].properties[tm_man_fingerd/manpath].valuelist=false svc.proptree[network/finger:default/].properties[tm_man_fingerd/section].datatype=astring svc.proptree[network/finger:default/].properties[tm_man_fingerd/section].value=1M svc.proptree[network/finger:default/].properties[tm_man_fingerd/section].valuelist=false svc.proptree[network/finger:default/].properties[tm_man_fingerd/title].datatype=astring svc.proptree[network/finger:default/].properties[tm_man_fingerd/title].value=fingerd svc.proptree[network/finger:default/].properties[tm_man_fingerd/title].valuelist=false svc.proptree[network/finger:default/].properties[tm_man_in_fingerd/manpath].datatype=astring svc.proptree[network/finger:default/].properties[tm_man_in_fingerd/manpath].value=/usr/share/man svc.proptree[network/finger:default/].properties[tm_man_in_fingerd/manpath].valuelist=false svc.proptree[network/finger:default/].properties[tm_man_in_fingerd/section].datatype=astring svc.proptree[network/finger:default/].properties[tm_man_in_fingerd/section].value=1M svc.proptree[network/finger:default/].properties[tm_man_in_fingerd/section].valuelist=false svc.proptree[network/finger:default/].properties[tm_man_in_fingerd/title].datatype=astring svc.proptree[network/finger:default/].properties[tm_man_in_fingerd/title].value=in.fingerd svc.proptree[network/finger:default/].properties[tm_man_in_fingerd/title].valuelist=false -------------- next part -------------- ( typeset -A proptree=( [network/finger:default/]=( typeset -A properties=( [general/enabled]=( datatype=boolean value=true valuelist=false ) [general/entity_stability]=( datatype=astring value=Unstable valuelist=false ) [general/restarter]=( datatype=fmri value=svc:/network/inetd:default valuelist=false ) [inetd/endpoint_type]=( datatype=astring value=stream valuelist=false ) [inetd/isrpc]=( datatype=boolean value=false valuelist=false ) [inetd/name]=( datatype=astring value=finger valuelist=false ) [inetd/proto]=( datatype=astring value=tcp6 valuelist=false ) [inetd/stability]=( datatype=astring value=Evolving valuelist=false ) [inetd/wait]=( datatype=boolean value=false valuelist=false ) [inetd_disable/exec]=( datatype=astring value=:kill valuelist=false ) [inetd_disable/timeout_seconds]=( datatype=count value=0 valuelist=false ) [inetd_disable/type]=( datatype=astring value=method valuelist=false ) [inetd_start/exec]=( datatype=astring value=/usr/sbin/in.fingerd valuelist=false ) [inetd_start/group]=( datatype=astring value=noaccess valuelist=false ) [inetd_start/limit_privileges]=( datatype=astring value=:default valuelist=false ) [inetd_start/privileges]=( datatype=astring value=:default valuelist=false ) [inetd_start/project]=( datatype=astring value=:default valuelist=false ) [inetd_start/resource_pool]=( datatype=astring value=:default valuelist=false ) [inetd_start/supp_groups]=( datatype=astring value=:default valuelist=false ) [inetd_start/timeout_seconds]=( datatype=count value=0 valuelist=false ) [inetd_start/type]=( datatype=astring value=method valuelist=false ) [inetd_start/use_profile]=( datatype=boolean value=false valuelist=false ) [inetd_start/user]=( datatype=astring value=noaccess valuelist=false ) [inetd_start/working_directory]=( datatype=astring value=:default valuelist=false ) [inetd_state/cur_state]=( datatype=integer value=1 valuelist=false ) [inetd_state/next_state]=( datatype=integer value=13 valuelist=false ) [restarter/auxiliary_state]=( datatype=astring value=none valuelist=false ) [restarter/next_state]=( datatype=astring value=none valuelist=false ) [restarter/state]=( datatype=astring value=online valuelist=false ) [restarter/state_timestamp]=( datatype=time value=1211525081.044669000 valuelist=false ) [tm_common_name/C]=( datatype=ustring value=finger valuelist=false ) [tm_description/C]=( datatype=ustring value='in.fingerd is the remote user information service which implementsserver side of the Name/Finger protocol. This protocol provides aremote interface to programs which display information on systemstatus and individual users.' valuelist=false ) [tm_man_fingerd/manpath]=( datatype=astring value=/usr/share/man valuelist=false ) [tm_man_fingerd/section]=( datatype=astring value=1M valuelist=false ) [tm_man_fingerd/title]=( datatype=astring value=fingerd valuelist=false ) [tm_man_in_fingerd/manpath]=( datatype=astring value=/usr/share/man valuelist=false ) [tm_man_in_fingerd/section]=( datatype=astring value=1M valuelist=false ) [tm_man_in_fingerd/title]=( datatype=astring value=in.fingerd valuelist=false ) ) ) ) )