commit 7ef0141356454503ab81460290b5dffa32c1f441
Author: David Ward <david.ward@ll.mit.edu>
Date:   Fri May 4 00:50:15 2012 +0200

    refresh lxc-ls
    
    Add an '--active' option that lists active containers by searching
    cgroups. (Otherwise, the directories in /var/lib/lxc are listed.)
    Modify the cgroup search to only use hierarchies that contain one
    or more subsystems. When searching, if a hierarchy contains the
    'ns' subsystem, do not append '/lxc' to the parent cgroup.
    
    Add a '--help' option that prints the command syntax.
    
    Print error messages and help information to stderr.
    
    Update the documentation.
    
    Signed-off-by: David Ward <david.ward@ll.mit.edu>
    Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>

diff --git a/doc/lxc-ls.sgml.in b/doc/lxc-ls.sgml.in
index 3ffd4f8..d33e9b3 100644
--- a/doc/lxc-ls.sgml.in
+++ b/doc/lxc-ls.sgml.in
@@ -48,7 +48,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
   <refsynopsisdiv>
     <cmdsynopsis>
-      <command>lxc-ls <optional>ls option</optional>
+      <command>lxc-ls <optional>--active</optional> <optional>ls option</optional>
       </command>
     </cmdsynopsis>
   </refsynopsisdiv>
@@ -67,6 +67,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
       <varlistentry>
 	<term>
+	  <option><optional>--active</optional></option>
+	</term>
+	<listitem>
+	  <para>
+	    List active containers.
+	  </para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>
 	  <option><optional>ls options</optional></option>
 	</term>
 	<listitem>
@@ -94,10 +105,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
       </varlistentry>
 
       <varlistentry>
-	<term>lxc-ls -1</term>
+	<term>lxc-ls --active -1</term>
 	<listitem>
 	<para>
-	  list all the containers and display the list in one column.
+	  list active containers and display the list in one column.
 	</para>
 	</listitem>
       </varlistentry>
diff --git a/src/lxc/lxc-ls.in b/src/lxc/lxc-ls.in
index a1ad642..11a3b45 100644
--- a/src/lxc/lxc-ls.in
+++ b/src/lxc/lxc-ls.in
@@ -1,43 +1,100 @@
 #!/bin/bash
 
-localstatedir=@LOCALSTATEDIR@
-lxcpath=@LXCPATH@
+#
+# lxc: linux Container library
 
-if [ ! -r $lxcpath ]; then
-    exit 0
-fi
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+localstatedir=@LOCALSTATEDIR@
+lxc_path=@LXCPATH@
 
-function get_cgroup()
+usage()
 {
-	local mount_string
-	mount_string=$(mount -t cgroup |grep -E -e '^lxc ')
-	if test -n "$mount_string"; then
-		mount_point=$(echo $mount_string |cut -d' ' -f3)
-		return
-	fi
-	mount_string=`grep -m1 -E '^[^ \t]+[ \t]+[^ \t]+[ \t]+cgroup' /proc/self/mounts`;
-	if test -z "$mount_string"; then
-		echo "failed to find mounted cgroup"
-		exit 1
-	fi
-	mount_point=`echo "$mount_string" |cut -d' ' -f2`;
+	echo "usage: $(basename $0) [--active] [--] [LS_OPTIONS...]" >&2
 }
 
-ls "$@" $lxcpath
+help() {
+	usage
+	echo >&2
+	echo "List containers existing on the system." >&2
+	echo >&2
+	echo "  --active     list active containers" >&2
+	echo "  LS_OPTIONS   ls command options (see \`ls --help')" >&2
+}
+
+get_parent_cgroup()
+{
+	local hierarchies hierarchy fields subsystems init_cgroup mountpoint
+
+	parent_cgroup=""
+
+	# Obtain a list of hierarchies that contain one or more subsystems
+	hierarchies=$(tail -n +2 /proc/cgroups | cut -f 2)
 
-active=$(netstat -xl 2>/dev/null | grep $lxcpath | \
-	sed -e 's#.*'"$lxcpath/"'\(.*\)/command#\1#');
+	# Iterate through the list until a suitable hierarchy is found
+	for hierarchy in $hierarchies; do
+		# Obtain information about the init process in the hierarchy
+		fields=$(grep -E "^$hierarchy:" /proc/1/cgroup | head -n 1)
+		if [ -z "$fields" ]; then continue; fi
+		fields=${fields#*:}
 
-if test -n "$active"; then
-	get_cgroup
-	if test -n "$mount_point"; then
-		# get cgroup for init
-		init_cgroup=`cat /proc/1/cgroup | awk -F: '{ print $3 }' | head -1`
-		if [ ! -d $mount_point/$init_cgroup/lxc  ]; then
-			cd $mount_point/$init_cgroup
+		# Get a comma-separated list of the hierarchy's subsystems
+		subsystems=${fields%:*}
+
+		# Get the cgroup of the init process in the hierarchy
+		init_cgroup=${fields#*:}
+
+		# Get the filesystem mountpoint of the hierarchy
+		mountpoint=$(grep -E "^cgroup [^ ]+ [^ ]+ ([^ ]+,)?$subsystems(,[^ ]+)? " /proc/self/mounts | cut -d ' ' -f 2)
+		if [ -z "$mountpoint" ]; then continue; fi
+
+		# Return the absolute path to the containers' parent cgroup
+		# (do not append '/lxc' if the hierarchy contains the 'ns' subsystem)
+		if [[ ",$subsystems," == *,ns,* ]]; then
+			parent_cgroup="${mountpoint}${init_cgroup%/}"
 		else
-			cd $mount_point/$init_cgroup/lxc
+			parent_cgroup="${mountpoint}${init_cgroup%/}/lxc"
 		fi
-		ls "$@" -d $active
-	fi
+		break
+	done
+}
+
+directory="$lxc_path"
+
+for i in "$@"; do
+	case $i in
+		--help)
+			help; exit 1;;
+		--active)
+			get_parent_cgroup; directory="$parent_cgroup"; shift;;
+		--)
+			shift; break;;
+		*)
+			break;;
+        esac
+done
+
+containers=""
+if [ ! -z "$directory" ]; then
+	containers=$(find $directory -mindepth 1 -maxdepth 1 -type d -printf "%f\n" 2>/dev/null)
 fi
+
+if [ -z "$containers" ]; then
+	echo "$(basename $0): no containers found" >&2
+	exit 1
+fi
+
+cd "$directory"
+ls -d $@ $containers
