This is the first import of the lttng-tools tree.
Signed-off-by: David Goulet <david.goulet@polymtl.ca>
--- /dev/null
+*.o
+*.so
+*.swp
+*.o
+*.swo
+Makefile
+.libs/
+.deps/
+*~
+*.la
+*.lo
+Makefile.in
+*.loT
+*.info
+configure
+aclocal.m4
+autom4te.cache/
+config.h
+config.h.in
+config/
+config.log
+config.status
+stamp-h1
+libtool
+
+ltt-sessiond/ltt-sessiond
+lttng/lttng
--- /dev/null
+David Goulet <david.goulet@polymtl.ca>
--- /dev/null
+LTTng Tracing Tools
+
+Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+
+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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
--- /dev/null
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved. This file is offered as-is,
+without warranty of any kind.
+
+Basic Installation
+==================
+
+ Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package. The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package. Some packages provide this
+`INSTALL' file but do not implement all of the features documented
+below. The lack of an optional feature in a given package is not
+necessarily a bug. More recommendations for GNU packages can be found
+in *note Makefile Conventions: (standards)Makefile Conventions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+ The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system.
+
+ Running `configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package, generally using the just-built uninstalled binaries.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation. When installing into a prefix owned by root, it is
+ recommended that the package be configured and built as a regular
+ user, and only the `make install' phase executed with root
+ privileges.
+
+ 5. Optionally, type `make installcheck' to repeat any self-tests, but
+ this time using the binaries in their final installed location.
+ This target does not install anything. Running this target as a
+ regular user, particularly if the prior `make install' required
+ root privileges, verifies that the installation completed
+ correctly.
+
+ 6. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+ 7. Often, you can also type `make uninstall' to remove the installed
+ files again. In practice, not all packages have tested that
+ uninstallation works correctly, even though it is required by the
+ GNU Coding Standards.
+
+ 8. Some packages, particularly those that use Automake, provide `make
+ distcheck', which can by used by developers to test that all other
+ targets like `make install' and `make uninstall' work correctly.
+ This target is generally not run by end users.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you can use GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'. This
+is known as a "VPATH" build.
+
+ With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+ On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple `-arch' options to the
+compiler but only a single `-arch' option to the preprocessor. Like
+this:
+
+ ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CPP="gcc -E" CXXCPP="g++ -E"
+
+ This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the `lipo' tool if you have problems.
+
+Installation Names
+==================
+
+ By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX', where PREFIX must be an
+absolute file name.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them. In general, the
+default for these options is expressed in terms of `${prefix}', so that
+specifying just `--prefix' will affect all of the other directory
+specifications that were not explicitly provided.
+
+ The most portable way to affect installation locations is to pass the
+correct locations to `configure'; however, many packages provide one or
+both of the following shortcuts of passing variable assignments to the
+`make install' command line to change installation locations without
+having to reconfigure or recompile.
+
+ The first method involves providing an override variable for each
+affected directory. For example, `make install
+prefix=/alternate/directory' will choose an alternate location for all
+directory configuration variables that were expressed in terms of
+`${prefix}'. Any directories that were specified during `configure',
+but not in terms of `${prefix}', must each be overridden at install
+time for the entire installation to be relocated. The approach of
+makefile variable overrides for each directory variable is required by
+the GNU Coding Standards, and ideally causes no recompilation.
+However, some platforms have known limitations with the semantics of
+shared libraries that end up requiring recompilation when using this
+method, particularly noticeable in packages that use GNU Libtool.
+
+ The second method involves providing the `DESTDIR' variable. For
+example, `make install DESTDIR=/alternate/directory' will prepend
+`/alternate/directory' before all installation names. The approach of
+`DESTDIR' overrides is not required by the GNU Coding Standards, and
+does not work on platforms that have drive letters. On the other hand,
+it does better at avoiding recompilation issues, and works well even
+when some directory options were not specified in terms of `${prefix}'
+at `configure' time.
+
+Optional Features
+=================
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+ Some packages offer the ability to configure how verbose the
+execution of `make' will be. For these packages, running `./configure
+--enable-silent-rules' sets the default to minimal output, which can be
+overridden with `make V=1'; while running `./configure
+--disable-silent-rules' sets the default to verbose, which can be
+overridden with `make V=0'.
+
+Particular systems
+==================
+
+ On HP-UX, the default C compiler is not ANSI C compatible. If GNU
+CC is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+ ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+ On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its `<wchar.h>' header file. The option `-nodtk' can be used as
+a workaround. If GNU CC is not installed, it is therefore recommended
+to try
+
+ ./configure CC="cc"
+
+and if that doesn't work, try
+
+ ./configure CC="cc -nodtk"
+
+ On Solaris, don't put `/usr/ucb' early in your `PATH'. This
+directory contains several dysfunctional programs; working variants of
+these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
+in your `PATH', put it _after_ `/usr/bin'.
+
+ On Haiku, software installed for all users goes in `/boot/common',
+not `/usr/local'. It is recommended to use the following options:
+
+ ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS
+ KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug. Until the bug is fixed you can use this workaround:
+
+ CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+ Print a summary of all of the options to `configure', and exit.
+
+`--help=short'
+`--help=recursive'
+ Print a summary of the options unique to this package's
+ `configure', and exit. The `short' variant lists options used
+ only in the top level, while the `recursive' variant lists options
+ also present in any nested packages.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--prefix=DIR'
+ Use DIR as the installation prefix. *note Installation Names::
+ for more details, including other options available for fine-tuning
+ the installation locations.
+
+`--no-create'
+`-n'
+ Run the configure checks, but stop before creating any output
+ files.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
--- /dev/null
+ACLOCAL_AMFLAGS = -I config
+
+SUBDIRS = liblttsessiondcomm liblttngctl lttng ltt-sessiond tests
--- /dev/null
+LTTng Trace Control
+----------------
+
+Please visit http://lttng.org for more information.
+
+Latest development can be found at:
+
+ * Gitweb : http://git.lttng.org/lttng-tools.git/
+ * Git : git://git.lttng.org/lttng-tools.git
+
+PREREQUISITES:
+
+ - libuuid
+ Universally unique id library - headers and static libraries libuuid
+ generates and parses 128-bit universally unique ids (UUIDs). See RFC
+ 4122 for more information.
+
+ * Debian/Ubuntu package: uuid-dev
+
+ - liburcu
+ Userspace RCU library, by Mathieu Desnoyers and Paul E. McKenney
+
+ -> Tested with liburcu >= v0.5.4
+
+ * Debian/Ubuntu package: liburcu-dev
+ * Git : git://lttng.org/userspace-rcu.git
+ * Website: http://lttng.org/urcu
+
+ - libustctl
+ LTTng user-space tracer control library
+
+ Needed for interaction with that tracer.
+
+ - liblttctl
+ LTTng kernel tracer control library
+
+ Needed for interaction with that tracer.
+
+INSTALLATION INSTRUCTIONS:
+
+ - Download, compile and install liburcu, libuuid, libustctl and liblttctl
+ - In this package's tree, run ./configure.
+ - Run make.
+ - Run make install.
+ - Run ldconfig.
+
+ If compiling from the git repository, run ./bootstrap before running
+ the configure script, to generate it.
+
+PACKAGE CONTENTS:
+
+ This package contains the following elements:
+
+ - liblttngctl
+ The LTTng trace control library.
+
+ - liblttsessiondcomm
+ The ltt-sessiond communication library. In order to talk with ltt-sessiond,
+ thi library must be used.
+
+ - ltt-sessiond
+ The LTTng session daemon binary.
+
+ - lttng
+ The LTTng tracer command line control tool.
+
+ - include
+ The liblttngctl API header file.
+
+ - tests
+ Various test programs.
--- /dev/null
+#! /bin/sh
+
+set -x
+if [ ! -e config ]; then
+ mkdir config
+fi
+
+autoreconf -i
--- /dev/null
+AC_INIT([lttng-tools], [0.0.1], [david.goulet@polymtl.ca], [http://lttng.org])
+AC_CONFIG_AUX_DIR([config])
+AC_CONFIG_MACRO_DIR([config])
+AM_INIT_AUTOMAKE
+AM_SILENT_RULES([yes])
+
+AC_CHECK_HEADERS([ \
+ sys/types.h unistd.h fcntl.h string.h pthread.h limits.h \
+ signal.h stdlib.h sys/un.h sys/socket.h stdlib.h stdio.h \
+ getopt.h sys/ipc.h sys/shm.h popt.h grp.h \
+])
+
+# Check for pthread
+AC_CHECK_LIB([pthread], [pthread_create], [],
+ [AC_MSG_ERROR([Cannot find libpthread. Use [LDFLAGS]=-Ldir to specify its location.])]
+)
+
+# Check libpopt
+AC_CHECK_LIB([popt], [poptGetContext], [],
+ [AC_MSG_ERROR([Cannot find libpopt. Use [LDFLAGS]=-Ldir to specify its location.])]
+)
+
+# Check libuuid
+AC_CHECK_LIB([uuid], [uuid_generate], [],
+ [AC_MSG_ERROR([Cannot find libuuid. Use [LDFLAGS]=-Ldir to specify its location.])]
+)
+
+# Check libustctl
+AC_CHECK_LIB([ustctl], [ustctl_connect_pid], [],
+ [AC_MSG_ERROR([Cannot find libustctl. Use [LDFLAGS]=-Ldir to specify its location.])]
+)
+
+# Check liburcu
+AC_CHECK_LIB([urcu], [synchronize_rcu], [],
+ [AC_MSG_ERROR([Cannot find liburcu. Use [LDFLAGS]=-Ldir to specify its location.])]
+)
+AC_CHECK_DECL([cds_list_add], [],
+ [AC_MSG_ERROR([liburcu 0.5.4 or newer is needed])], [[#include <urcu/list.h>]]
+)
+
+CFLAGS="-Wall $CFLAGS -g"
+
+AC_PROG_CC
+AC_PROG_LIBTOOL
+
+AC_CONFIG_FILES([
+ Makefile
+ include/Makefile
+ liblttngctl/Makefile
+ liblttsessiondcomm/Makefile
+ lttng/Makefile
+ tests/Makefile
+ ltt-sessiond/Makefile
+])
+
+AC_OUTPUT
--- /dev/null
+nobase_include_HEADERS = \
+ lttng/liblttngctl.h
+
+noinst_HEADERS = lttngerr.h
--- /dev/null
+/* Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _LIBLTTNGCTL_H
+#define _LIBLTTNGCTL_H
+
+#define DEFAULT_TRACING_GROUP "tracing"
+
+/*
+ * From libuuid
+ */
+#define UUID_STR_LEN 37
+
+extern int lttng_create_session(const char *name, char *session_id);
+extern int lttng_connect_sessiond(void);
+extern int lttng_set_tracing_group(const char *name);
+extern int lttng_check_session_daemon(void);
+extern const char *lttng_get_readable_code(int code);
+extern size_t lttng_ust_list_apps(pid_t **pids);
+
+#endif /* _LIBLTTNGCTL_H */
--- /dev/null
+/* Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _LTTNGERR_H
+#define _LTTNGERR_H
+
+#include <errno.h>
+#include <stdarg.h>
+
+extern int opt_quiet;
+extern int opt_verbose;
+
+enum __lttng_print_type {
+ PRINT_ERR,
+ PRINT_WARN,
+ PRINT_BUG,
+ PRINT_DBG,
+ PRINT_MSG,
+};
+
+/*
+ * __lttng_print
+ *
+ * Internal function for printing message
+ * depending on command line option and verbosity.
+ */
+void __lttng_print(enum __lttng_print_type type, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+
+ if (opt_quiet == 0) {
+ if (type == PRINT_MSG || (opt_verbose && type == PRINT_DBG)) {
+ vfprintf(stdout, fmt, ap);
+ } else if (type != PRINT_MSG && type != PRINT_DBG) {
+ vfprintf(stderr, fmt, ap);
+ }
+ }
+
+ va_end(ap);
+}
+
+#define MSG(fmt, args...) __lttng_print(PRINT_MSG, fmt "\n", ## args)
+#define ERR(fmt, args...) __lttng_print(PRINT_ERR, "Error: " fmt "\n", ## args)
+#define WARN(fmt, args...) __lttng_print(PRINT_WARN, "Warning: " fmt "\n", ## args)
+#define BUG(fmt, args...) __lttng_print(PRINT_BUG, "BUG: " fmt "\n", ## args)
+#define DBG(fmt, args...) __lttng_print(PRINT_DBG, "DEBUG: " fmt "\n", ## args)
+
+#endif /* _LTTNGERR_H */
--- /dev/null
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/liblttsessiondcomm
+
+lib_LTLIBRARIES = liblttngctl.la
+
+liblttngctl_la_SOURCES = liblttngctl.c
+
+liblttngctl_la_LIBADD = \
+ $(top_builddir)/liblttsessiondcomm/liblttsessiondcomm.la
--- /dev/null
+/* Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <lttng/liblttngctl.h>
+
+#include "liblttsessiondcomm.h"
+#include "lttngerr.h"
+
+/* Socket to session daemon for communication */
+static int sessiond_socket;
+static char sessiond_sock_path[PATH_MAX];
+
+/* Communication structure to ltt-sessiond */
+static struct lttcomm_lttng_msg llm;
+static struct lttcomm_session_msg lsm;
+
+/* Prototypes */
+static int check_tracing_group(const char *grp_name);
+static int ask_sessiond(void);
+static int set_session_daemon_path(void);
+static void reset_data_struct(void);
+
+int lttng_connect_sessiond(void);
+int lttng_create_session(const char *name, char *session_id);
+int lttng_check_session_daemon(void);
+
+/* Variables */
+static char *tracing_group;
+static int connected;
+
+/*
+ * ask_sessiond
+ *
+ * Send lttcomm_session_msg to the daemon and wait
+ * for the reply. Data replied will be put in llm
+ *
+ * On success, return 0
+ * On error, return error code
+ */
+static int ask_sessiond(void)
+{
+ int ret;
+
+ if (!connected) {
+ ret = -ECONNREFUSED;
+ goto error;
+ }
+
+ ret = lttcomm_send_unix_sock(sessiond_socket, &lsm, sizeof(lsm));
+ if (ret < 0) {
+ goto error;
+ }
+
+ ret = lttcomm_recv_unix_sock(sessiond_socket, &llm, sizeof(llm));
+ if (ret < 0) {
+ goto error;
+ }
+
+ /* Check return code */
+ if (llm.ret_code != LTTCOMM_OK) {
+ ret = -llm.ret_code;
+ goto error;
+ }
+
+ return 0;
+
+error:
+ return ret;
+}
+
+/*
+ * lttng_get_readable_code
+ *
+ * Return a human readable string of code
+ */
+const char *lttng_get_readable_code(int code)
+{
+ if (code > -LTTCOMM_OK) {
+ return "Ended with errors";
+ }
+
+ return lttcomm_get_readable_code(code);
+}
+
+/*
+ * lttng_create_session
+ *
+ * Create a tracing session using "name" to the session daemon.
+ * If no name is given, the auto session creation is set and
+ * the daemon will take care of finding a name.
+ *
+ * On success, return 0 and session_id point to the uuid str.
+ * On error, negative value is returned.
+ */
+int lttng_create_session(const char *name, char *session_id)
+{
+ int ret;
+
+ lsm.cmd_type = LTTNG_CREATE_SESSION;
+ if (name == NULL) {
+ lsm.u.create_session.auto_session = 1;
+ } else {
+ strncpy(lsm.session_name, name, strlen(name));
+ lsm.u.create_session.auto_session = 0;
+ }
+
+ /* Ask the session daemon */
+ ret = ask_sessiond();
+ if (ret < 0) {
+ goto end;
+ }
+
+ /* Unparse session ID */
+ uuid_unparse(llm.session_id, session_id);
+
+end:
+ reset_data_struct();
+
+ return ret;
+}
+
+/*
+ * lttng_ust_list_apps
+ *
+ * Ask the session daemon for all UST traceable
+ * applications.
+ *
+ * Return the size of pids.
+ */
+size_t lttng_ust_list_apps(pid_t **pids)
+{
+ int ret;
+
+ lsm.cmd_type = UST_LIST_APPS;
+
+ ret = ask_sessiond();
+ if (ret < 0) {
+ goto error;
+ }
+
+ *pids = llm.u.list_apps.pids;
+
+ return llm.u.list_apps.size;
+
+error:
+ return ret;
+}
+
+/*
+ * lttng_connect_sessiond
+ *
+ * Connect to the LTTng session daemon.
+ * On success, return 0
+ * On error, return a negative value
+ */
+int lttng_connect_sessiond(void)
+{
+ int ret;
+
+ ret = set_session_daemon_path();
+ if (ret < 0) {
+ return ret;
+ }
+
+ /* Connect to the sesssion daemon */
+ ret = lttcomm_connect_unix_sock(sessiond_sock_path);
+ if (ret < 0) {
+ return ret;
+ }
+
+ sessiond_socket = ret;
+ connected = 1;
+
+ return 0;
+}
+
+/*
+ * lttng_set_tracing_group
+ *
+ * Set tracing group variable with name. This function
+ * allocate memory pointed by tracing_group.
+ */
+int lttng_set_tracing_group(const char *name)
+{
+ if (asprintf(&tracing_group, "%s", name) < 0) {
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+/*
+ * lttng_check_session_daemon
+ *
+ * Return 0 if a sesssion daemon is available
+ * else return -1
+ */
+int lttng_check_session_daemon(void)
+{
+ int ret;
+
+ ret = set_session_daemon_path();
+ if (ret < 0) {
+ return ret;
+ }
+
+ /* If socket exist, we consider the daemon started */
+ ret = access(sessiond_sock_path, F_OK);
+ if (ret < 0) {
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ * reset_data_struct
+ *
+ * Reset session daemon structures.
+ */
+static void reset_data_struct(void)
+{
+ memset(&lsm, 0, sizeof(lsm));
+ memset(&llm, 0, sizeof(llm));
+}
+
+/*
+ * set_session_daemon_path
+ *
+ * Set sessiond socket path by putting it in
+ * the global sessiond_sock_path variable.
+ */
+static int set_session_daemon_path(void)
+{
+ int ret;
+
+ /* Are we in the tracing group ? */
+ ret = check_tracing_group(tracing_group);
+ if (ret < 0) {
+ if (sprintf(sessiond_sock_path, DEFAULT_HOME_CLIENT_UNIX_SOCK,
+ getenv("HOME")) < 0) {
+ return -ENOMEM;
+ }
+ } else {
+ strncpy(sessiond_sock_path, DEFAULT_GLOBAL_CLIENT_UNIX_SOCK,
+ sizeof(DEFAULT_GLOBAL_CLIENT_UNIX_SOCK));
+ }
+
+ return 0;
+}
+
+/*
+ * check_tracing_group
+ *
+ * Check if the specified group name exist.
+ * If yes, 0, else -1
+ */
+static int check_tracing_group(const char *grp_name)
+{
+ struct group *grp_tracing; /* no free(). See getgrnam(3) */
+ gid_t *grp_list;
+ int grp_list_size, grp_id, i;
+ int ret = -1;
+
+ /* Get GID of group 'tracing' */
+ grp_tracing = getgrnam(grp_name);
+ if (grp_tracing == NULL) {
+ /* NULL means not found also. getgrnam(3) */
+ if (errno != 0) {
+ perror("getgrnam");
+ }
+ goto end;
+ }
+
+ /* Get number of supplementary group IDs */
+ grp_list_size = getgroups(0, NULL);
+ if (grp_list_size < 0) {
+ perror("getgroups");
+ goto end;
+ }
+
+ /* Alloc group list of the right size */
+ grp_list = malloc(grp_list_size * sizeof(gid_t));
+ grp_id = getgroups(grp_list_size, grp_list);
+ if (grp_id < -1) {
+ perror("getgroups");
+ goto free_list;
+ }
+
+ for (i = 0; i < grp_list_size; i++) {
+ if (grp_list[i] == grp_tracing->gr_gid) {
+ ret = 0;
+ break;
+ }
+ }
+
+free_list:
+ free(grp_list);
+
+end:
+ return ret;
+}
+
+/*
+ * lib constructor
+ */
+static void __attribute__((constructor)) init()
+{
+ /* Set default session group */
+ lttng_set_tracing_group(DEFAULT_TRACING_GROUP);
+}
--- /dev/null
+AM_CPPFLAGS = -I$(top_srcdir)/include
+
+lib_LTLIBRARIES = liblttsessiondcomm.la
+
+liblttsessiondcomm_la_SOURCES = \
+ liblttsessiondcomm.c
--- /dev/null
+/* Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "liblttsessiondcomm.h"
+
+/*
+ * Human readable error message.
+ */
+static const char *lttcomm_readable_code[] = {
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_OK) ] = "Success",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_ERR) ] = "Unknown error",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_UND) ] = "Undefined command",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_NO_SESSION) ] = "No session found",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_LIST_FAIL) ] = "Unable to list traceable apps",
+};
+
+/*
+ * lttcom_get_readable_code
+ *
+ * Return ptr to string representing a human readable
+ * error code from the lttcomm_return_code enum.
+ *
+ * These code MUST be negative in other to treat that
+ * as an error value.
+ */
+const char *lttcomm_get_readable_code(enum lttcomm_return_code code)
+{
+ int tmp_code = -code;
+
+ if (tmp_code >= LTTCOMM_OK && tmp_code < LTTCOMM_NR) {
+ return lttcomm_readable_code[LTTCOMM_ERR_INDEX(tmp_code)];
+ }
+
+ return "Unknown error code";
+}
+
+/*
+ * lttcomm_connect_unix_sock
+ *
+ * Connect to unix socket using the path name.
+ */
+int lttcomm_connect_unix_sock(const char *pathname)
+{
+ struct sockaddr_un sun;
+ int fd;
+ int ret = 1;
+
+ fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ perror("socket");
+ goto error;
+ }
+
+ memset(&sun, 0, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+ strncpy(sun.sun_path, pathname, sizeof(sun.sun_path));
+
+ ret = connect(fd, (struct sockaddr *) &sun, sizeof(sun));
+ if (ret < 0) {
+ perror("connect");
+ goto error;
+ }
+
+ return fd;
+
+error:
+ return -1;
+}
+
+/*
+ * lttcomm_accept_unix_sock
+ *
+ * Do an accept(2) on the sock and return the
+ * new file descriptor. The socket MUST be bind(2) before.
+ */
+int lttcomm_accept_unix_sock(int sock)
+{
+ int new_fd;
+ struct sockaddr_un sun;
+ socklen_t len = 0;
+
+ /* Blocking call */
+ new_fd = accept(sock, (struct sockaddr *) &sun, &len);
+ if (new_fd < 0) {
+ perror("accept");
+ goto error;
+ }
+
+ return new_fd;
+
+error:
+ return -1;
+}
+
+/*
+ * lttcomm_create_unix_sock
+ *
+ * Creates a AF_UNIX local socket using pathname
+ * bind the socket upon creation and return the fd.
+ */
+int lttcomm_create_unix_sock(const char *pathname)
+{
+ struct sockaddr_un sun;
+ int fd;
+ int ret = -1;
+
+ /* Create server socket */
+ if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
+ perror("socket");
+ goto error;
+ }
+
+ memset(&sun, 0, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+ strncpy(sun.sun_path, pathname, strlen(pathname));
+
+ ret = bind(fd, (struct sockaddr *) &sun, sizeof(sun));
+ if (ret < 0) {
+ perror("bind");
+ goto error;
+ }
+
+ return fd;
+
+error:
+ return ret;
+}
+
+/*
+ * lttcomm_listen_unix_sock
+ *
+ * Make the socket listen using MAX_LISTEN.
+ */
+int lttcomm_listen_unix_sock(int sock)
+{
+ int ret;
+
+ ret = listen(sock, MAX_LISTEN);
+ if (ret < 0) {
+ perror("listen");
+ }
+
+ return ret;
+}
+
+/*
+ * lttcomm_recv_unix_sock
+ *
+ * Receive data of size len in put that data into
+ * the buf param. Using recvmsg API.
+ * Return the size of received data.
+ */
+ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len)
+{
+ struct msghdr msg;
+ struct iovec iov[1];
+ ssize_t ret = -1;
+
+ memset(&msg, 0, sizeof(msg));
+
+ iov[0].iov_base = buf;
+ iov[0].iov_len = len;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+
+ ret = recvmsg(sock, &msg, 0);
+ if (ret < 0) {
+ perror("recvmsg");
+ }
+
+ return ret;
+}
+
+/*
+ * lttcomm_send_unix_sock
+ *
+ * Send buf data of size len. Using sendmsg API.
+ * Return the size of sent data.
+ */
+ssize_t lttcomm_send_unix_sock(int sock, void *buf, size_t len)
+{
+ struct msghdr msg;
+ struct iovec iov[1];
+ ssize_t ret = -1;
+
+ memset(&msg, 0, sizeof(msg));
+
+ iov[0].iov_base = buf;
+ iov[0].iov_len = len;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+
+ ret = sendmsg(sock, &msg, 0);
+ if (ret < 0) {
+ perror("sendmsg");
+ }
+
+ return ret;
+}
--- /dev/null
+/* Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _LIBLTTSESSIONDCOMM_H
+#define _LIBLTTSESSIONDCOMM_H
+
+#include <limits.h>
+#include <uuid/uuid.h>
+
+/* Default unix socket path */
+#define DEFAULT_GLOBAL_CLIENT_UNIX_SOCK "/tmp/client-ltt-sessiond"
+#define DEFAULT_GLOBAL_APPS_UNIX_SOCK "/tmp/apps-ltt-sessiond"
+#define DEFAULT_HOME_APPS_UNIX_SOCK "%s/.apps-ltt-sessiond"
+#define DEFAULT_HOME_CLIENT_UNIX_SOCK "%s/.client-ltt-sessiond"
+
+/* Queue size of listen(2) */
+#define MAX_LISTEN 10
+
+/* Maximum amount of PID the list_apps command
+ * can send back to the lttng client.
+ */
+#define MAX_APPS_PID 20
+
+/* Get the error code index from 0 since
+ * LTTCOMM_OK start at 1000
+ */
+#define LTTCOMM_ERR_INDEX(code) code - LTTCOMM_OK
+
+enum lttcomm_command_type {
+ LTTNG_CREATE_SESSION,
+ LTTNG_DESTROY_SESSION,
+ LTTNG_FORCE_SUBBUF_SWITCH,
+ LTTNG_GET_ALL_SESSION,
+ LTTNG_GET_SOCK_PATH,
+ LTTNG_GET_SUBBUF_NUM_SIZE,
+ LTTNG_LIST_MARKERS,
+ LTTNG_LIST_SESSIONS,
+ LTTNG_LIST_TRACE_EVENTS,
+ LTTNG_SETUP_TRACE,
+ LTTNG_SET_SOCK_PATH,
+ LTTNG_SET_SUBBUF_NUM,
+ LTTNG_SET_SUBBUF_SIZE,
+ UST_ALLOC_TRACE,
+ UST_CREATE_TRACE,
+ UST_DESTROY_TRACE,
+ UST_DISABLE_MARKER,
+ UST_ENABLE_MARKER,
+ UST_LIST_APPS,
+ UST_START_TRACE,
+ UST_STOP_TRACE,
+};
+
+/*
+ * lttcomm error code.
+ */
+enum lttcomm_return_code {
+ LTTCOMM_OK = 1000, /* Ok */
+ LTTCOMM_ERR, /* Unknown Error */
+ LTTCOMM_UND, /* Undefine command */
+ LTTCOMM_ALLOC_FAIL, /* Trace allocation fail */
+ LTTCOMM_NO_SESSION, /* No session found */
+ LTTCOMM_CREATE_FAIL, /* Create trace fail */
+ LTTCOMM_SESSION_FAIL, /* Create session fail */
+ LTTCOMM_START_FAIL, /* Start tracing fail */
+ LTTCOMM_LIST_FAIL, /* Listing apps fail */
+ LTTCOMM_NR, /* Last element */
+};
+
+/*
+ * Data structure for ltt-session received message
+ */
+struct lttcomm_session_msg {
+ /* Common data to almost all command */
+ enum lttcomm_command_type cmd_type;
+ uuid_t session_id;
+ char trace_name[NAME_MAX];
+ char session_name[NAME_MAX];
+ pid_t pid;
+ union {
+ struct {
+ int auto_session;
+ } create_session;
+ /* Marker data */
+ struct {
+ char channel[NAME_MAX];
+ char marker[NAME_MAX];
+ } marker;
+ /* SET_SOCK_PATH */
+ struct {
+ char sock_path[PATH_MAX];
+ } sock_path;
+ /* SET_SUBBUF_NUM */
+ struct {
+ unsigned int subbuf_num;
+ char channel[NAME_MAX];
+ } subbuf_num;
+ /* SET_SUBBUF_SIZE */
+ struct {
+ unsigned int subbuf_size;
+ char channel[NAME_MAX];
+ } subbuf_size;
+ } u;
+};
+
+/*
+ * Data structure for the lttng client response
+ */
+struct lttcomm_lttng_msg {
+ enum lttcomm_command_type cmd_type;
+ enum lttcomm_return_code ret_code;
+ uuid_t session_id;
+ pid_t pid;
+ char trace_name[NAME_MAX];
+ union {
+ /* UST_LIST_APPS */
+ struct {
+ size_t size;
+ pid_t pids[MAX_APPS_PID];
+ } list_apps;
+ } u;
+};
+
+extern int lttcomm_create_unix_sock(const char *pathname);
+extern int lttcomm_connect_unix_sock(const char *pathname);
+extern int lttcomm_accept_unix_sock(int sock);
+extern int lttcomm_listen_unix_sock(int sock);
+extern ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len);
+extern ssize_t lttcomm_send_unix_sock(int sock, void *buf, size_t len);
+extern const char *lttcomm_get_readable_code(enum lttcomm_return_code code);
+
+#endif /* _LIBLTTSESSIONDCOMM_H */
--- /dev/null
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/liblttsessiondcomm
+
+bin_PROGRAMS = ltt-sessiond
+
+ltt_sessiond_SOURCES = ltt-sessiond.c
+
+ltt_sessiond_LDADD = \
+ $(top_builddir)/liblttsessiondcomm/liblttsessiondcomm.la
--- /dev/null
+/* Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <getopt.h>
+#include <grp.h>
+#include <limits.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <urcu/list.h> /* URCU list library (-lurcu) */
+#include <ust/ustctl.h> /* UST control lib (-lust) */
+
+#include "liblttsessiondcomm.h"
+#include "ltt-sessiond.h"
+
+/* Static functions */
+static int set_signal_handler(void);
+static int set_socket_perms(void);
+static void sighandler(int);
+static void daemonize(void);
+static void cleanup(void);
+static int check_existing_daemon(void);
+static int notify_apps(const char*);
+static int connect_app(pid_t);
+static int init_daemon_socket(void);
+static struct lttcomm_lttng_msg *process_client_msg(struct lttcomm_session_msg*);
+
+static void *thread_manage_clients(void *);
+static void *thread_manage_apps(void *);
+
+static int create_session(const char*, uuid_t *);
+static void destroy_session(uuid_t);
+
+static struct ltt_session *find_session(uuid_t);
+
+/* Variables */
+const char *progname;
+const char *opt_tracing_group;
+static int opt_daemon;
+static int is_root; /* Set to 1 if the daemon is running as root */
+
+static char apps_unix_sock_path[PATH_MAX]; /* Global application Unix socket path */
+static char client_unix_sock_path[PATH_MAX]; /* Global client Unix socket path */
+
+static int client_socket;
+static int apps_socket;
+
+static struct ltt_session *current_session;
+static int session_count;
+
+/* Init session's list */
+static struct ltt_session_list ltt_session_list = {
+ .head = CDS_LIST_HEAD_INIT(ltt_session_list.head),
+};
+
+static struct ltt_traceable_app_list ltt_traceable_app_list = {
+ .head = CDS_LIST_HEAD_INIT(ltt_traceable_app_list.head),
+};
+
+/*
+ * thread_manage_apps
+ *
+ * This thread manage the application socket communication
+ */
+static void *thread_manage_apps(void *data)
+{
+ int sock, ret;
+ struct ltt_traceable_app *lta;
+
+ /* TODO: Something more elegant is needed but fine for now */
+ struct {
+ int reg; /* 1:register, 0:unregister */
+ pid_t pid;
+ uid_t uid;
+ } reg_msg;
+
+ /* Notify all applications to register */
+ notify_apps(default_global_apps_pipe);
+
+ ret = lttcomm_listen_unix_sock(apps_socket);
+ if (ret < 0) {
+ goto error;
+ }
+
+ while (1) {
+ /* Blocking call, waiting for transmission */
+ sock = lttcomm_accept_unix_sock(apps_socket);
+ if (sock < 0) {
+ goto error;
+ }
+
+ /* Basic recv here to handle the very simple data
+ * that the libust send to register (reg_msg).
+ */
+ ret = recv(sock, ®_msg, sizeof(reg_msg), 0);
+ if (ret < 0) {
+ perror("recv");
+ continue;
+ }
+
+ /* Add application to the global traceable list */
+ if (reg_msg.reg == 1) {
+ /* Registering */
+ lta = malloc(sizeof(struct ltt_traceable_app));
+ lta->pid = reg_msg.pid;
+ lta->uid = reg_msg.uid;
+ cds_list_add(<a->list, <t_traceable_app_list.head);
+ } else {
+ /* Unregistering */
+ lta = NULL;
+ cds_list_for_each_entry(lta, <t_traceable_app_list.head, list) {
+ if (lta->pid == reg_msg.pid && lta->uid == reg_msg.uid) {
+ cds_list_del(<a->list);
+ break;
+ }
+ }
+
+ /* If an item was found, free it from memory */
+ if (lta) {
+ free(lta);
+ }
+ }
+ }
+
+error:
+
+ return NULL;
+}
+
+/*
+ * thread_manage_clients
+ *
+ * This thread manage all clients request using the unix
+ * client socket for communication.
+ */
+static void *thread_manage_clients(void *data)
+{
+ int sock, ret;
+ struct lttcomm_session_msg lsm;
+ struct lttcomm_lttng_msg *llm;
+
+ ret = lttcomm_listen_unix_sock(client_socket);
+ if (ret < 0) {
+ goto error;
+ }
+
+ while (1) {
+ /* Blocking call, waiting for transmission */
+ sock = lttcomm_accept_unix_sock(client_socket);
+ if (sock < 0) {
+ goto error;
+ }
+
+ /*
+ * Data is received from the lttng client. The struct
+ * lttcomm_session_msg (lsm) contains the command and data
+ * request of the client.
+ */
+ ret = lttcomm_recv_unix_sock(sock, &lsm, sizeof(lsm));
+ if (ret < 0) {
+ continue;
+ }
+
+ /* This function dispatch the work to the LTTng or UST libs
+ * and make sure that the reply structure (llm) is filled.
+ */
+ llm = process_client_msg(&lsm);
+
+ /* Having a valid lttcomm_lttng_msg struct, reply is sent back
+ * to the client directly.
+ */
+ if (llm != NULL) {
+ ret = lttcomm_send_unix_sock(sock, llm,
+ sizeof(struct lttcomm_lttng_msg));
+ free(llm);
+ if (ret < 0) {
+ continue;
+ }
+ } else {
+ /* The lttcomm_lttng_msg struct was not allocated
+ * correctly. Fatal error since the daemon is not able
+ * to respond. However, we still permit client connection.
+ *
+ * TODO: We should have a default llm that tells the client
+ * that the sessiond had a fatal error and thus the client could
+ * take action to restart ltt-sessiond or inform someone.
+ */
+ }
+ }
+
+error:
+ return NULL;
+}
+
+/*
+ * connect_app
+ *
+ * Return a socket connected to the libust communication socket
+ * of the application identified by the pid.
+ */
+static int connect_app(pid_t pid)
+{
+ int sock;
+
+ sock = ustctl_connect_pid(pid);
+ if (sock < 0) {
+ fprintf(stderr, "Fail connecting to the PID %d\n", pid);
+ }
+
+ return sock;
+}
+
+/*
+ * notify_apps
+ *
+ * Notify apps by writing 42 to a named pipe using name.
+ * Every applications waiting for a ltt-sessiond will be notified
+ * and re-register automatically to the session daemon.
+ *
+ * Return open or write error value.
+ */
+static int notify_apps(const char *name)
+{
+ int fd;
+ int ret = -1;
+
+ /* Try opening the global pipe */
+ fd = open(name, O_WRONLY);
+ if (fd < 0) {
+ goto error;
+ }
+
+ /* Notify by writing on the pipe */
+ ret = write(fd, "42", 2);
+ if (ret < 0) {
+ perror("write");
+ }
+
+error:
+ return ret;
+}
+
+/*
+ * find_session
+ *
+ * Return a ltt_session structure ptr that matches the uuid.
+ */
+static struct ltt_session *find_session(uuid_t session_id)
+{
+ struct ltt_session *iter = NULL;
+
+ /* Sanity check for NULL session_id */
+ if (uuid_is_null(session_id)) {
+ goto end;
+ }
+
+ cds_list_for_each_entry(iter, <t_session_list.head, list) {
+ if (uuid_compare(iter->uuid, session_id)) {
+ break;
+ }
+ }
+
+end:
+ return iter;
+}
+
+/*
+ * destroy_session
+ *
+ * Delete session from the global session list
+ * and free the memory.
+ */
+static void destroy_session(uuid_t session_id)
+{
+ struct ltt_session *iter = NULL;
+
+ cds_list_for_each_entry(iter, <t_session_list.head, list) {
+ if (uuid_compare(iter->uuid, session_id)) {
+ cds_list_del(&iter->list);
+ break;
+ }
+ }
+
+ if (iter) {
+ free(iter);
+ session_count--;
+ }
+}
+
+/*
+ * create_session
+ *
+ * Create a brand new session,
+ */
+static int create_session(const char *name, uuid_t *session_id)
+{
+ struct ltt_session *new_session;
+
+ /* Allocate session data structure */
+ new_session = malloc(sizeof(struct ltt_session));
+ if (new_session == NULL) {
+ perror("malloc");
+ goto error;
+ }
+
+ if (name != NULL) {
+ if (asprintf(&new_session->name, "%s", name) < 0) {
+ goto error;
+ }
+ } else {
+ /* Generate session name based on the session count */
+ if (asprintf(&new_session->name, "%s%d", "auto", session_count) < 0) {
+ goto error;
+ }
+ }
+
+ /* UUID generation */
+ uuid_generate(new_session->uuid);
+ uuid_copy(*session_id, new_session->uuid);
+
+ /* Set consumer (identifier) to 0. This means that there is
+ * NO consumer attach to that session yet.
+ */
+ new_session->ust_consumer = 0;
+ new_session->lttng_consumer = 0;
+
+ /* Init list */
+ CDS_INIT_LIST_HEAD(&new_session->ust_traces);
+ CDS_INIT_LIST_HEAD(&new_session->lttng_traces);
+
+ /* Add new session to the global session list */
+ cds_list_add(&new_session->list, <t_session_list.head);
+
+ session_count++;
+
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * ust_list_apps
+ *
+ * List traceable user-space application and fill an
+ * array of pids.
+ *
+ * Return size of the array.
+ */
+static size_t ust_list_apps(pid_t *pids)
+{
+ size_t size = 0;
+ struct ltt_traceable_app *iter = NULL;
+
+ cds_list_for_each_entry(iter, <t_traceable_app_list.head, list) {
+ if (size >= MAX_APPS_PID) {
+ break;
+ }
+
+ pids[size] = iter->pid;
+ size++;
+ }
+
+ return size;
+}
+
+/*
+ * process_client_msg
+ *
+ * This takes the lttcomm_session_msg struct and process the command requested
+ * by the client. It then creates the reply by allocating a lttcomm_lttng_msg
+ * and fill it with the necessary information.
+ *
+ * It's the caller responsability to free that structure when done with it.
+ *
+ * Return pointer to lttcomm_lttng_msg allocated struct.
+ */
+static struct lttcomm_lttng_msg *process_client_msg(struct lttcomm_session_msg *lsm)
+{
+ struct lttcomm_lttng_msg *llm;
+
+ /* Allocate the reply message structure */
+ llm = malloc(sizeof(struct lttcomm_lttng_msg));
+ if (llm == NULL) {
+ perror("malloc");
+ goto end;
+ }
+
+ /* Copy common data to identify the response
+ * on the lttng client side.
+ */
+ llm->cmd_type = lsm->cmd_type;
+ llm->pid = lsm->pid;
+ if (!uuid_is_null(lsm->session_id)) {
+ uuid_copy(llm->session_id, lsm->session_id);
+ }
+ strncpy(llm->trace_name, lsm->trace_name, sizeof(llm->trace_name));
+
+ /* Default return code.
+ * In a our world, everything is OK... right?
+ */
+ llm->ret_code = LTTCOMM_OK;
+
+ /* Process by command type */
+ switch (lsm->cmd_type) {
+ case UST_LIST_APPS:
+ {
+ llm->u.list_apps.size = ust_list_apps(llm->u.list_apps.pids);
+ break;
+ }
+ default:
+ /* Undefined command */
+ llm->ret_code = LTTCOMM_UND;
+ break;
+ }
+
+end:
+ return llm;
+}
+
+/*
+ * usage function on stderr
+ */
+static void usage(void)
+{
+ fprintf(stderr, "Usage:\n%s OPTIONS\n\nOptions:\n"
+ "\t-h, --help\t\tDisplay this usage.\n"
+ "\t-c, --client-sock PATH\t\tSpecify path for the client unix socket\n"
+ "\t-a, --apps-sock PATH\t\tSpecify path for apps unix socket.\n"
+ "\t-d, --daemonize\t\tStart as a daemon.\n"
+ "\t-g, --group NAME\t\tSpecify the tracing group name. (default: tracing)\n"
+ "\t-V, --version\t\tShow version number.\n",
+ progname);
+}
+
+/*
+ * daemon argument parsing
+ */
+static int parse_args(int argc, char **argv)
+{
+ int c;
+
+ static struct option long_options[] = {
+ { "client-sock", 1, 0, 'c' },
+ { "apps-sock", 1, 0, 'a' },
+ { "daemonize", 0, 0, 'd' },
+ { "help", 0, 0, 'h' },
+ { "group", 1, 0, 'g' },
+ { "version", 0, 0, 'V' },
+ { NULL, 0, 0, 0 }
+ };
+
+ while (1) {
+ int option_index = 0;
+ c = getopt_long(argc, argv, "dhV" "a:c:g:s:", long_options, &option_index);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 0:
+ fprintf(stderr, "option %s", long_options[option_index].name);
+ if (optarg) {
+ fprintf(stderr, " with arg %s\n", optarg);
+ }
+ break;
+ case 's':
+ snprintf(client_unix_sock_path, PATH_MAX, "%s", optarg);
+ break;
+ case 'a':
+ snprintf(apps_unix_sock_path, PATH_MAX, "%s", optarg);
+ break;
+ case 'd':
+ opt_daemon = 1;
+ break;
+ case 'g':
+ opt_tracing_group = strdup(optarg);
+ break;
+ case 'h':
+ usage();
+ exit(EXIT_FAILURE);
+ case 'V':
+ fprintf(stdout, "%s\n", VERSION);
+ exit(EXIT_SUCCESS);
+ default:
+ /* Unknown option or other error.
+ * Error is printed by getopt, just return */
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * init_daemon_socket
+ *
+ * Creates the two needed socket by the daemon.
+ * apps_socket - The communication socket for all UST apps.
+ * client_socket - The communication of the cli tool (lttng).
+ */
+static int init_daemon_socket()
+{
+ int ret = 0;
+ mode_t old_umask;
+
+ old_umask = umask(0);
+
+ /* Create client tool unix socket */
+ client_socket = lttcomm_create_unix_sock(client_unix_sock_path);
+ if (client_socket < 0) {
+ ret = -1;
+ goto end;
+ }
+
+ /* File permission MUST be 660 */
+ ret = chmod(client_unix_sock_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+ if (ret < 0) {
+ perror("chmod");
+ goto end;
+ }
+
+ /* Create the application unix socket */
+ apps_socket = lttcomm_create_unix_sock(apps_unix_sock_path);
+ if (apps_socket < 0) {
+ ret = -1;
+ goto end;
+ }
+
+ /* File permission MUST be 660 */
+ ret = chmod(apps_unix_sock_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+ if (ret < 0) {
+ perror("chmod");
+ goto end;
+ }
+
+end:
+ umask(old_umask);
+ return ret;
+}
+
+/*
+ * check_existing_daemon
+ *
+ * Check if the global socket is available.
+ * If yes, error is returned.
+ */
+static int check_existing_daemon()
+{
+ int ret;
+
+ ret = access(client_unix_sock_path, F_OK);
+ if (ret == 0) {
+ ret = access(apps_unix_sock_path, F_OK);
+ }
+
+ return ret;
+}
+
+/*
+ * get_home_dir
+ *
+ * Return pointer to home directory path using
+ * the env variable HOME.
+ *
+ * Default : /tmp
+ */
+static const char *get_home_dir(void)
+{
+ const char *home_path;
+
+ if ((home_path = (const char*) getenv("HOME")) == NULL) {
+ home_path = default_home_dir;
+ }
+
+ return home_path;
+}
+
+/*
+ * set_socket_perms
+ *
+ * Set the tracing group gid onto the client socket.
+ */
+static int set_socket_perms(void)
+{
+ int ret;
+ struct group *grp;
+
+ /* Decide which group name to use */
+ (opt_tracing_group != NULL) ?
+ (grp = getgrnam(opt_tracing_group)) :
+ (grp = getgrnam(default_tracing_group));
+
+ if (grp == NULL) {
+ fprintf(stderr, "Missing tracing group. Aborting execution.\n");
+ ret = -1;
+ goto end;
+ }
+
+ ret = chown(client_unix_sock_path, 0, grp->gr_gid);
+ if (ret < 0) {
+ perror("chown");
+ }
+
+end:
+ return ret;
+}
+
+/*
+ * daemonize
+ *
+ * Daemonize ltt-sessiond.
+ */
+static void daemonize(void)
+{
+ pid_t pid, sid;
+ const char *home_dir = get_home_dir();
+
+ /* Fork off the parent process */
+ if ((pid = fork()) < 0) {
+ perror("fork");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Parent can now exit */
+ if (pid > 0) {
+ exit(EXIT_SUCCESS);
+ }
+
+ /* Change the file mode mask */
+ umask(0);
+
+ /* Create a new SID for the child process */
+ if ((sid = setsid()) < 0) {
+ perror("setsid");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Change the current working directory */
+ if ((chdir(home_dir)) < 0) {
+ perror("chdir");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Close out the standard file descriptors */
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+}
+
+/*
+ * set_signal_handler
+ *
+ * Setup signal handler for :
+ * SIGINT, SIGTERM, SIGPIPE
+ */
+static int set_signal_handler(void)
+{
+ int ret = 0;
+ struct sigaction sa;
+ sigset_t sigset;
+
+ if ((ret = sigemptyset(&sigset)) < 0) {
+ perror("sigemptyset");
+ return ret;
+ }
+
+ sa.sa_handler = sighandler;
+ sa.sa_mask = sigset;
+ sa.sa_flags = 0;
+ if ((ret = sigaction(SIGTERM, &sa, NULL)) < 0) {
+ perror("sigaction");
+ return ret;
+ }
+
+ if ((ret = sigaction(SIGINT, &sa, NULL)) < 0) {
+ perror("sigaction");
+ return ret;
+ }
+
+ if ((ret = sigaction(SIGPIPE, &sa, NULL)) < 0) {
+ perror("sigaction");
+ return ret;
+ }
+
+ return ret;
+}
+
+/**
+ * sighandler
+ *
+ * Signal handler for the daemon
+ */
+static void sighandler(int sig)
+{
+ switch (sig) {
+ case SIGPIPE:
+ case SIGINT:
+ case SIGTERM:
+ cleanup();
+ default:
+ break;
+ }
+
+ exit(EXIT_SUCCESS);
+}
+
+/*
+ * cleanup
+ *
+ * Cleanup the daemon on exit
+ */
+static void cleanup()
+{
+ /* <fun> */
+ fprintf(stdout, "\n\n%c[%d;%dm*** assert failed *** ==> %c[%dm", 27,1,31,27,0);
+ fprintf(stdout, "%c[%d;%dm Matthew, BEET driven development works!%c[%dm\n",27,1,33,27,0);
+ /* </fun> */
+
+ unlink(client_unix_sock_path);
+ unlink(apps_unix_sock_path);
+}
+
+/*
+ * main
+ */
+int main(int argc, char **argv)
+{
+ int i;
+ int ret = 0;
+ void *status;
+ pthread_t threads[2];
+
+ /* Parse arguments */
+ progname = argv[0];
+ if ((ret = parse_args(argc, argv) < 0)) {
+ goto error;
+ }
+
+ /* Daemonize */
+ if (opt_daemon) {
+ daemonize();
+ }
+
+ /* Check if daemon is UID = 0 */
+ is_root = !getuid();
+
+ /* Set all sockets path */
+ if (is_root) {
+ if (strlen(apps_unix_sock_path) == 0) {
+ (snprintf(apps_unix_sock_path, PATH_MAX,
+ DEFAULT_GLOBAL_APPS_UNIX_SOCK));
+ }
+
+ if (strlen(client_unix_sock_path) == 0) {
+ (snprintf(client_unix_sock_path, PATH_MAX,
+ DEFAULT_GLOBAL_CLIENT_UNIX_SOCK));
+ }
+ } else {
+ if (strlen(apps_unix_sock_path) == 0) {
+ (snprintf(apps_unix_sock_path, PATH_MAX,
+ DEFAULT_HOME_APPS_UNIX_SOCK, get_home_dir()));
+ }
+
+ /* Set the cli tool unix socket path */
+ if (strlen(client_unix_sock_path) == 0) {
+ (snprintf(client_unix_sock_path, PATH_MAX,
+ DEFAULT_HOME_CLIENT_UNIX_SOCK, get_home_dir()));
+ }
+ }
+
+ /* See if daemon already exist. If any of the two
+ * socket needed by the daemon are present, this test fails
+ */
+ if ((ret = check_existing_daemon()) == 0) {
+ fprintf(stderr, "Already running daemon.\n");
+ goto error;
+ }
+
+ if (set_signal_handler() < 0) {
+ goto error;
+ }
+
+ /* Setup the two needed unix socket */
+ if (init_daemon_socket() < 0) {
+ goto error;
+ }
+
+ /* Set credentials to socket */
+ if (is_root && (set_socket_perms() < 0)) {
+ goto error;
+ }
+
+ while (1) {
+ /* Create thread to manage the client socket */
+ ret = pthread_create(&threads[0], NULL, thread_manage_clients, (void *) NULL);
+ if (ret != 0) {
+ perror("pthread_create");
+ goto error;
+ }
+
+ /* Create thread to manage application socket */
+ ret = pthread_create(&threads[1], NULL, thread_manage_apps, (void *) NULL);
+ if (ret != 0) {
+ perror("pthread_create");
+ goto error;
+ }
+
+ for (i = 0; i < 2; i++) {
+ ret = pthread_join(threads[i], &status);
+ if (ret != 0) {
+ perror("pthread_join");
+ goto error;
+ }
+ }
+ }
+
+ cleanup();
+ return 0;
+
+error:
+ cleanup();
+
+ return EXIT_FAILURE;
+}
--- /dev/null
+/* Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _LTT_SESSIOND_H
+#define _LTT_SESSIOND_H
+
+const char default_home_dir[] = "/tmp";
+const char default_tracing_group[] = "tracing";
+const char default_ust_sock_dir[] = "/tmp/ust-app-socks";
+const char default_global_apps_pipe[] = "/tmp/ust-app-socks/global";
+
+/* LTTng trace representation */
+struct ltt_lttng_trace {
+ struct cds_list_head list;
+ char trace_name[NAME_MAX];
+ struct cds_list_head marker_list;
+};
+
+/* UST trace representation */
+struct ltt_ust_trace {
+ struct cds_list_head list;
+ int shmid;
+ char trace_name[NAME_MAX];
+ struct cds_list_head markers;
+};
+
+struct ltt_ust_marker {
+ struct cds_list_head list;
+ char *name;
+ char *channel;
+};
+
+/* Global session list */
+struct ltt_session_list {
+ struct cds_list_head head;
+};
+
+/* Traceable application list */
+struct ltt_traceable_app_list {
+ struct cds_list_head head;
+};
+
+/*
+ * Registered traceable applications. Libust registers
+ * to the session daemon and a linked list is kept
+ * of all running traceable app.
+ */
+struct ltt_traceable_app {
+ struct cds_list_head list;
+ pid_t pid;
+ uid_t uid; /* User ID that owns the apps */
+};
+
+/*
+ * ltt-session - This data structure contains information needed
+ * to identify a tracing session for both LTTng and UST.
+ */
+struct ltt_session {
+ char *name;
+ struct cds_list_head list;
+ uuid_t uuid;
+ struct cds_list_head ust_traces;
+ struct cds_list_head lttng_traces;
+ pid_t ust_consumer;
+ pid_t lttng_consumer;
+};
+
+#endif /* _LTT_SESSIOND_H */
--- /dev/null
+AM_CPPFLAGS = -I$(top_srcdir)/include
+#AM_CFLAGS = $(LTTNG_LIBS) -lpopt
+
+bin_PROGRAMS = lttng
+
+lttng_SOURCES = options.c lttng.c
+
+lttng_LDADD = \
+ $(top_builddir)/liblttngctl/liblttngctl.la
+# $(top_builddir)/liblttsessiondcomm/liblttsessiondcomm.la
--- /dev/null
+/* Copyright (c) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <grp.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <lttng/liblttngctl.h>
+
+#include "lttng.h"
+#include "lttngerr.h"
+
+/* Variables */
+static char *progname;
+
+/* Prototypes */
+static int process_client_opt(void);
+static int process_opt_list_apps(void);
+
+/*
+ * start_client
+ *
+ * Process client request from the command line
+ * options. Every tracing action is done by the
+ * liblttngctl API.
+ */
+static int process_client_opt(void)
+{
+ int ret;
+
+ /* Connect to the session daemon */
+ ret = lttng_connect_sessiond();
+ if (ret < 0) {
+ ERR("%s", lttng_get_readable_code(ret));
+ goto end;
+ }
+
+ if (opt_list_apps) {
+ ret = process_opt_list_apps();
+ if (ret < 0) {
+ ERR("%s", lttng_get_readable_code(ret));
+ goto end;
+ }
+ }
+
+ return 0;
+
+end:
+ return ret;
+}
+
+/*
+ * process_opt_list_apps
+ *
+ * Get the UST traceable pid list and print
+ * them to the user.
+ */
+static int process_opt_list_apps(void)
+{
+ int i, ret;
+ pid_t *pids;
+ FILE *fp;
+ char path[24]; /* Can't go bigger than /proc/65535/cmdline */
+ char cmdline[PATH_MAX];
+
+ ret = lttng_ust_list_apps(&pids);
+ if (ret < 0) {
+ goto error;
+ }
+
+ MSG("LTTng UST traceable application [name (pid)]:");
+ for (i=0; i < ret; i++) {
+ snprintf(path, sizeof(path), "/proc/%d/cmdline", pids[i]);
+ fp = fopen(path, "r");
+ if (fp == NULL) {
+ continue;
+ }
+ ret = fread(cmdline, 1, sizeof(cmdline), fp);
+ MSG("\t%s (%d)", cmdline, pids[i]);
+ fclose(fp);
+ }
+
+ return 0;
+
+error:
+ return ret;
+}
+
+/*
+ * check_ltt_sessiond
+ *
+ * Check if the session daemon is available using
+ * the liblttngctl API for the check.
+ */
+static int check_ltt_sessiond(void)
+{
+ int ret;
+
+ ret = lttng_check_session_daemon();
+ if (ret < 0) {
+ ERR("No session daemon found. Aborting.");
+ }
+
+ return ret;
+}
+
+
+/*
+ * clean_exit
+ */
+void clean_exit(int code)
+{
+ DBG("Clean exit");
+ exit(code);
+}
+
+/*
+ * main
+ */
+int main(int argc, char *argv[])
+{
+ int ret;
+
+ progname = argv[0] ? argv[0] : "lttng";
+
+ /* For Mathieu Desnoyers aka Dr Tracing */
+ if (strncmp(progname, "drtrace", 7) == 0) {
+ MSG("%c[%d;%dmWelcome back Dr Tracing!%c[%dm\n\n", 27,1,33,27,0);
+ }
+
+ ret = parse_args(argc, (const char **) argv);
+ if (ret < 0) {
+ return EXIT_FAILURE;
+ }
+
+ if (opt_tracing_group != NULL) {
+ DBG("Set tracing group to '%s'", opt_tracing_group);
+ lttng_set_tracing_group(opt_tracing_group);
+ }
+
+ /* If ask for kernel tracing, need root perms */
+ if (opt_trace_kernel) {
+ DBG("Kernel tracing activated");
+ if (getuid() != 0) {
+ ERR("%s must be setuid root", progname);
+ return -EPERM;
+ }
+ }
+
+ /* Check if the lttng session daemon is running.
+ * If no, a daemon will be spawned.
+ */
+ if (check_ltt_sessiond() < 0) {
+ return EXIT_FAILURE;
+ }
+
+ ret = process_client_opt();
+ if (ret < 0) {
+ return ret;
+ }
+
+ return 0;
+}
--- /dev/null
+/* Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _LTTNG_H
+#define _LTTNG_H
+
+/* Function prototypes */
+int parse_args(int argc, const char **argv);
+void clean_exit(int code);
+
+/* Command line options */
+extern int opt_trace_kernel;
+extern int opt_verbose;
+extern int opt_quiet;
+extern char *opt_tracing_group;
+extern char *opt_session_name;
+extern int opt_list_apps;
+
+#endif /* _LTTNG_H */
--- /dev/null
+/* Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <popt.h>
+#include <stdlib.h>
+
+#include "lttng.h"
+
+/* Option variables */
+char *opt_tracing_group;
+char *opt_session_name;
+int opt_trace_kernel = 0;
+int opt_quiet = 0;
+int opt_verbose = 0;
+int opt_list_apps = 0;
+
+enum {
+ OPT_HELP = 42,
+};
+
+static struct poptOption long_options[] = {
+ /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
+ {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
+ {"group", 0, POPT_ARG_STRING, &opt_tracing_group, 0, 0},
+ {"kernel", 0, POPT_ARG_VAL, &opt_trace_kernel, 1, 0, 0},
+ {"no-kernel", 0, POPT_ARG_VAL, &opt_trace_kernel, 0, 0, 0},
+ {"session", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_session_name, 0, 0},
+ {"quiet", 'q', POPT_ARG_VAL, &opt_quiet, 1, 0},
+ {"verbose", 'v', POPT_ARG_VAL, &opt_verbose, 1, 0},
+ {"list-apps", 'l', POPT_ARG_VAL, &opt_list_apps, 1, 0},
+ {0, 0, 0, 0, 0, 0}
+};
+
+
+/*
+ * usage
+ */
+static void usage(FILE *ofp)
+{
+ fprintf(ofp, "LTTng Trace Control " VERSION"\n\n");
+ fprintf(ofp, "usage : lttng [OPTION]\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, "Options:\n");
+ fprintf(ofp, " -v, --verbose Verbose mode\n");
+ fprintf(ofp, " -q, --quiet Quiet mode\n");
+ fprintf(ofp, " --help Show help\n");
+ fprintf(ofp, " --group NAME Unix tracing group name. (default: tracing)\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, "Tracing options:\n");
+ //fprintf(ofp, " --session [NAME] Specify tracing session. If no NAME is given\n");
+ //fprintf(ofp, " or option is ommited, a session will be created\n");
+ //fprintf(ofp, " --kernel Enable kernel tracing\n");
+ //fprintf(ofp, " --no-kernel Disable kernel tracing\n");
+ fprintf(ofp, " -l, --list-apps List traceable UST applications\n");
+}
+
+/*
+ * parse_args
+ *
+ * Parse command line arguments.
+ * Return 0 if OK, else -1
+ */
+int parse_args(int argc, const char **argv)
+{
+ static poptContext pc;
+ int opt;
+
+ pc = poptGetContext("lttng", argc, argv, long_options, 0);
+ poptReadDefaultConfig(pc, 0);
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_HELP:
+ usage(stderr);
+ clean_exit(EXIT_SUCCESS);
+ break;
+ default:
+ usage(stderr);
+ clean_exit(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ if (pc) {
+ poptFreeContext(pc);
+ }
+
+ return 0;
+}
--- /dev/null
+SUBDIRS = .
+
+dist_noinst_SCRIPTS = runall