Merge branch 'master' of ssh://git.dorsal.polymtl.ca/home/git/ust
authorMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Wed, 2 Feb 2011 21:59:17 +0000 (16:59 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Wed, 2 Feb 2011 21:59:17 +0000 (16:59 -0500)
31 files changed:
Makefile.am
README
configure.ac
doc/info/ust.texi
doc/man/ustctl.1
doc/man/ustctl.1.md
include/Makefile.am
include/ust/ustcmd.h [deleted file]
include/ust/ustctl.h [new file with mode: 0644]
libustcmd/Makefile.am [deleted file]
libustcmd/README [deleted file]
libustcmd/ustcmd.c [deleted file]
libustctl/Makefile.am [new file with mode: 0644]
libustctl/README [new file with mode: 0644]
libustctl/libustctl.c [new file with mode: 0644]
tests/Makefile.am
tests/libustctl_function_tests/Makefile.am [new file with mode: 0644]
tests/libustctl_function_tests/libustctl_function_tests.c [new file with mode: 0644]
tests/manual_mode_tracing.sh
tests/runtests
tests/ustcmd_function_tests/Makefile.am [deleted file]
tests/ustcmd_function_tests/ustcmd_function_tests.c [deleted file]
ustctl/Makefile.am
ustctl/channel_cmds.c [new file with mode: 0644]
ustctl/cli.c [new file with mode: 0644]
ustctl/cli.h [new file with mode: 0644]
ustctl/marker_cmds.c [new file with mode: 0644]
ustctl/scanning_functions.c [new file with mode: 0644]
ustctl/scanning_functions.h [new file with mode: 0644]
ustctl/trace_cmds.c [new file with mode: 0644]
ustctl/ustctl.c

index 249bf026d5cad0f4deb282f937f41a16a42759ab..6957f07de11c00c278f30e66f8f007b677457ddd 100644 (file)
@@ -5,7 +5,7 @@ ACLOCAL_AMFLAGS = -I config
 # libust and '.' (that contains the linker script). However, '.'
 # must be installed after libust so it can overwrite libust.so with
 # the linker script.
-SUBDIRS = snprintf libustcomm libustcmd libust . tests libustinstr-malloc libustconsumer ust-consumerd ustctl libustfork include doc
+SUBDIRS = snprintf libustcomm libustctl libust . tests libustinstr-malloc libustconsumer ust-consumerd ustctl libustfork include doc
 
 EXTRA_DIST = libust.ldscript.in libust-initializer.c libust-initializer.h
 dist_bin_SCRIPTS = usttrace
diff --git a/README b/README
index a381c951a376f1debab6e3583c67ba3f1cebcacb..b09a1ab7e75259635421565a0316d7e744fc1d01 100644 (file)
--- a/README
+++ b/README
@@ -79,11 +79,11 @@ PACKAGE CONTENTS:
     calls in order to trace across these calls. It _has_ to be LD_PRELOAD'ed
     in order to hijack calls. In contrast, libust may be linked at build time.
 
-  - libustcmd
+  - libustctl
     A library to control tracing in other processes. Used by ustctl.
 
   - libustcomm
-    A static library shared between libust, ust-consumerd and libustcmd, that
+    A static library shared between libust, ust-consumerd and libustctl, that
     provides functions that allow these components to communicate together.
 
   - libustconsumer
index c7d966b91d1eedea78c5ce143705a30b19757cfc..2b2962a5e1891231effe8c83e9249f28e9a0c061 100644 (file)
@@ -130,14 +130,14 @@ AC_CONFIG_FILES([
        tests/tracepoint/Makefile
        tests/tracepoint/benchmark/Makefile
        tests/register_test/Makefile
-       tests/ustcmd_function_tests/Makefile
+       tests/libustctl_function_tests/Makefile
        libustinstr-malloc/Makefile
        libustfork/Makefile
        libustconsumer/Makefile
        ust-consumerd/Makefile
        ustctl/Makefile
        libustcomm/Makefile
-       libustcmd/Makefile
+       libustctl/Makefile
        snprintf/Makefile
 ])
 AC_OUTPUT
index efad0f6b92111664a390dda92adb954c8cf35a03..83c91e022802011803201e523afa949e76722975 100644 (file)
@@ -91,7 +91,7 @@ Components licensed as LGPL v2.1:
 Components licensed as GPL v2:
 @itemize @bullet
 @item ustctl
-@item libustcmd
+@item libustctl
 @item ust-consumerd
 @end itemize
 
@@ -395,25 +395,25 @@ $ ust-consumerd
 # it has pid 1234.
 
 # List the available markers
-$ ustctl --list-markers 1234
+$ ustctl list-markers 1234
 # A column indicates 0 for an inactive marker and 1 for an active marker.
 
 # Enable a marker
-$ ustctl --enable-marker ust/mymark 1234
+$ ustctl enable-marker 1234 auto ust/mymark
 
 # Create a trace
-$ ustctl --create-trace 1234
+$ ustctl create-trace 1234 auto
 
 # Start tracing
-$ ustctl --start-trace 1234
+$ ustctl start-trace 1234 auto
 
 # Do things...
 
 # Stop tracing
-$ ustctl --stop-trace 1234
+$ ustctl stop-trace 1234 auto
 
 # Destroy the trace
-$ ustctl --destroy-trace 1234
+$ ustctl destroy-trace 1234 auto
 @end verbatim
 @end example
 
index b0f97d9a774e5898a91b2b30f053061867d9606d..2250b316a78500af31ec7c89cfd0887433a44b7c 100644 (file)
-.\" generated with Ronn/v0.5
-.\" http://github.com/rtomayko/ronn/
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
 .
-.TH "USTCTL" "1" "August 2010" "" ""
+.TH "USTCTL" "1" "January 2011" "" ""
 .
 .SH "NAME"
-\fBustctl\fR \-\- a program to control the tracing of userspace applications
+\fBustctl\fR \- a program to control the tracing of userspace applications
 .
 .SH "SYNOPSIS"
-\fBustctl\fR [\fIcommand\fR] [\fIPIDs\fR]...
+\fBustctl\fR [\fICOMMAND\fR] [\fIARGS\fR]\.\.\.
 .
 .SH "DESCRIPTION"
-\fBustctl\fR is a program to control the tracing of userspace applications. It can
-list markers, start the tracing, stop the tracing, enable/disable markers, etc.
+\fBustctl\fR is a program to control the tracing of userspace applications\. It can list markers, start the tracing, stop the tracing, enable/disable markers, etc\.
 .
 .SH "OPTIONS"
-These programs follow the usual GNU command line syntax, with long options
-starting with two dashes(`\-'). A summary of options is included below.
+These programs follow the usual GNU command line syntax, with long options starting with two dashes(`\-\')\. A summary of options is included below\.
 .
 .TP
 \fB\-h\fR, \fB\-\-help\fR
-Show summary of options.
+Show summary of commands\.
+.
+.SH "COMMANDS"
+\fBustctl\fR accepts commands followed by arguments for each respective command\. Most commands require the pid of the application being traced\.
 .
 .TP
-\fB\-\-create\-trace\fR
-Create trace.
+\fBcreate\-trace\fR \fIPID\fR \fITRACE\fR
+Create trace\.
 .
 .TP
-\fB\-\-alloc\-trace\fR
-Allocate trace.
+\fBalloc\-trace\fR \fIPID\fR \fITRACE\fR
+Allocate trace\.
 .
 .TP
-\fB\-\-start\-trace\fR
-Start tracing.
+\fBstart\-trace\fR \fIPID\fR \fITRACE\fR
+Start tracing\.
 .
 .TP
-\fB\-\-stop\-trace\fR
-Stop tracing.
+\fBstop\-trace\fR \fIPID\fR \fITRACE\fR
+Stop tracing\.
 .
 .TP
-\fB\-\-destroy\-trace\fR
-Destroy the trace.
+\fBdestroy\-trace\fR \fIPID\fR \fITRACE\fR
+Destroy the trace\.
 .
 .TP
-\fB\-\-set\-subbuf\-size\fR \fICHANNEL\fR/\fIbytes\fR
-Set the size of subbuffers in CHANNEL.
+\fBset\-subbuf\-size\fR \fIPID\fR \fITRACE\fR \fICHANNEL\fR/\fIbytes\fR
+Set the size of subbuffers in CHANNEL\.
 .
 .TP
-\fB\-\-set\-subbuf\-num\fR \fICHANNEL\fR
-Set the number of subbuffers per buffer for CHANNEL. Must be a power of 2.
+\fBset\-subbuf\-num\fR \fIPID\fR \fITRACE\fR \fICHANNEL\fR/\fInr\fR
+Set the number of subbuffers per buffer for CHANNEL\. Must be a power of 2\.
 .
 .TP
-\fB\-\-set\-sock\-path\fR
-Set the path of the daemon socket.
+\fBset\-sock\-path\fR \fIPID\fR \fISOCKPATH\fR
+Set the path of the daemon socket\.
 .
 .TP
-\fB\-\-get\-subbuf\-size\fR \fICHANNEL\fR
-Print the size of subbuffers per buffer for CHANNEL.
+\fBget\-subbuf\-size\fR \fIPID\fR \fITRACE\fR \fICHANNEL\fR
+Print the size of subbuffers per buffer for CHANNEL\.
 .
 .TP
-\fB\-\-get\-subbuf\-num\fR \fICHANNEL\fR
-Print the number of subbuffers per buffer for CHANNEL.
+\fBget\-subbuf\-num\fR \fIPID\fR \fITRACE\fR \fICHANNEL\fR
+Print the number of subbuffers per buffer for CHANNEL\.
 .
 .TP
-\fB\-\-get\-sock\-path\fR
-Get the path of the daemon socket.
+\fBget\-sock\-path\fR \fIPID\fR
+Get the path of the daemon socket\.
 .
 .TP
-\fB\-\-enable\-marker\fR \fICHANNEL\fR/\fIMARKER\fR
-Enable a marker.
+\fBenable\-marker\fR \fIPID\fR \fITRACE\fR \fICHANNEL\fR/\fIMARKER\fR
+Enable a marker\.
 .
 .TP
-\fB\-\-disable\-marker\fR \fICHANNEL\fR/\fIMARKER\fR
-Disable a marker.
+\fBdisable\-marker\fR \fIPID\fR \fITRACE\fR \fICHANNEL\fR/\fIMARKER\fR
+Disable a marker\.
 .
 .TP
-\fB\-\-list\-markers\fR
-List the markers of the process, their state and format string.
+\fBlist\-markers\fR \fIPID\fR
+List the markers of the process, their state and format string\.
 .
 .TP
-\fB\-\-force\-switch\fR
-Force a subbuffer switch. This will flush all the data currently held.
+\fBforce\-subbuf\-switch\fR \fIPID\fR \fITRACE\fR
+Force a subbuffer switch\. This will flush all the data currently held\.
 .
 .SH "LIFE CYCLE OF A TRACE"
-Typically, the first step is to enable markers with \fB\-\-enable\-marker\fR. An
-enabled marker generates an event when the control flow passes over it
-(assuming the trace is recording). A disabled marker produces nothing. Enabling
-and disabling markers may however be done at any point, including while the
-trace is being recorded.
+Typically, the first step is to enable markers with \fBenable\-marker\fR\. An enabled marker generates an event when the control flow passes over it (assuming the trace is recording)\. A disabled marker produces nothing\. Enabling and disabling markers may however be done at any point, including while the trace is being recorded\.
 .
 .P
-In order to record events, a trace is first created with \fB\-\-create\-trace\fR. At
-this point, the subbuffer count and size may be changed with \fB\-\-set\-subbuf\-num\fR
-and \fB\-\-set\-subbuf\-size\fR.
+In order to record events, a trace is first created with \fBcreate\-trace\fR\. At this point, the subbuffer count and size may be changed with \fBset\-subbuf\-num\fR and \fBset\-subbuf\-size\fR\.
 .
 .P
-Afterward, the trace may be allocated with \fB\-\-alloc\-trace\fR. This allocates the
-buffers in memory, so once this is done, the subbuffer size and count can not
-be changed. Trace allocation also causes the daemon to connect to the trace
-buffers and wait for data to arrive. Explicit allocation is optional, as it is
-done automatically at trace start.
+Afterward, the trace may be allocated with \fBalloc\-trace\fR\. This allocates the buffers in memory, so once this is done, the subbuffer size and count can not be changed\. Trace allocation also causes the daemon to connect to the trace buffers and wait for data to arrive\. Explicit allocation is optional, as it is done automatically at trace start\.
 .
 .P
-The trace may then be started with \fB\-\-start\-trace\fR. This results in events
-being recorded in the buffer. The daemon automatically collects these events.
+The trace may then be started with \fBstart\-trace\fR\. This results in events being recorded in the buffer\. The daemon automatically collects these events\.
 .
 .P
-The trace may be stopped with \fB\-\-stop\-trace\fR, either definitely after all the
-wanted information is collected, or temporarily, before being started again
-with \fB\-\-start\-trace\fR. This results in effectively 'pausing' the recording.
-After using \fB\-\-stop\-trace\fR, if a daemon is collecting the trace, it may not
-have flushed to the disk the full contents of the buffer yet.
+The trace may be stopped with \fBstop\-trace\fR, either definitely after all the wanted information is collected, or temporarily, before being started again with \fBstart\-trace\fR\. This results in effectively \'pausing\' the recording\. After using \fBstop\-trace\fR, if a daemon is collecting the trace, it may not have flushed to the disk the full contents of the buffer yet\.
 .
 .P
-Finally, when \fB\-\-destroy\-trace\fR is used, the trace buffers are unallocated.
-However, the memory may not be effectively freed until the daemon finishes to
-collect them. When the trace is being collected by \fBust-consumerd\fR, this command
-guarantees its full contents is flushed to the disk.
+Finally, when \fBdestroy\-trace\fR is used, the trace buffers are unallocated\. However, the memory may not be effectively freed until the daemon finishes to collect them\. When the trace is being collected by \fBust\-consumerd\fR, this command guarantees its full contents is flushed to the disk\.
 .
 .SH "STRUCTURE OF A TRACE"
-Each instrumentation point that is added in a program is associated to a
-channel.
+Each instrumentation point that is added in a program is associated to a channel\.
 .
 .P
-Trace events are put in buffers. There is one buffer per channel, per cpu.
-For example, on a system with 4 cores and tracing an application with 3
-channels, there will be 12 buffers in total. The content of each of these
-buffers is put in a distinct file in the trace directory. For example, the \fBmetadata_2\fR file contains the data that was extracted from the buffer that
-contained the events from the metadata channel and having occurred on cpu 2.
+Trace events are put in buffers\. There is one buffer per channel, per cpu\. For example, on a system with 4 cores and tracing an application with 3 channels, there will be 12 buffers in total\. The content of each of these buffers is put in a distinct file in the trace directory\. For example, the \fBmetadata_2\fR file contains the data that was extracted from the buffer that contained the events from the metadata channel and having occurred on cpu 2\.
 .
 .P
-In memory, each buffer is divided in subbuffers. Subbuffers are equally\-sized,
-contiguous parts of a buffer. The size of a buffer is equal to the number of
-subbuffers it contains times the size of each subbuffer. When a subbuffer is
-full, it is collected by the daemon while the others are filled. If, however,
-the buffer size is too small, buffer overflows may occur and result in event
-loss. By default, the number of subbuffers per buffer is 2. Subbuffer size
-for a given channel may be chosen with \fB\-\-set\-subbuf\-size\fR while the subbuffer
-count is set with \fB\-\-set\-subbuf\-num\fR.
+In memory, each buffer is divided in subbuffers\. Subbuffers are equally\-sized, contiguous parts of a buffer\. The size of a buffer is equal to the number of subbuffers it contains times the size of each subbuffer\. When a subbuffer is full, it is collected by the daemon while the others are filled\. If, however, the buffer size is too small, buffer overflows may occur and result in event loss\. By default, the number of subbuffers per buffer is 2\. Subbuffer size for a given channel may be chosen with \fBset\-subbuf\-size\fR while the subbuffer count is set with \fBset\-subbuf\-num\fR\.
 .
 .SH "SEE ALSO"
-usttrace(1), ust-consumerd(1)
+usttrace(1), ust\-consumerd(1)
 .
 .SH "AUTHOR"
-\fBustctl\fR was written by Pierre\-Marc Fournier.
+\fBustctl\fR was written by Pierre\-Marc Fournier\.
 .
 .P
-This manual page was written by Jon Bernard <jbernard@debian.org>, for
-the Debian project (and may be used by others). It was updated by Pierre\-Marc
-Fournier.
+This manual page was written by Jon Bernard <jbernard@debian\.org>, for the Debian project (and may be used by others)\. It was updated by Pierre\-Marc Fournier\.
index c8ad1f1722fc907bb03a31e0f88a2cfb59b44b55..89a952ac33a9e5f6b58824053183bb485d5636cc 100644 (file)
@@ -3,7 +3,7 @@ ustctl(1) -- a program to control the tracing of userspace applications
 
 ## SYNOPSIS
 
-`ustctl` [<command>] [<PIDs>]...
+`ustctl` [<COMMAND>] [<ARGS>]...
 
 ## DESCRIPTION
 
@@ -16,81 +16,86 @@ These programs follow the usual GNU command line syntax, with long options
 starting with two dashes(`-'). A summary of options is included below.
 
   * `-h`, `--help`:
-    Show summary of options.
+    Show summary of commands.
 
-  * `--create-trace`:
+## COMMANDS
+
+`ustctl` accepts commands followed by arguments for each respective command.
+Most commands require the pid of the application being traced.
+
+  * `create-trace` <PID> <TRACE>:
     Create trace.
 
-  * `--alloc-trace`:
+  * `alloc-trace` <PID> <TRACE>:
     Allocate trace.
 
-  * `--start-trace`:
+  * `start-trace` <PID> <TRACE>:
     Start tracing.
 
-  * `--stop-trace`:
+  * `stop-trace` <PID> <TRACE>:
     Stop tracing.
 
-  * `--destroy-trace`:
+  * `destroy-trace` <PID> <TRACE>:
     Destroy the trace.
 
-  * `--set-subbuf-size` <CHANNEL>/<bytes>:
+  * `set-subbuf-size`  <PID> <TRACE> <CHANNEL>/<bytes>:
     Set the size of subbuffers in CHANNEL.
 
-  * `--set-subbuf-num` <CHANNEL>:
+  * `set-subbuf-num`  <PID> <TRACE> <CHANNEL>/<nr>:
     Set the number of subbuffers per buffer for CHANNEL. Must be a power of 2.
 
-  * `--set-sock-path`:
+  * `set-sock-path` <PID> <SOCKPATH>:
     Set the path of the daemon socket.
 
-  * `--get-subbuf-size` <CHANNEL>:
+  * `get-subbuf-size` <PID> <TRACE> <CHANNEL>:
     Print the size of subbuffers per buffer for CHANNEL.
 
-  * `--get-subbuf-num` <CHANNEL>:
+  * `get-subbuf-num` <PID> <TRACE> <CHANNEL>:
     Print the number of subbuffers per buffer for CHANNEL.
 
-  * `--get-sock-path`:
+  * `get-sock-path` <PID>:
     Get the path of the daemon socket.
 
-  * `--enable-marker` <CHANNEL>/<MARKER>:
+  * `enable-marker` <PID> <TRACE> <CHANNEL>/<MARKER>:
     Enable a marker.
 
-  * `--disable-marker` <CHANNEL>/<MARKER>:
+  * `disable-marker` <PID> <TRACE> <CHANNEL>/<MARKER>:
     Disable a marker.
 
-  * `--list-markers`:
+  * `list-markers` <PID>:
     List the markers of the process, their state and format string.
 
-  * `--force-switch`:
+  * `force-subbuf-switch` <PID> <TRACE>:
     Force a subbuffer switch. This will flush all the data currently held.
 
 ## LIFE CYCLE OF A TRACE
 
-Typically, the first step is to enable markers with `--enable-marker`. An
+Typically, the first step is to enable markers with `enable-marker`. An
 enabled marker generates an event when the control flow passes over it
 (assuming the trace is recording). A disabled marker produces nothing. Enabling
 and disabling markers may however be done at any point, including while the
 trace is being recorded.
 
-In order to record events, a trace is first created with `--create-trace`. At
-this point, the subbuffer count and size may be changed with `--set-subbuf-num`
-and `--set-subbuf-size`.
+In order to record events, a trace is first created with `create-trace`. At
+this point, the subbuffer count and size may be changed with `set-subbuf-num`
+and `set-subbuf-size`.
 
-Afterward, the trace may be allocated with `--alloc-trace`. This allocates the
+Afterward, the trace may be allocated with `alloc-trace`. This allocates the
 buffers in memory, so once this is done, the subbuffer size and count can not
 be changed. Trace allocation also causes the daemon to connect to the trace
 buffers and wait for data to arrive. Explicit allocation is optional, as it is
 done automatically at trace start.
 
-The trace may then be started with `--start-trace`. This results in events
+The trace may then be started with `start-trace`. This results in events
 being recorded in the buffer. The daemon automatically collects these events.
 
-The trace may be stopped with `--stop-trace`, either definitely after all the
+The trace may be stopped with `stop-trace`, either definitely after all the
 wanted information is collected, or temporarily, before being started again
-with `--start-trace`. This results in effectively 'pausing' the recording.
-After using `--stop-trace`, if a daemon is collecting the trace, it may not
+with `start-trace`. This results in effectively 'pausing' the recording.
+After using `stop-trace`, if a daemon is collecting the trace, it may not
 have flushed to the disk the full contents of the buffer yet.
 
-Finally, when `--destroy-trace` is used, the trace buffers are unallocated.
+Finally, when `destroy-trace` is used, the trace buffers are unallocated.
 However, the memory may not be effectively freed until the daemon finishes to
 collect them. When the trace is being collected by `ust-consumerd`, this command
 guarantees its full contents is flushed to the disk.
@@ -113,8 +118,8 @@ subbuffers it contains times the size of each subbuffer. When a subbuffer is
 full, it is collected by the daemon while the others are filled. If, however,
 the buffer size is too small, buffer overflows may occur and result in event
 loss. By default, the number of subbuffers per buffer is 2. Subbuffer size
-for a given channel may be chosen with `--set-subbuf-size` while the subbuffer
-count is set with `--set-subbuf-num`.
+for a given channel may be chosen with `set-subbuf-size` while the subbuffer
+count is set with `set-subbuf-num`.
 
 ## SEE ALSO
 
index 400e8b1a8fde99f3fbefb139d1dcaef4f588651f..e703ffd094949eaf8c60b7b50d82576c5052170b 100644 (file)
@@ -17,7 +17,7 @@ nobase_include_HEADERS = \
        ust/kcompat/simple.h \
        ust/kcompat/types.h \
        ust/kcompat/stringify.h \
-       ust/ustcmd.h \
+       ust/ustctl.h \
        ust/ustconsumer.h
 
 noinst_HEADERS = share.h usterr.h ust_snprintf.h
diff --git a/include/ust/ustcmd.h b/include/ust/ustcmd.h
deleted file mode 100644 (file)
index 6273575..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/* Copyright (C) 2009  Pierre-Marc Fournier
- *
- * 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
- */
-
-#ifndef _USTCMD_H
-#define _USTCMD_H
-
-#include <stdio.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <fcntl.h>
-
-#define USTCMD_ERR_CONN                1 /* Process connection error */
-#define USTCMD_ERR_ARG         2 /* Invalid function argument */
-#define USTCMD_ERR_GEN         3 /* General ustcmd error */
-
-#define USTCMD_MS_CHR_OFF      '0' /* Marker state 'on' character */
-#define USTCMD_MS_CHR_ON       '1' /* Marker state 'on' character */
-#define USTCMD_MS_OFF          0   /* Marker state 'on' value */
-#define USTCMD_MS_ON           1   /* Marker state 'on' value */
-
-#define USTCMD_SOCK_PATH       "/tmp/socks/"
-
-/* Channel/marker/state/format string (cmsf) info. structure */
-struct marker_status {
-       char *channel; /* Channel name (end of marker_status array if NULL) */
-       char *marker; /* Marker name (end of marker_status array if NULL) */
-       int state; /* State (0 := marker disabled, 1 := marker enabled) */
-       char *fs; /* Format string (end of marker_status array if NULL) */
-};
-
-struct trace_event_status {
-       char *name;
-};
-
-extern pid_t *ustcmd_get_online_pids(void);
-extern int ustcmd_set_marker_state(const char *trace, const char *channel,
-                                  const char *marker, int state, pid_t pid);
-extern int ustcmd_set_subbuf_size(const char *trace, const char *channel,
-                                 unsigned int subbuf_size, pid_t pid);
-extern int ustcmd_set_subbuf_num(const char *trace, const char *channel,
-                                unsigned int num, pid_t pid);
-extern int ustcmd_get_subbuf_size(const char *trace, const char *channel,
-                                 pid_t pid);
-extern int ustcmd_get_subbuf_num(const char *trace, const char *channel,
-                                pid_t pid);
-extern int ustcmd_destroy_trace(const char *trace, pid_t pid);
-extern int ustcmd_setup_and_start(const char *trace, pid_t pid);
-extern int ustcmd_stop_trace(const char *trace, pid_t pid);
-extern int ustcmd_create_trace(const char *trace, pid_t pid);
-extern int ustcmd_start_trace(const char *trace, pid_t pid);
-extern int ustcmd_alloc_trace(const char *trace, pid_t pid);
-extern int ustcmd_free_cmsf(struct marker_status *);
-extern unsigned int ustcmd_count_nl(const char *);
-extern int ustcmd_get_cmsf(struct marker_status **, pid_t);
-extern int ustcmd_free_tes(struct trace_event_status *);
-extern int ustcmd_get_tes(struct trace_event_status **, pid_t);
-extern int ustcmd_set_sock_path(const char *sock_path, pid_t pid);
-extern int ustcmd_get_sock_path(char **sock_path, pid_t pid);
-extern int ustcmd_force_switch(pid_t pid);
-
-#endif /* _USTCMD_H */
diff --git a/include/ust/ustctl.h b/include/ust/ustctl.h
new file mode 100644 (file)
index 0000000..195ee26
--- /dev/null
@@ -0,0 +1,76 @@
+/* Copyright (C) 2009  Pierre-Marc Fournier
+ *
+ * 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
+ */
+
+#ifndef _USTCTL_H
+#define _USTCTL_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#define USTCTL_ERR_CONN                1 /* Process connection error */
+#define USTCTL_ERR_ARG         2 /* Invalid function argument */
+#define USTCTL_ERR_GEN         3 /* General ustctl error */
+
+#define USTCTL_MS_CHR_OFF      '0' /* Marker state 'on' character */
+#define USTCTL_MS_CHR_ON       '1' /* Marker state 'on' character */
+#define USTCTL_MS_OFF          0   /* Marker state 'on' value */
+#define USTCTL_MS_ON           1   /* Marker state 'on' value */
+
+#define USTCTL_SOCK_PATH       "/tmp/socks/"
+
+/* Channel/marker/state/format string (cmsf) info. structure */
+struct marker_status {
+       char *channel; /* Channel name (end of marker_status array if NULL) */
+       char *marker; /* Marker name (end of marker_status array if NULL) */
+       int state; /* State (0 := marker disabled, 1 := marker enabled) */
+       char *fs; /* Format string (end of marker_status array if NULL) */
+};
+
+struct trace_event_status {
+       char *name;
+};
+
+extern pid_t *ustctl_get_online_pids(void);
+extern int ustctl_set_marker_state(const char *trace, const char *channel,
+                                  const char *marker, int state, pid_t pid);
+extern int ustctl_set_subbuf_size(const char *trace, const char *channel,
+                                 unsigned int subbuf_size, pid_t pid);
+extern int ustctl_set_subbuf_num(const char *trace, const char *channel,
+                                unsigned int num, pid_t pid);
+extern int ustctl_get_subbuf_size(const char *trace, const char *channel,
+                                 pid_t pid);
+extern int ustctl_get_subbuf_num(const char *trace, const char *channel,
+                                pid_t pid);
+extern int ustctl_destroy_trace(const char *trace, pid_t pid);
+extern int ustctl_setup_and_start(const char *trace, pid_t pid);
+extern int ustctl_stop_trace(const char *trace, pid_t pid);
+extern int ustctl_create_trace(const char *trace, pid_t pid);
+extern int ustctl_start_trace(const char *trace, pid_t pid);
+extern int ustctl_alloc_trace(const char *trace, pid_t pid);
+extern int ustctl_free_cmsf(struct marker_status *);
+extern unsigned int ustctl_count_nl(const char *);
+extern int ustctl_get_cmsf(struct marker_status **, pid_t);
+extern int ustctl_free_tes(struct trace_event_status *);
+extern int ustctl_get_tes(struct trace_event_status **, pid_t);
+extern int ustctl_set_sock_path(const char *sock_path, pid_t pid);
+extern int ustctl_get_sock_path(char **sock_path, pid_t pid);
+extern int ustctl_force_switch(pid_t pid);
+
+#endif /* _USTCTL_H */
diff --git a/libustcmd/Makefile.am b/libustcmd/Makefile.am
deleted file mode 100644 (file)
index f467244..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/libustcomm
-AM_CFLAGS = -fno-strict-aliasing
-
-lib_LTLIBRARIES = libustcmd.la
-
-libustcmd_la_SOURCES = \
-       ustcmd.c
-
-libustcmd_la_LDFLAGS = -no-undefined -version-info 0:0:0
-
-libustcmd_la_LIBADD = \
-       $(top_builddir)/libustcomm/libustcomm.la
-
-libustcmd_la_CFLAGS = -DUST_COMPONENT="libustcmd" -fno-strict-aliasing
diff --git a/libustcmd/README b/libustcmd/README
deleted file mode 100644 (file)
index 8c2819a..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-libustcmd is a library that provides an API and its implementation to send
-commands to traceable processes.
diff --git a/libustcmd/ustcmd.c b/libustcmd/ustcmd.c
deleted file mode 100644 (file)
index 62c117f..0000000
+++ /dev/null
@@ -1,671 +0,0 @@
-/* Copyright (C) 2009  Pierre-Marc Fournier, Philippe Proulx-Barrette
- *
- * 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
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <string.h>
-#include <dirent.h>
-
-#include "ustcomm.h"
-#include "ust/ustcmd.h"
-#include "usterr.h"
-
-static int do_cmd(const pid_t pid,
-                 const struct ustcomm_header *req_header,
-                 const char *req_data,
-                 struct ustcomm_header *res_header,
-                 char **res_data)
-{
-       int app_fd, result, saved_errno = 0;
-       char *recv_buf;
-
-       if (ustcomm_connect_app(pid, &app_fd)) {
-               ERR("could not connect to PID %u", (unsigned int) pid);
-               errno = ENOTCONN;
-               return -1;
-       }
-
-       recv_buf = zmalloc(USTCOMM_BUFFER_SIZE);
-       if (!recv_buf) {
-               saved_errno = ENOMEM;
-               goto close_app_fd;
-       }
-
-       result = ustcomm_req(app_fd, req_header, req_data, res_header, recv_buf);
-       if (result > 0) {
-               saved_errno = -res_header->result;
-               if (res_header->size == 0 || saved_errno > 0) {
-                       free(recv_buf);
-               } else {
-                       if (res_data) {
-                               *res_data = recv_buf;
-                       } else {
-                               free(recv_buf);
-                       }
-               }
-       } else {
-               ERR("ustcomm req failed");
-               if (result == 0) {
-                       saved_errno = ENOTCONN;
-               } else {
-                       saved_errno = -result;
-               }
-               free(recv_buf);
-       }
-
-close_app_fd:
-       close(app_fd);
-
-       errno = saved_errno;
-
-       if (errno) {
-               return -1;
-       }
-
-       return 0;
-}
-
-pid_t *ustcmd_get_online_pids(void)
-{
-       struct dirent *dirent;
-       DIR *dir;
-       unsigned int ret_size = 1 * sizeof(pid_t), i = 0;
-
-       dir = opendir(SOCK_DIR);
-       if (!dir) {
-               return NULL;
-       }
-
-       pid_t *ret = (pid_t *) malloc(ret_size);
-
-       while ((dirent = readdir(dir))) {
-               if (!strcmp(dirent->d_name, ".") ||
-                   !strcmp(dirent->d_name, "..")) {
-
-                       continue;
-               }
-
-               if (dirent->d_type != DT_DIR &&
-                   !!strcmp(dirent->d_name, "ust-consumer")) {
-
-                       sscanf(dirent->d_name, "%u", (unsigned int *) &ret[i]);
-                       /* FIXME: Here we previously called pid_is_online, which
-                        * always returned 1, now I replaced it with just 1.
-                        * We need to figure out an intelligent way of solving
-                        * this, maybe connect-disconnect.
-                        */
-                       if (1) {
-                               ret_size += sizeof(pid_t);
-                               ret = (pid_t *) realloc(ret, ret_size);
-                               ++i;
-                       }
-               }
-       }
-
-       ret[i] = 0; /* Array end */
-
-       if (ret[0] == 0) {
-               /* No PID at all */
-               free(ret);
-               return NULL;
-       }
-
-       closedir(dir);
-       return ret;
-}
-
-/**
- * Sets marker state (USTCMD_MS_ON or USTCMD_MS_OFF).
- *
- * @param mn   Marker name
- * @param state        Marker's new state
- * @param pid  Traced process ID
- * @return     0 if successful, or errors {USTCMD_ERR_GEN, USTCMD_ERR_ARG}
- */
-int ustcmd_set_marker_state(const char *trace, const char *channel,
-                           const char *marker, int state, pid_t pid)
-{
-       struct ustcomm_header req_header, res_header;
-       struct ustcomm_marker_info marker_inf;
-       int result;
-
-       result = ustcomm_pack_marker_info(&req_header,
-                                         &marker_inf,
-                                         trace,
-                                         channel,
-                                         marker);
-       if (result < 0) {
-               errno = -result;
-               return -1;
-       }
-
-       req_header.command = state ? ENABLE_MARKER : DISABLE_MARKER;
-
-       return do_cmd(pid, &req_header, (char *)&marker_inf,
-                     &res_header, NULL);
-}
-
-/**
- * Set subbuffer size.
- *
- * @param channel_size Channel name and size
- * @param pid          Traced process ID
- * @return             0 if successful, or error
- */
-int ustcmd_set_subbuf_size(const char *trace, const char *channel,
-                          unsigned int subbuf_size, pid_t pid)
-{
-       struct ustcomm_header req_header, res_header;
-       struct ustcomm_channel_info ch_inf;
-       int result;
-
-       result = ustcomm_pack_channel_info(&req_header,
-                                          &ch_inf,
-                                          trace,
-                                          channel);
-       if (result < 0) {
-               errno = -result;
-               return -1;
-       }
-
-       req_header.command = SET_SUBBUF_SIZE;
-       ch_inf.subbuf_size = subbuf_size;
-
-       return do_cmd(pid, &req_header, (char *)&ch_inf,
-                     &res_header, NULL);
-}
-
-/**
- * Set subbuffer num.
- *
- * @param channel_num  Channel name and num
- * @param pid          Traced process ID
- * @return             0 if successful, or error
- */
-int ustcmd_set_subbuf_num(const char *trace, const char *channel,
-                         unsigned int num, pid_t pid)
-{
-       struct ustcomm_header req_header, res_header;
-       struct ustcomm_channel_info ch_inf;
-       int result;
-
-       result = ustcomm_pack_channel_info(&req_header,
-                                          &ch_inf,
-                                          trace,
-                                          channel);
-       if (result < 0) {
-               errno = -result;
-               return -1;
-       }
-
-       req_header.command = SET_SUBBUF_NUM;
-       ch_inf.subbuf_num = num;
-
-       return do_cmd(pid, &req_header, (char *)&ch_inf,
-                     &res_header, NULL);
-
-}
-
-static int ustcmd_get_subbuf_num_size(const char *trace, const char *channel,
-                                     pid_t pid, int *num, int *size)
-{
-       struct ustcomm_header req_header, res_header;
-       struct ustcomm_channel_info ch_inf, *ch_inf_res;
-       int result;
-
-
-       result = ustcomm_pack_channel_info(&req_header,
-                                          &ch_inf,
-                                          trace,
-                                          channel);
-       if (result < 0) {
-               errno = -result;
-               return -1;
-       }
-
-       req_header.command = GET_SUBBUF_NUM_SIZE;
-
-       result = do_cmd(pid, &req_header, (char *)&ch_inf,
-                       &res_header, (char **)&ch_inf_res);
-       if (result < 0) {
-               return -1;
-       }
-
-       *num = ch_inf_res->subbuf_num;
-       *size = ch_inf_res->subbuf_size;
-
-       free(ch_inf_res);
-
-       return 0;
-}
-
-/**
- * Get subbuffer num.
- *
- * @param channel      Channel name
- * @param pid          Traced process ID
- * @return             subbuf cnf if successful, or error
- */
-int ustcmd_get_subbuf_num(const char *trace, const char *channel, pid_t pid)
-{
-       int num, size, result;
-
-       result = ustcmd_get_subbuf_num_size(trace, channel, pid,
-                                           &num, &size);
-       if (result < 0) {
-               errno = -result;
-               return -1;
-       }
-
-       return num;
-}
-
-/**
- * Get subbuffer size.
- *
- * @param channel      Channel name
- * @param pid          Traced process ID
- * @return             subbuf size if successful, or error
- */
-int ustcmd_get_subbuf_size(const char *trace, const char *channel, pid_t pid)
-{
-       int num, size, result;
-
-       result = ustcmd_get_subbuf_num_size(trace, channel, pid,
-                                           &num, &size);
-       if (result < 0) {
-               errno = -result;
-               return -1;
-       }
-
-       return size;
-}
-
-
-static int do_trace_cmd(const char *trace, pid_t pid, int command)
-{
-       struct ustcomm_header req_header, res_header;
-       struct ustcomm_single_field trace_inf;
-       int result;
-
-       result = ustcomm_pack_single_field(&req_header,
-                                          &trace_inf,
-                                          trace);
-       if (result < 0) {
-               errno = -result;
-               return -1;
-       }
-
-       req_header.command = command;
-
-       return do_cmd(pid, &req_header, (char *)&trace_inf, &res_header, NULL);
-}
-
-/**
- * Destroys an UST trace according to a PID.
- *
- * @param pid  Traced process ID
- * @return     0 if successful, or error USTCMD_ERR_GEN
- */
-int ustcmd_destroy_trace(const char *trace, pid_t pid)
-{
-       return do_trace_cmd(trace, pid, DESTROY_TRACE);
-}
-
-/**
- * Starts an UST trace (and setups it) according to a PID.
- *
- * @param pid  Traced process ID
- * @return     0 if successful, or error USTCMD_ERR_GEN
- */
-int ustcmd_setup_and_start(const char *trace, pid_t pid)
-{
-       return do_trace_cmd(trace, pid, START);
-}
-
-/**
- * Creates an UST trace according to a PID.
- *
- * @param pid  Traced process ID
- * @return     0 if successful, or error USTCMD_ERR_GEN
- */
-int ustcmd_create_trace(const char *trace, pid_t pid)
-{
-       return do_trace_cmd(trace, pid, CREATE_TRACE);
-}
-
-/**
- * Starts an UST trace according to a PID.
- *
- * @param pid  Traced process ID
- * @return     0 if successful, or error USTCMD_ERR_GEN
- */
-int ustcmd_start_trace(const char *trace, pid_t pid)
-{
-       return do_trace_cmd(trace, pid, START_TRACE);
-}
-
-/**
- * Alloc an UST trace according to a PID.
- *
- * @param pid  Traced process ID
- * @return     0 if successful, or error USTCMD_ERR_GEN
- */
-int ustcmd_alloc_trace(const char *trace, pid_t pid)
-{
-       return do_trace_cmd(trace, pid, ALLOC_TRACE);
-}
-
-/**
- * Stops an UST trace according to a PID.
- *
- * @param pid  Traced process ID
- * @return     0 if successful, or error USTCMD_ERR_GEN
- */
-int ustcmd_stop_trace(const char *trace, pid_t pid)
-{
-       return do_trace_cmd(trace, pid, STOP_TRACE);
-}
-
-/**
- * Counts newlines ('\n') in a string.
- *
- * @param str  String to search in
- * @return     Total newlines count
- */
-unsigned int ustcmd_count_nl(const char *str)
-{
-       unsigned int i = 0, tot = 0;
-
-       while (str[i] != '\0') {
-               if (str[i] == '\n') {
-                       ++tot;
-               }
-               ++i;
-       }
-
-       return tot;
-}
-
-/**
- * Frees a CMSF array.
- *
- * @param cmsf CMSF array to free
- * @return     0 if successful, or error USTCMD_ERR_ARG
- */
-int ustcmd_free_cmsf(struct marker_status *cmsf)
-{
-       if (cmsf == NULL) {
-               return USTCMD_ERR_ARG;
-       }
-
-       unsigned int i = 0;
-       while (cmsf[i].channel != NULL) {
-               free(cmsf[i].channel);
-               free(cmsf[i].marker);
-               free(cmsf[i].fs);
-               ++i;
-       }
-       free(cmsf);
-
-       return 0;
-}
-
-/**
- * Gets channel/marker/state/format string for a given PID.
- *
- * @param cmsf Pointer to CMSF array to be filled (callee allocates, caller
- *             frees with `ustcmd_free_cmsf')
- * @param pid  Targeted PID
- * @return     0 if successful, or -1 on error
- */
-int ustcmd_get_cmsf(struct marker_status **cmsf, const pid_t pid)
-{
-       struct ustcomm_header req_header, res_header;
-       char *big_str = NULL;
-       int result, app_fd;
-       struct marker_status *tmp_cmsf = NULL;
-       unsigned int i = 0, cmsf_ind = 0;
-
-       if (cmsf == NULL) {
-               return -1;
-       }
-
-       if (ustcomm_connect_app(pid, &app_fd)) {
-               ERR("could not connect to PID %u", (unsigned int) pid);
-               return -1;
-       }
-
-       req_header.command = LIST_MARKERS;
-       req_header.size = 0;
-
-       result = ustcomm_send(app_fd, &req_header, NULL);
-       if (result <= 0) {
-               PERROR("error while requesting markers list for process %d", pid);
-               return -1;
-       }
-
-       result = ustcomm_recv_alloc(app_fd, &res_header, &big_str);
-       if (result <= 0) {
-               ERR("error while receiving markers list");
-               return -1;
-       }
-
-       close(app_fd);
-
-       tmp_cmsf = (struct marker_status *) zmalloc(sizeof(struct marker_status) *
-                                                   (ustcmd_count_nl(big_str) + 1));
-       if (tmp_cmsf == NULL) {
-               ERR("Failed to allocate CMSF array");
-               return -1;
-       }
-
-       /* Parse received reply string (format: "[chan]/[mark] [st] [fs]"): */
-       while (big_str[i] != '\0') {
-               char state;
-
-               sscanf(big_str + i, "marker: %a[^/]/%a[^ ] %c %a[^\n]",
-                      &tmp_cmsf[cmsf_ind].channel,
-                      &tmp_cmsf[cmsf_ind].marker,
-                      &state,
-                      &tmp_cmsf[cmsf_ind].fs);
-               tmp_cmsf[cmsf_ind].state = (state == USTCMD_MS_CHR_ON ?
-                                           USTCMD_MS_ON : USTCMD_MS_OFF); /* Marker state */
-
-               while (big_str[i] != '\n') {
-                       ++i; /* Go to next '\n' */
-               }
-               ++i; /* Skip current pointed '\n' */
-               ++cmsf_ind;
-       }
-       tmp_cmsf[cmsf_ind].channel = NULL;
-       tmp_cmsf[cmsf_ind].marker = NULL;
-       tmp_cmsf[cmsf_ind].fs = NULL;
-
-       *cmsf = tmp_cmsf;
-
-       free(big_str);
-       return 0;
-}
-
-
-/**
- * Frees a TES array.
- *
- * @param tes  TES array to free
- * @return     0 if successful, or error USTCMD_ERR_ARG
- */
-int ustcmd_free_tes(struct trace_event_status *tes)
-{
-       if (tes == NULL) {
-               return USTCMD_ERR_ARG;
-       }
-
-       unsigned int i = 0;
-       while (tes[i].name != NULL) {
-               free(tes[i].name);
-               ++i;
-       }
-       free(tes);
-
-       return 0;
-}
-
-/**
- * Gets trace_events string for a given PID.
- *
- * @param tes  Pointer to TES array to be filled (callee allocates, caller
- *             frees with `ustcmd_free_tes')
- * @param pid  Targeted PID
- * @return     0 if successful, or -1 on error
- */
-int ustcmd_get_tes(struct trace_event_status **tes,
-                  const pid_t pid)
-{
-       struct ustcomm_header req_header, res_header;
-       char *big_str = NULL;
-       int result, app_fd;
-       struct trace_event_status *tmp_tes = NULL;
-       unsigned int i = 0, tes_ind = 0;
-
-       if (tes == NULL) {
-               return -1;
-       }
-
-       if (ustcomm_connect_app(pid, &app_fd)) {
-               ERR("could not connect to PID %u", (unsigned int) pid);
-               return -1;
-       }
-
-       req_header.command = LIST_TRACE_EVENTS;
-       req_header.size = 0;
-
-       result = ustcomm_send(app_fd, &req_header, NULL);
-       if (result != 1) {
-               ERR("error while requesting trace_event list");
-               return -1;
-       }
-
-       result = ustcomm_recv_alloc(app_fd, &res_header, &big_str);
-       if (result != 1) {
-               ERR("error while receiving markers list");
-               return -1;
-       }
-
-       close(app_fd);
-
-       tmp_tes = (struct trace_event_status *)
-               zmalloc(sizeof(struct trace_event_status) *
-                       (ustcmd_count_nl(big_str) + 1));
-       if (tmp_tes == NULL) {
-               ERR("Failed to allocate TES array");
-               return -1;
-       }
-
-       /* Parse received reply string (format: "[name]"): */
-       while (big_str[i] != '\0') {
-               sscanf(big_str + i, "trace_event: %a[^\n]",
-                      &tmp_tes[tes_ind].name);
-               while (big_str[i] != '\n') {
-                       ++i; /* Go to next '\n' */
-               }
-               ++i; /* Skip current pointed '\n' */
-               ++tes_ind;
-       }
-       tmp_tes[tes_ind].name = NULL;
-
-       *tes = tmp_tes;
-
-       free(big_str);
-       return 0;
-}
-
-/**
- * Set socket path
- *
- * @param sock_path    Socket path
- * @param pid          Traced process ID
- * @return             0 if successful, or error
- */
-int ustcmd_set_sock_path(const char *sock_path, pid_t pid)
-{
-       int result;
-       struct ustcomm_header req_header, res_header;
-       struct ustcomm_single_field sock_path_msg;
-
-       result = ustcomm_pack_single_field(&req_header,
-                                          &sock_path_msg,
-                                          sock_path);
-       if (result < 0) {
-               errno = -result;
-               return -1;
-       }
-
-       req_header.command = SET_SOCK_PATH;
-
-       return do_cmd(pid, &req_header, (char *)&sock_path_msg,
-                     &res_header, NULL);
-}
-
-/**
- * Get socket path
- *
- * @param sock_path    Pointer to where the socket path will be returned
- * @param pid          Traced process ID
- * @return             0 if successful, or error
- */
-int ustcmd_get_sock_path(char **sock_path, pid_t pid)
-{
-       int result;
-       struct ustcomm_header req_header, res_header;
-       struct ustcomm_single_field *sock_path_msg;
-
-       req_header.command = GET_SOCK_PATH;
-       req_header.size = 0;
-
-       result = do_cmd(pid, &req_header, NULL, &res_header,
-                       (char **)&sock_path_msg);
-       if (result < 0) {
-               return -1;
-       }
-
-       result = ustcomm_unpack_single_field(sock_path_msg);
-       if (result < 0) {
-               return result;
-       }
-
-       *sock_path = strdup(sock_path_msg->field);
-
-       free(sock_path_msg);
-
-       return 0;
-}
-
-int ustcmd_force_switch(pid_t pid)
-{
-       struct ustcomm_header req_header, res_header;
-
-       req_header.command = FORCE_SUBBUF_SWITCH;
-       req_header.size = 0;
-
-       return do_cmd(pid, &req_header, NULL, &res_header, NULL);
-}
-
diff --git a/libustctl/Makefile.am b/libustctl/Makefile.am
new file mode 100644 (file)
index 0000000..bc7526b
--- /dev/null
@@ -0,0 +1,14 @@
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/libustcomm
+AM_CFLAGS = -fno-strict-aliasing
+
+lib_LTLIBRARIES = libustctl.la
+
+libustctl_la_SOURCES = \
+       libustctl.c
+
+libustctl_la_LDFLAGS = -no-undefined -version-info 0:0:0
+
+libustctl_la_LIBADD = \
+       $(top_builddir)/libustcomm/libustcomm.la
+
+libustctl_la_CFLAGS = -DUST_COMPONENT="libustctl" -fno-strict-aliasing
diff --git a/libustctl/README b/libustctl/README
new file mode 100644 (file)
index 0000000..fd4cc97
--- /dev/null
@@ -0,0 +1,2 @@
+libustctl is a library that provides an API and its implementation to send
+commands to traceable processes.
diff --git a/libustctl/libustctl.c b/libustctl/libustctl.c
new file mode 100644 (file)
index 0000000..9c4ced2
--- /dev/null
@@ -0,0 +1,671 @@
+/* Copyright (C) 2009  Pierre-Marc Fournier, Philippe Proulx-Barrette
+ *
+ * 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
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <dirent.h>
+
+#include "ustcomm.h"
+#include "ust/ustctl.h"
+#include "usterr.h"
+
+static int do_cmd(const pid_t pid,
+                 const struct ustcomm_header *req_header,
+                 const char *req_data,
+                 struct ustcomm_header *res_header,
+                 char **res_data)
+{
+       int app_fd, result, saved_errno = 0;
+       char *recv_buf;
+
+       if (ustcomm_connect_app(pid, &app_fd)) {
+               ERR("could not connect to PID %u", (unsigned int) pid);
+               errno = ENOTCONN;
+               return -1;
+       }
+
+       recv_buf = zmalloc(USTCOMM_BUFFER_SIZE);
+       if (!recv_buf) {
+               saved_errno = ENOMEM;
+               goto close_app_fd;
+       }
+
+       result = ustcomm_req(app_fd, req_header, req_data, res_header, recv_buf);
+       if (result > 0) {
+               saved_errno = -res_header->result;
+               if (res_header->size == 0 || saved_errno > 0) {
+                       free(recv_buf);
+               } else {
+                       if (res_data) {
+                               *res_data = recv_buf;
+                       } else {
+                               free(recv_buf);
+                       }
+               }
+       } else {
+               ERR("ustcomm req failed");
+               if (result == 0) {
+                       saved_errno = ENOTCONN;
+               } else {
+                       saved_errno = -result;
+               }
+               free(recv_buf);
+       }
+
+close_app_fd:
+       close(app_fd);
+
+       errno = saved_errno;
+
+       if (errno) {
+               return -1;
+       }
+
+       return 0;
+}
+
+pid_t *ustctl_get_online_pids(void)
+{
+       struct dirent *dirent;
+       DIR *dir;
+       unsigned int ret_size = 1 * sizeof(pid_t), i = 0;
+
+       dir = opendir(SOCK_DIR);
+       if (!dir) {
+               return NULL;
+       }
+
+       pid_t *ret = (pid_t *) malloc(ret_size);
+
+       while ((dirent = readdir(dir))) {
+               if (!strcmp(dirent->d_name, ".") ||
+                   !strcmp(dirent->d_name, "..")) {
+
+                       continue;
+               }
+
+               if (dirent->d_type != DT_DIR &&
+                   !!strcmp(dirent->d_name, "ust-consumer")) {
+
+                       sscanf(dirent->d_name, "%u", (unsigned int *) &ret[i]);
+                       /* FIXME: Here we previously called pid_is_online, which
+                        * always returned 1, now I replaced it with just 1.
+                        * We need to figure out an intelligent way of solving
+                        * this, maybe connect-disconnect.
+                        */
+                       if (1) {
+                               ret_size += sizeof(pid_t);
+                               ret = (pid_t *) realloc(ret, ret_size);
+                               ++i;
+                       }
+               }
+       }
+
+       ret[i] = 0; /* Array end */
+
+       if (ret[0] == 0) {
+               /* No PID at all */
+               free(ret);
+               return NULL;
+       }
+
+       closedir(dir);
+       return ret;
+}
+
+/**
+ * Sets marker state (USTCTL_MS_ON or USTCTL_MS_OFF).
+ *
+ * @param mn   Marker name
+ * @param state        Marker's new state
+ * @param pid  Traced process ID
+ * @return     0 if successful, or errors {USTCTL_ERR_GEN, USTCTL_ERR_ARG}
+ */
+int ustctl_set_marker_state(const char *trace, const char *channel,
+                           const char *marker, int state, pid_t pid)
+{
+       struct ustcomm_header req_header, res_header;
+       struct ustcomm_marker_info marker_inf;
+       int result;
+
+       result = ustcomm_pack_marker_info(&req_header,
+                                         &marker_inf,
+                                         trace,
+                                         channel,
+                                         marker);
+       if (result < 0) {
+               errno = -result;
+               return -1;
+       }
+
+       req_header.command = state ? ENABLE_MARKER : DISABLE_MARKER;
+
+       return do_cmd(pid, &req_header, (char *)&marker_inf,
+                     &res_header, NULL);
+}
+
+/**
+ * Set subbuffer size.
+ *
+ * @param channel_size Channel name and size
+ * @param pid          Traced process ID
+ * @return             0 if successful, or error
+ */
+int ustctl_set_subbuf_size(const char *trace, const char *channel,
+                          unsigned int subbuf_size, pid_t pid)
+{
+       struct ustcomm_header req_header, res_header;
+       struct ustcomm_channel_info ch_inf;
+       int result;
+
+       result = ustcomm_pack_channel_info(&req_header,
+                                          &ch_inf,
+                                          trace,
+                                          channel);
+       if (result < 0) {
+               errno = -result;
+               return -1;
+       }
+
+       req_header.command = SET_SUBBUF_SIZE;
+       ch_inf.subbuf_size = subbuf_size;
+
+       return do_cmd(pid, &req_header, (char *)&ch_inf,
+                     &res_header, NULL);
+}
+
+/**
+ * Set subbuffer num.
+ *
+ * @param channel_num  Channel name and num
+ * @param pid          Traced process ID
+ * @return             0 if successful, or error
+ */
+int ustctl_set_subbuf_num(const char *trace, const char *channel,
+                         unsigned int num, pid_t pid)
+{
+       struct ustcomm_header req_header, res_header;
+       struct ustcomm_channel_info ch_inf;
+       int result;
+
+       result = ustcomm_pack_channel_info(&req_header,
+                                          &ch_inf,
+                                          trace,
+                                          channel);
+       if (result < 0) {
+               errno = -result;
+               return -1;
+       }
+
+       req_header.command = SET_SUBBUF_NUM;
+       ch_inf.subbuf_num = num;
+
+       return do_cmd(pid, &req_header, (char *)&ch_inf,
+                     &res_header, NULL);
+
+}
+
+static int ustctl_get_subbuf_num_size(const char *trace, const char *channel,
+                                     pid_t pid, int *num, int *size)
+{
+       struct ustcomm_header req_header, res_header;
+       struct ustcomm_channel_info ch_inf, *ch_inf_res;
+       int result;
+
+
+       result = ustcomm_pack_channel_info(&req_header,
+                                          &ch_inf,
+                                          trace,
+                                          channel);
+       if (result < 0) {
+               errno = -result;
+               return -1;
+       }
+
+       req_header.command = GET_SUBBUF_NUM_SIZE;
+
+       result = do_cmd(pid, &req_header, (char *)&ch_inf,
+                       &res_header, (char **)&ch_inf_res);
+       if (result < 0) {
+               return -1;
+       }
+
+       *num = ch_inf_res->subbuf_num;
+       *size = ch_inf_res->subbuf_size;
+
+       free(ch_inf_res);
+
+       return 0;
+}
+
+/**
+ * Get subbuffer num.
+ *
+ * @param channel      Channel name
+ * @param pid          Traced process ID
+ * @return             subbuf cnf if successful, or error
+ */
+int ustctl_get_subbuf_num(const char *trace, const char *channel, pid_t pid)
+{
+       int num, size, result;
+
+       result = ustctl_get_subbuf_num_size(trace, channel, pid,
+                                           &num, &size);
+       if (result < 0) {
+               errno = -result;
+               return -1;
+       }
+
+       return num;
+}
+
+/**
+ * Get subbuffer size.
+ *
+ * @param channel      Channel name
+ * @param pid          Traced process ID
+ * @return             subbuf size if successful, or error
+ */
+int ustctl_get_subbuf_size(const char *trace, const char *channel, pid_t pid)
+{
+       int num, size, result;
+
+       result = ustctl_get_subbuf_num_size(trace, channel, pid,
+                                           &num, &size);
+       if (result < 0) {
+               errno = -result;
+               return -1;
+       }
+
+       return size;
+}
+
+
+static int do_trace_cmd(const char *trace, pid_t pid, int command)
+{
+       struct ustcomm_header req_header, res_header;
+       struct ustcomm_single_field trace_inf;
+       int result;
+
+       result = ustcomm_pack_single_field(&req_header,
+                                          &trace_inf,
+                                          trace);
+       if (result < 0) {
+               errno = -result;
+               return -1;
+       }
+
+       req_header.command = command;
+
+       return do_cmd(pid, &req_header, (char *)&trace_inf, &res_header, NULL);
+}
+
+/**
+ * Destroys an UST trace according to a PID.
+ *
+ * @param pid  Traced process ID
+ * @return     0 if successful, or error USTCTL_ERR_GEN
+ */
+int ustctl_destroy_trace(const char *trace, pid_t pid)
+{
+       return do_trace_cmd(trace, pid, DESTROY_TRACE);
+}
+
+/**
+ * Starts an UST trace (and setups it) according to a PID.
+ *
+ * @param pid  Traced process ID
+ * @return     0 if successful, or error USTCTL_ERR_GEN
+ */
+int ustctl_setup_and_start(const char *trace, pid_t pid)
+{
+       return do_trace_cmd(trace, pid, START);
+}
+
+/**
+ * Creates an UST trace according to a PID.
+ *
+ * @param pid  Traced process ID
+ * @return     0 if successful, or error USTCTL_ERR_GEN
+ */
+int ustctl_create_trace(const char *trace, pid_t pid)
+{
+       return do_trace_cmd(trace, pid, CREATE_TRACE);
+}
+
+/**
+ * Starts an UST trace according to a PID.
+ *
+ * @param pid  Traced process ID
+ * @return     0 if successful, or error USTCTL_ERR_GEN
+ */
+int ustctl_start_trace(const char *trace, pid_t pid)
+{
+       return do_trace_cmd(trace, pid, START_TRACE);
+}
+
+/**
+ * Alloc an UST trace according to a PID.
+ *
+ * @param pid  Traced process ID
+ * @return     0 if successful, or error USTCTL_ERR_GEN
+ */
+int ustctl_alloc_trace(const char *trace, pid_t pid)
+{
+       return do_trace_cmd(trace, pid, ALLOC_TRACE);
+}
+
+/**
+ * Stops an UST trace according to a PID.
+ *
+ * @param pid  Traced process ID
+ * @return     0 if successful, or error USTCTL_ERR_GEN
+ */
+int ustctl_stop_trace(const char *trace, pid_t pid)
+{
+       return do_trace_cmd(trace, pid, STOP_TRACE);
+}
+
+/**
+ * Counts newlines ('\n') in a string.
+ *
+ * @param str  String to search in
+ * @return     Total newlines count
+ */
+unsigned int ustctl_count_nl(const char *str)
+{
+       unsigned int i = 0, tot = 0;
+
+       while (str[i] != '\0') {
+               if (str[i] == '\n') {
+                       ++tot;
+               }
+               ++i;
+       }
+
+       return tot;
+}
+
+/**
+ * Frees a CMSF array.
+ *
+ * @param cmsf CMSF array to free
+ * @return     0 if successful, or error USTCTL_ERR_ARG
+ */
+int ustctl_free_cmsf(struct marker_status *cmsf)
+{
+       if (cmsf == NULL) {
+               return USTCTL_ERR_ARG;
+       }
+
+       unsigned int i = 0;
+       while (cmsf[i].channel != NULL) {
+               free(cmsf[i].channel);
+               free(cmsf[i].marker);
+               free(cmsf[i].fs);
+               ++i;
+       }
+       free(cmsf);
+
+       return 0;
+}
+
+/**
+ * Gets channel/marker/state/format string for a given PID.
+ *
+ * @param cmsf Pointer to CMSF array to be filled (callee allocates, caller
+ *             frees with `ustctl_free_cmsf')
+ * @param pid  Targeted PID
+ * @return     0 if successful, or -1 on error
+ */
+int ustctl_get_cmsf(struct marker_status **cmsf, const pid_t pid)
+{
+       struct ustcomm_header req_header, res_header;
+       char *big_str = NULL;
+       int result, app_fd;
+       struct marker_status *tmp_cmsf = NULL;
+       unsigned int i = 0, cmsf_ind = 0;
+
+       if (cmsf == NULL) {
+               return -1;
+       }
+
+       if (ustcomm_connect_app(pid, &app_fd)) {
+               ERR("could not connect to PID %u", (unsigned int) pid);
+               return -1;
+       }
+
+       req_header.command = LIST_MARKERS;
+       req_header.size = 0;
+
+       result = ustcomm_send(app_fd, &req_header, NULL);
+       if (result <= 0) {
+               PERROR("error while requesting markers list for process %d", pid);
+               return -1;
+       }
+
+       result = ustcomm_recv_alloc(app_fd, &res_header, &big_str);
+       if (result <= 0) {
+               ERR("error while receiving markers list");
+               return -1;
+       }
+
+       close(app_fd);
+
+       tmp_cmsf = (struct marker_status *) zmalloc(sizeof(struct marker_status) *
+                                                   (ustctl_count_nl(big_str) + 1));
+       if (tmp_cmsf == NULL) {
+               ERR("Failed to allocate CMSF array");
+               return -1;
+       }
+
+       /* Parse received reply string (format: "[chan]/[mark] [st] [fs]"): */
+       while (big_str[i] != '\0') {
+               char state;
+
+               sscanf(big_str + i, "marker: %a[^/]/%a[^ ] %c %a[^\n]",
+                      &tmp_cmsf[cmsf_ind].channel,
+                      &tmp_cmsf[cmsf_ind].marker,
+                      &state,
+                      &tmp_cmsf[cmsf_ind].fs);
+               tmp_cmsf[cmsf_ind].state = (state == USTCTL_MS_CHR_ON ?
+                                           USTCTL_MS_ON : USTCTL_MS_OFF); /* Marker state */
+
+               while (big_str[i] != '\n') {
+                       ++i; /* Go to next '\n' */
+               }
+               ++i; /* Skip current pointed '\n' */
+               ++cmsf_ind;
+       }
+       tmp_cmsf[cmsf_ind].channel = NULL;
+       tmp_cmsf[cmsf_ind].marker = NULL;
+       tmp_cmsf[cmsf_ind].fs = NULL;
+
+       *cmsf = tmp_cmsf;
+
+       free(big_str);
+       return 0;
+}
+
+
+/**
+ * Frees a TES array.
+ *
+ * @param tes  TES array to free
+ * @return     0 if successful, or error USTCTL_ERR_ARG
+ */
+int ustctl_free_tes(struct trace_event_status *tes)
+{
+       if (tes == NULL) {
+               return USTCTL_ERR_ARG;
+       }
+
+       unsigned int i = 0;
+       while (tes[i].name != NULL) {
+               free(tes[i].name);
+               ++i;
+       }
+       free(tes);
+
+       return 0;
+}
+
+/**
+ * Gets trace_events string for a given PID.
+ *
+ * @param tes  Pointer to TES array to be filled (callee allocates, caller
+ *             frees with `ustctl_free_tes')
+ * @param pid  Targeted PID
+ * @return     0 if successful, or -1 on error
+ */
+int ustctl_get_tes(struct trace_event_status **tes,
+                  const pid_t pid)
+{
+       struct ustcomm_header req_header, res_header;
+       char *big_str = NULL;
+       int result, app_fd;
+       struct trace_event_status *tmp_tes = NULL;
+       unsigned int i = 0, tes_ind = 0;
+
+       if (tes == NULL) {
+               return -1;
+       }
+
+       if (ustcomm_connect_app(pid, &app_fd)) {
+               ERR("could not connect to PID %u", (unsigned int) pid);
+               return -1;
+       }
+
+       req_header.command = LIST_TRACE_EVENTS;
+       req_header.size = 0;
+
+       result = ustcomm_send(app_fd, &req_header, NULL);
+       if (result != 1) {
+               ERR("error while requesting trace_event list");
+               return -1;
+       }
+
+       result = ustcomm_recv_alloc(app_fd, &res_header, &big_str);
+       if (result != 1) {
+               ERR("error while receiving markers list");
+               return -1;
+       }
+
+       close(app_fd);
+
+       tmp_tes = (struct trace_event_status *)
+               zmalloc(sizeof(struct trace_event_status) *
+                       (ustctl_count_nl(big_str) + 1));
+       if (tmp_tes == NULL) {
+               ERR("Failed to allocate TES array");
+               return -1;
+       }
+
+       /* Parse received reply string (format: "[name]"): */
+       while (big_str[i] != '\0') {
+               sscanf(big_str + i, "trace_event: %a[^\n]",
+                      &tmp_tes[tes_ind].name);
+               while (big_str[i] != '\n') {
+                       ++i; /* Go to next '\n' */
+               }
+               ++i; /* Skip current pointed '\n' */
+               ++tes_ind;
+       }
+       tmp_tes[tes_ind].name = NULL;
+
+       *tes = tmp_tes;
+
+       free(big_str);
+       return 0;
+}
+
+/**
+ * Set socket path
+ *
+ * @param sock_path    Socket path
+ * @param pid          Traced process ID
+ * @return             0 if successful, or error
+ */
+int ustctl_set_sock_path(const char *sock_path, pid_t pid)
+{
+       int result;
+       struct ustcomm_header req_header, res_header;
+       struct ustcomm_single_field sock_path_msg;
+
+       result = ustcomm_pack_single_field(&req_header,
+                                          &sock_path_msg,
+                                          sock_path);
+       if (result < 0) {
+               errno = -result;
+               return -1;
+       }
+
+       req_header.command = SET_SOCK_PATH;
+
+       return do_cmd(pid, &req_header, (char *)&sock_path_msg,
+                     &res_header, NULL);
+}
+
+/**
+ * Get socket path
+ *
+ * @param sock_path    Pointer to where the socket path will be returned
+ * @param pid          Traced process ID
+ * @return             0 if successful, or error
+ */
+int ustctl_get_sock_path(char **sock_path, pid_t pid)
+{
+       int result;
+       struct ustcomm_header req_header, res_header;
+       struct ustcomm_single_field *sock_path_msg;
+
+       req_header.command = GET_SOCK_PATH;
+       req_header.size = 0;
+
+       result = do_cmd(pid, &req_header, NULL, &res_header,
+                       (char **)&sock_path_msg);
+       if (result < 0) {
+               return -1;
+       }
+
+       result = ustcomm_unpack_single_field(sock_path_msg);
+       if (result < 0) {
+               return result;
+       }
+
+       *sock_path = strdup(sock_path_msg->field);
+
+       free(sock_path_msg);
+
+       return 0;
+}
+
+int ustctl_force_switch(pid_t pid)
+{
+       struct ustcomm_header req_header, res_header;
+
+       req_header.command = FORCE_SUBBUF_SWITCH;
+       req_header.size = 0;
+
+       return do_cmd(pid, &req_header, NULL, &res_header, NULL);
+}
+
index 526f81c789964bf545bd1e91d89dddac3e9ad498..e4e06cebb8fd985aa41aa98e86a95409e8205c42 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = . hello hello2 basic basic_long fork simple_include snprintf test-nevents test-libustinstr-malloc dlopen same_line_marker trace_event register_test tracepoint ustcmd_function_tests
+SUBDIRS = . hello hello2 basic basic_long fork simple_include snprintf test-nevents test-libustinstr-malloc dlopen same_line_marker trace_event register_test tracepoint libustctl_function_tests
 
 dist_noinst_SCRIPTS = test_loop runtests trace_matches
 
diff --git a/tests/libustctl_function_tests/Makefile.am b/tests/libustctl_function_tests/Makefile.am
new file mode 100644 (file)
index 0000000..723b456
--- /dev/null
@@ -0,0 +1,10 @@
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/tests/
+
+noinst_PROGRAMS = libustctl_function_tests
+libustctl_function_tests_SOURCES = libustctl_function_tests.c
+libustctl_function_tests_LDADD = $(top_builddir)/libust/libust.la \
+       $(top_builddir)/libustctl/libustctl.la \
+       $(top_builddir)/libust-initializer.o \
+       $(top_builddir)/tests/libtap.la \
+       -lpthread
+
diff --git a/tests/libustctl_function_tests/libustctl_function_tests.c b/tests/libustctl_function_tests/libustctl_function_tests.c
new file mode 100644 (file)
index 0000000..784ff5d
--- /dev/null
@@ -0,0 +1,184 @@
+/* Copyright (C) 2010 Nils Carlson
+ *
+ * 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
+ */
+
+/* Simple function tests for ustctl */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <ust/marker.h>
+#include <ust/ustctl.h>
+
+#include "tap.h"
+
+static void ustctl_function_tests(pid_t pid)
+{
+       int result;
+       unsigned int subbuf_size, subbuf_num;
+       unsigned int new_subbuf_size, new_subbuf_num;
+       struct marker_status *marker_status, *ms_ptr;
+       char *old_socket_path, *new_socket_path;
+       char *tmp_ustd_socket = "/tmp/tmp_ustd_socket";
+       char *trace = "auto";
+
+       printf("Connecting to pid %d\n", pid);
+
+       /* marker status array functions */
+       result = ustctl_get_cmsf(&marker_status, pid);
+       tap_ok(!result, "ustctl_get_cmsf");
+
+       result = 0;
+       for (ms_ptr = marker_status; ms_ptr->channel; ms_ptr++) {
+               if (!strcmp(ms_ptr->channel, "ust") &&
+                   !strcmp(ms_ptr->marker, "bar")) {
+                       result = 1;
+               }
+       }
+       tap_ok(result, "Found channel \"ust\", marker \"bar\"");
+
+       tap_ok(!ustctl_free_cmsf(marker_status), "ustctl_free_cmsf");
+
+       /* Get and set the socket path */
+       tap_ok(!ustctl_get_sock_path(&old_socket_path, pid),
+              "ustctl_get_sock_path");
+
+       printf("Socket path: %s\n", old_socket_path);
+
+       tap_ok(!ustctl_set_sock_path(tmp_ustd_socket, pid),
+              "ustctl_set_sock_path - set a new path");
+
+       tap_ok(!ustctl_get_sock_path(&new_socket_path, pid),
+              "ustctl_get_sock_path - get the new path");
+
+       tap_ok(!strcmp(new_socket_path, tmp_ustd_socket),
+              "Compare the set path and the retrieved path");
+
+       free(new_socket_path);
+
+       tap_ok(!ustctl_set_sock_path(old_socket_path, pid),
+              "Reset the socket path");
+
+       free(old_socket_path);
+
+       /* Enable, disable markers */
+       tap_ok(!ustctl_set_marker_state(trace, "ust", "bar", 1, pid),
+              "ustctl_set_marker_state - existing marker ust bar");
+
+       /* Create and allocate a trace */
+       tap_ok(!ustctl_create_trace(trace, pid), "ustctl_create_trace");
+
+       tap_ok(!ustctl_alloc_trace(trace, pid), "ustctl_alloc_trace");
+
+       /* Get subbuf size and number */
+       subbuf_num = ustctl_get_subbuf_num(trace, "ust", pid);
+       tap_ok(subbuf_num > 0, "ustctl_get_subbuf_num - %d sub-buffers",
+              subbuf_num);
+
+       subbuf_size = ustctl_get_subbuf_size(trace, "ust", pid);
+       tap_ok(subbuf_size, "ustctl_get_subbuf_size - sub-buffer size is %d",
+              subbuf_size);
+
+       /* Start the trace */
+       tap_ok(!ustctl_start_trace(trace, pid), "ustctl_start_trace");
+
+
+       /* Stop the trace and destroy it*/
+       tap_ok(!ustctl_stop_trace(trace, pid), "ustctl_stop_trace");
+
+       tap_ok(!ustctl_destroy_trace(trace, pid), "ustctl_destroy_trace");
+
+       /* Create a new trace */
+       tap_ok(!ustctl_create_trace(trace, pid), "ustctl_create_trace - create a new trace");
+
+       printf("Setting new subbufer number and sizes (doubling)\n");
+       new_subbuf_num = 2 * subbuf_num;
+       new_subbuf_size = 2 * subbuf_size;
+
+       tap_ok(!ustctl_set_subbuf_num(trace, "ust", new_subbuf_num, pid),
+              "ustctl_set_subbuf_num");
+
+       tap_ok(!ustctl_set_subbuf_size(trace, "ust", new_subbuf_size, pid),
+              "ustctl_set_subbuf_size");
+
+
+       /* Allocate the new trace */
+       tap_ok(!ustctl_alloc_trace(trace, pid), "ustctl_alloc_trace - allocate the new trace");
+
+
+        /* Get subbuf size and number and compare with what was set */
+       subbuf_num = ustctl_get_subbuf_num(trace, "ust", pid);
+
+       subbuf_size = ustctl_get_subbuf_size(trace, "ust", pid);
+
+       tap_ok(subbuf_num == new_subbuf_num, "Set a new subbuf number, %d == %d",
+              subbuf_num, new_subbuf_num);
+
+
+       result = ustctl_get_subbuf_size(trace, "ust", pid);
+       tap_ok(subbuf_size == new_subbuf_size, "Set a new subbuf size, %d == %d",
+              subbuf_size, new_subbuf_size);
+
+       tap_ok(!ustctl_destroy_trace(trace, pid), "ustctl_destroy_trace - without ever starting");
+
+
+       printf("##### Tests that definetly should work are completed #####\n");
+       printf("############## Start expected failure cases ##############\n");
+
+       tap_ok(ustctl_set_marker_state(trace, "ust","bar", 1, pid),
+              "Enable already enabled marker ust/bar");
+
+       tap_ok(ustctl_set_marker_state(trace, "ustl", "blar", 1, pid),
+              "Enable non-existent marker ustl blar");
+
+       tap_ok(ustctl_start_trace(trace, pid),
+              "Start a non-existent trace");
+
+       tap_ok(ustctl_destroy_trace(trace, pid),
+              "Destroy non-existent trace");
+
+       exit(tap_status() ? EXIT_FAILURE : EXIT_SUCCESS);
+
+}
+
+
+int main()
+{
+       int i, status, pipefd[2];
+       pid_t parent_pid, child_pid;
+       FILE *pipe_file;
+
+       tap_plan(27);
+
+       printf("Function tests for ustctl\n");
+
+       parent_pid = getpid();
+       child_pid = fork();
+       if (child_pid) {
+               for(i=0; i<10; i++) {
+                       trace_mark(ust, bar, "str %s", "FOOBAZ");
+                       trace_mark(ust, bar2, "number1 %d number2 %d", 53, 9800);
+                       usleep(100000);
+               }
+
+               wait(&status);
+       } else {
+               ustctl_function_tests(parent_pid);
+       }
+
+       exit(status ? EXIT_FAILURE : EXIT_SUCCESS);
+}
index b0df338ea51fa759b9ec80d46bfd963bf9853eef..b60a957084c458fd3e98822dc2a778c92c5a6f41 100755 (executable)
@@ -42,17 +42,18 @@ UST_CONSUMERD_PID="$(<$pidfilepath)"
 
 LD_PRELOAD=/usr/local/lib/libust.so.0.0.0:/usr/local/lib/libustinstr-malloc.so find -L / >/dev/null 2>&1 &
 PID=$!
+TRACE=auto
 sleep 0.1
-okx ustctl --list-markers "$PID"
-okx ustctl --enable-marker ust/malloc $PID
-okx ustctl --enable-marker ust/free $PID
-okx ustctl --create-trace $PID
-okx ustctl --alloc-trace $PID
-okx ustctl --start-trace $PID
+okx ustctl list-markers $PID
+okx ustctl enable-marker $PID $TRACE ust/malloc
+okx ustctl enable-marker $PID $TRACE ust/free
+okx ustctl create-trace $PID $TRACE
+okx ustctl alloc-trace $PID $TRACE
+okx ustctl start-trace $PID $TRACE
 sleep 0.5
 
-okx ustctl --stop-trace $PID
-okx ustctl --destroy-trace $PID
+okx ustctl stop-trace $PID $TRACE
+okx ustctl destroy-trace $PID $TRACE
 kill $PID
 kill -SIGTERM ${UST_CONSUMERD_PID}
 wait ${UST_CONSUMERD_PID}
index afc1e21170a9b64777abc5dc7b558fbf475593e7..68427f28253e160701681c829eae4645837eee15 100755 (executable)
@@ -45,7 +45,7 @@ simple_harness_run same_line_marker/same_line_marker.sh
 
 simple_harness_run tracepoint/run
 
-simple_harness_run ustcmd_function_tests/ustcmd_function_tests
+simple_harness_run libustctl_function_tests/libustctl_function_tests
 
 echo "************************************"
 if [[ $tests_failed -eq 0 ]]; then
diff --git a/tests/ustcmd_function_tests/Makefile.am b/tests/ustcmd_function_tests/Makefile.am
deleted file mode 100644 (file)
index b70e784..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/tests/
-
-noinst_PROGRAMS = ustcmd_function_tests
-ustcmd_function_tests_SOURCES = ustcmd_function_tests.c
-ustcmd_function_tests_LDADD = $(top_builddir)/libust/libust.la \
-       $(top_builddir)/libustcmd/libustcmd.la \
-       $(top_builddir)/libust-initializer.o \
-       $(top_builddir)/tests/libtap.la \
-       -lpthread
-
diff --git a/tests/ustcmd_function_tests/ustcmd_function_tests.c b/tests/ustcmd_function_tests/ustcmd_function_tests.c
deleted file mode 100644 (file)
index d44dafc..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/* Copyright (C) 2010 Nils Carlson
- *
- * 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
- */
-
-/* Simple function tests for ustcmd */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/types.h>
-
-#include <ust/marker.h>
-#include <ust/ustcmd.h>
-
-#include "tap.h"
-
-static void ustcmd_function_tests(pid_t pid)
-{
-       int result;
-       unsigned int subbuf_size, subbuf_num;
-       unsigned int new_subbuf_size, new_subbuf_num;
-       struct marker_status *marker_status, *ms_ptr;
-       char *old_socket_path, *new_socket_path;
-       char *tmp_ustd_socket = "/tmp/tmp_ustd_socket";
-       char *trace = "auto";
-
-       printf("Connecting to pid %d\n", pid);
-
-       /* marker status array functions */
-       result = ustcmd_get_cmsf(&marker_status, pid);
-       tap_ok(!result, "ustcmd_get_cmsf");
-
-       result = 0;
-       for (ms_ptr = marker_status; ms_ptr->channel; ms_ptr++) {
-               if (!strcmp(ms_ptr->channel, "ust") &&
-                   !strcmp(ms_ptr->marker, "bar")) {
-                       result = 1;
-               }
-       }
-       tap_ok(result, "Found channel \"ust\", marker \"bar\"");
-
-       tap_ok(!ustcmd_free_cmsf(marker_status), "ustcmd_free_cmsf");
-
-       /* Get and set the socket path */
-       tap_ok(!ustcmd_get_sock_path(&old_socket_path, pid),
-              "ustcmd_get_sock_path");
-
-       printf("Socket path: %s\n", old_socket_path);
-
-       tap_ok(!ustcmd_set_sock_path(tmp_ustd_socket, pid),
-              "ustcmd_set_sock_path - set a new path");
-
-       tap_ok(!ustcmd_get_sock_path(&new_socket_path, pid),
-              "ustcmd_get_sock_path - get the new path");
-
-       tap_ok(!strcmp(new_socket_path, tmp_ustd_socket),
-              "Compare the set path and the retrieved path");
-
-       free(new_socket_path);
-
-       tap_ok(!ustcmd_set_sock_path(old_socket_path, pid),
-              "Reset the socket path");
-
-       free(old_socket_path);
-
-       /* Enable, disable markers */
-       tap_ok(!ustcmd_set_marker_state(trace, "ust", "bar", 1, pid),
-              "ustcmd_set_marker_state - existing marker ust bar");
-
-       /* Create and allocate a trace */
-       tap_ok(!ustcmd_create_trace(trace, pid), "ustcmd_create_trace");
-
-       tap_ok(!ustcmd_alloc_trace(trace, pid), "ustcmd_alloc_trace");
-
-       /* Get subbuf size and number */
-       subbuf_num = ustcmd_get_subbuf_num(trace, "ust", pid);
-       tap_ok(subbuf_num > 0, "ustcmd_get_subbuf_num - %d sub-buffers",
-              subbuf_num);
-
-       subbuf_size = ustcmd_get_subbuf_size(trace, "ust", pid);
-       tap_ok(subbuf_size, "ustcmd_get_subbuf_size - sub-buffer size is %d",
-              subbuf_size);
-
-       /* Start the trace */
-       tap_ok(!ustcmd_start_trace(trace, pid), "ustcmd_start_trace");
-
-
-       /* Stop the trace and destroy it*/
-       tap_ok(!ustcmd_stop_trace(trace, pid), "ustcmd_stop_trace");
-
-       tap_ok(!ustcmd_destroy_trace(trace, pid), "ustcmd_destroy_trace");
-
-       /* Create a new trace */
-       tap_ok(!ustcmd_create_trace(trace, pid), "ustcmd_create_trace - create a new trace");
-
-       printf("Setting new subbufer number and sizes (doubling)\n");
-       new_subbuf_num = 2 * subbuf_num;
-       new_subbuf_size = 2 * subbuf_size;
-
-       tap_ok(!ustcmd_set_subbuf_num(trace, "ust", new_subbuf_num, pid),
-              "ustcmd_set_subbuf_num");
-
-       tap_ok(!ustcmd_set_subbuf_size(trace, "ust", new_subbuf_size, pid),
-              "ustcmd_set_subbuf_size");
-
-
-       /* Allocate the new trace */
-       tap_ok(!ustcmd_alloc_trace(trace, pid), "ustcmd_alloc_trace - allocate the new trace");
-
-
-        /* Get subbuf size and number and compare with what was set */
-       subbuf_num = ustcmd_get_subbuf_num(trace, "ust", pid);
-
-       subbuf_size = ustcmd_get_subbuf_size(trace, "ust", pid);
-
-       tap_ok(subbuf_num == new_subbuf_num, "Set a new subbuf number, %d == %d",
-              subbuf_num, new_subbuf_num);
-
-
-       result = ustcmd_get_subbuf_size(trace, "ust", pid);
-       tap_ok(subbuf_size == new_subbuf_size, "Set a new subbuf size, %d == %d",
-              subbuf_size, new_subbuf_size);
-
-       tap_ok(!ustcmd_destroy_trace(trace, pid), "ustcmd_destroy_trace - without ever starting");
-
-
-       printf("##### Tests that definetly should work are completed #####\n");
-       printf("############## Start expected failure cases ##############\n");
-
-       tap_ok(ustcmd_set_marker_state(trace, "ust","bar", 1, pid),
-              "Enable already enabled marker ust/bar");
-
-       tap_ok(ustcmd_set_marker_state(trace, "ustl", "blar", 1, pid),
-              "Enable non-existent marker ustl blar");
-
-       tap_ok(ustcmd_start_trace(trace, pid),
-              "Start a non-existent trace");
-
-       tap_ok(ustcmd_destroy_trace(trace, pid),
-              "Destroy non-existent trace");
-
-       exit(tap_status() ? EXIT_FAILURE : EXIT_SUCCESS);
-
-}
-
-
-int main()
-{
-       int i, status, pipefd[2];
-       pid_t parent_pid, child_pid;
-       FILE *pipe_file;
-
-       tap_plan(27);
-
-       printf("Function tests for ustcmd\n");
-
-       parent_pid = getpid();
-       child_pid = fork();
-       if (child_pid) {
-               for(i=0; i<10; i++) {
-                       trace_mark(ust, bar, "str %s", "FOOBAZ");
-                       trace_mark(ust, bar2, "number1 %d number2 %d", 53, 9800);
-                       usleep(100000);
-               }
-
-               wait(&status);
-       } else {
-               ustcmd_function_tests(parent_pid);
-       }
-
-       exit(status ? EXIT_FAILURE : EXIT_SUCCESS);
-}
index 49e46f0a04899bd86ce7010d8a7df20f38c458e4..1e442a3fbc863dea4b6dd0271c9709eb541ebb46 100644 (file)
@@ -1,15 +1,15 @@
 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/libustcomm \
-       -I$(top_srcdir)/libustcmd $(KCOMPAT_CFLAGS)
+       -I$(top_srcdir)/libustctl $(KCOMPAT_CFLAGS)
 AM_CFLAGS = -fno-strict-aliasing
 
 bin_PROGRAMS = ustctl
 
 ustctl_SOURCES = \
-       ustctl.c
+       ustctl.c marker_cmds.c trace_cmds.c channel_cmds.c cli.c cli.h scanning_functions.c scanning_functions.h
 
 ustctl_CFLAGS = -DUST_COMPONENT=ustctl -fno-strict-aliasing
 
 ustctl_LDADD = \
        $(top_builddir)/snprintf/libustsnprintf.la \
        $(top_builddir)/libustcomm/libustcomm.la \
-       $(top_builddir)/libustcmd/libustcmd.la
+       $(top_builddir)/libustctl/libustctl.la
diff --git a/ustctl/channel_cmds.c b/ustctl/channel_cmds.c
new file mode 100644 (file)
index 0000000..2ccf460
--- /dev/null
@@ -0,0 +1,153 @@
+/* Copyright (C) 2011  Ericsson AB, Nils Carlson <nils.carlson@ericsson.com>
+ *
+ * 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
+ */
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <ust/ustctl.h>
+#include "scanning_functions.h"
+#include "usterr.h"
+#include "cli.h"
+
+static int set_subbuf_size(int argc, char *argv[])
+{
+       int result = 0;
+       pid_t pid;
+       char *channel = NULL;
+       unsigned int size;
+
+       pid = parse_pid(argv[1]);
+
+       if (scan_ch_and_num(argv[3], &channel, &size)) {
+               fprintf(stderr, "Failed to scan channel and size from"
+                               " %s\n", argv[3]);
+               if (channel)
+                       free(channel);
+               return -1;
+       }
+       if (ustctl_set_subbuf_size(argv[2], channel, size, pid)) {
+               ERR("error while trying to set the size of subbuffers "
+                   "for PID %u\n",
+                   pid);
+               result = -1;
+       }
+
+       free(channel);
+
+       return result;
+}
+
+static int set_subbuf_num(int argc, char *argv[])
+{
+       int result = 0;
+       pid_t pid;
+       char *channel = NULL;
+       unsigned int num;
+
+       pid = parse_pid(argv[1]);
+
+       if (scan_ch_and_num(argv[3], &channel, &num)) {
+               fprintf(stderr, "Failed to scan channel and number from"
+                               " %s\n", argv[3]);
+               if (channel)
+                       free(channel);
+               return -1;
+       }
+       if (ustctl_set_subbuf_num(argv[2], channel, num, pid)) {
+               ERR("error while trying to set the number of subbuffers for PID %u\n",
+                   pid);
+               result = -1;
+       }
+
+       free(channel);
+
+       return result;
+}
+
+static int get_subbuf_size(int argc, char *argv[])
+{
+       pid_t pid;
+       unsigned int size;
+
+       pid = parse_pid(argv[1]);
+
+       if ((size = ustctl_get_subbuf_size(argv[2], argv[3], pid)) < 0) {
+               ERR("error while trying to get the subbuffer size from PID %u\n",
+                   pid);
+               return -1;
+       }
+
+       printf("The subbufer size is %d bytes\n", size);
+
+       return 0;
+}
+
+static int get_subbuf_num(int argc, char *argv[])
+{
+       pid_t pid;
+       unsigned int num;
+
+       pid = parse_pid(argv[1]);
+
+       if ((num = ustctl_get_subbuf_num(argv[2], argv[3], pid)) < 0) {
+               ERR("error while trying to get the subbuffer size from PID %u\n",
+                   pid);
+               return -1;
+       }
+
+       printf("There are %u subbufers in each buffer\n", num);
+
+       return 0;
+}
+
+struct cli_cmd __cli_cmds channel_cmds[] = {
+       {
+               .name = "set-subbuf-size",
+               .description = "Set the subbuffer size for a channel",
+               .help_text = "set-subbuf-size <pid> <trace> <channel>/<size> \n"
+               "Set the subbuffer size for a channel\n",
+               .function = set_subbuf_size,
+               .desired_args = 3,
+               .desired_args_op = CLI_EQ,
+       },
+       {
+               .name = "set-subbuf-num",
+               .description = "Set the number of subbuffers for a channel",
+               .help_text = "set-subbuf-num <pid> <trace> <channel>/<num> \n"
+               "Set the number of subbuffers for a channel\n",
+               .function = set_subbuf_num,
+               .desired_args = 3,
+               .desired_args_op = CLI_EQ,
+       },
+       {
+               .name = "get-subbuf-size",
+               .description = "Get the subbuffer size for a channel",
+               .help_text = "get-subbuf-size <pid> <trace> <channel>\n"
+               "Get the subbuffer size for a channel\n",
+               .function = get_subbuf_size,
+               .desired_args = 3,
+               .desired_args_op = CLI_EQ,
+       },
+       {
+               .name = "get-subbuf-num",
+               .description = "Get the number of subbuffers for a channel",
+               .help_text = "get-subbuf-num <pid> <trace> <channel>\n"
+               "Get the number of subbuffers for a channel\n",
+               .function = get_subbuf_num,
+               .desired_args = 3,
+               .desired_args_op = CLI_EQ,
+       },
+};
diff --git a/ustctl/cli.c b/ustctl/cli.c
new file mode 100644 (file)
index 0000000..0ca9db5
--- /dev/null
@@ -0,0 +1,207 @@
+/* Copyright (C) 2011  Ericsson AB, Nils Carlson <nils.carlson@ericsson.com>
+ *
+ * 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
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "cli.h"
+
+/* This dummy command is needed to create the sections in cli.o before
+ *  other .o files have these sections, usefull for development.
+ */
+static int _dummy(int argc, char *argv[]) {
+       return 0;
+}
+
+/* Define a dummy cmd to guarantee existence of the builtin variables */
+struct cli_cmd __cli_cmds __dummy_cli_cmd[] = {
+       {
+               .name = "_dummy",
+               .description = NULL,
+               .help_text = NULL,
+               .function = _dummy,
+               .desired_args = 0,
+               .desired_args_op = 0,
+       },
+};
+
+extern struct cli_cmd __start___cli_cmds[] __attribute__((visibility("hidden")));
+extern struct cli_cmd __stop___cli_cmds[] __attribute__((visibility("hidden")));
+
+static struct cli_cmd **cli_cmd_list;
+static int cli_cmd_list_size;
+
+static char *process_name;
+
+static int compute_cli_cmds_size(void)
+{
+       long cli_cmds_start, cli_cmds_end;
+
+       cli_cmds_start = (long)__start___cli_cmds;
+       cli_cmds_end = (long)__stop___cli_cmds;
+
+       return (cli_cmds_end - cli_cmds_start) / sizeof(struct cli_cmd);
+}
+
+static void __attribute__((constructor)) generate_cli_cmd_list(int argc, char *argv[])
+{
+       struct cli_cmd *cli_cmd;
+       int section_size, i;
+
+       process_name = basename(argv[0]);
+
+       section_size = compute_cli_cmds_size();
+
+       cli_cmd_list = malloc(section_size * sizeof(void *));
+       if (!cli_cmd_list) {
+               fprintf(stderr, "Failed to allocate command list!");
+               exit(EXIT_FAILURE);
+       }
+
+       cli_cmd_list_size = 0;
+
+       cli_cmd = __start___cli_cmds;
+       for (i = 0; i < section_size; i++) {
+               if (&cli_cmd[i] == &__dummy_cli_cmd[0]) {
+                       continue;
+               }
+
+               if (cli_cmd[i].name) {
+                       cli_cmd_list[cli_cmd_list_size++] = &cli_cmd[i];
+               }
+       }
+}
+
+struct cli_cmd *find_cli_cmd(const char *command)
+{
+       int i;
+
+       for (i = 0; i < cli_cmd_list_size; i++) {
+               if (!strcmp(cli_cmd_list[i]->name, command)) {
+                       return cli_cmd_list[i];
+               }
+       }
+
+       return NULL;
+}
+
+static int cmpcli_cmds(const void *p1, const void *p2)
+{
+       return strcmp(* (char * const *) ((struct cli_cmd *)p1)->name,
+                     * (char * const *) ((struct cli_cmd *)p2)->name);
+}
+
+#define HELP_BUFFER_SIZE 4096
+
+static void print_cmd_help(const char *prefix, const char *infix,
+                          struct cli_cmd *cli_cmd)
+{
+       if (cli_cmd->help_text) {
+               fprintf(stderr, "%s%s%s",
+                       prefix,
+                       infix,
+                       cli_cmd->help_text);
+       } else if (cli_cmd->description) {
+               fprintf(stderr, "%s%s%s\n%s\n",
+                       prefix,
+                       infix,
+                       cli_cmd->name,
+                       cli_cmd->description);
+       } else {
+               fprintf(stderr, "No help available for %s\n",
+                       cli_cmd->name);
+       }
+}
+
+void list_cli_cmds(int option)
+{
+       int i;
+
+       qsort(cli_cmd_list, cli_cmd_list_size, sizeof(void *), cmpcli_cmds);
+
+       for (i = 0; i < cli_cmd_list_size; i++) {
+               switch (option) {
+               case CLI_SIMPLE_LIST:
+                       fprintf(stderr, "%s ", cli_cmd_list[i]->name);
+                       break;
+               case CLI_DESCRIPTIVE_LIST:
+                       fprintf(stderr, "   %-25s%s\n", cli_cmd_list[i]->name,
+                               cli_cmd_list[i]->description);
+                       break;
+               case CLI_EXTENDED_LIST:
+                       print_cmd_help("", "", cli_cmd_list[i]);
+                       fprintf(stderr, "\n");
+                       break;
+               }
+       }
+
+       if (option == CLI_SIMPLE_LIST) {
+               fprintf(stderr, "\n");
+       }
+}
+
+int cli_print_help(const char *command)
+{
+       struct cli_cmd *cli_cmd;
+
+       cli_cmd = find_cli_cmd(command);
+       if (!cli_cmd) {
+               return -1;
+       }
+
+       print_cmd_help(process_name, " ", cli_cmd);
+
+       return 0;
+}
+
+static void cli_check_argc(const char *command, int args,
+                          int operator, int desired_args)
+{
+       switch(operator) {
+       case CLI_EQ:
+               if (args != desired_args)
+                       goto print_error;
+               break;
+       case CLI_GE:
+               if (args < desired_args)
+                       goto print_error;
+               break;
+       }
+
+       return;
+
+print_error:
+       fprintf(stderr, "%s %s requires %s%d argument%s, see usage.\n",
+               process_name, command, operator == CLI_EQ ? "" : "at least ",
+               desired_args, desired_args > 1 ? "s" : "");
+       cli_print_help(command);
+       exit(EXIT_FAILURE);
+}
+
+
+void cli_dispatch_cmd(struct cli_cmd *cmd, int argc, char *argv[])
+{
+       cli_check_argc(cmd->name, argc - 1, cmd->desired_args_op,
+                      cmd->desired_args);
+
+       if (cmd->function(argc, argv)) {
+               exit(EXIT_FAILURE);
+       }
+
+       exit(EXIT_SUCCESS);
+}
diff --git a/ustctl/cli.h b/ustctl/cli.h
new file mode 100644 (file)
index 0000000..a1e4eed
--- /dev/null
@@ -0,0 +1,50 @@
+/* Copyright (C) 2011  Ericsson AB, Nils Carlson <nils.carlson@ericsson.com>
+ *
+ * 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
+ */
+#ifndef _CLI_H
+#define _CLI_H
+
+struct cli_cmd {
+       const char *name;
+       const char *description;
+       const char *help_text;
+       int (*function)(int, char **);
+       int desired_args;
+       int desired_args_op;
+} __attribute__((aligned(8)));
+
+#define __cli_cmds __attribute__((section("__cli_cmds"), aligned(8), used))
+
+struct cli_cmd *find_cli_cmd(const char *command);
+
+enum cli_list_opts {
+       CLI_SIMPLE_LIST,
+       CLI_DESCRIPTIVE_LIST,
+       CLI_EXTENDED_LIST,
+};
+
+void list_cli_cmds(int option);
+
+int cli_print_help(const char *command);
+
+enum cli_arg_ops {
+       CLI_EQ,
+       CLI_GE,
+};
+
+void cli_dispatch_cmd(struct cli_cmd *cmd, int argc, char *argv[]);
+
+#endif /* _CLI_H */
diff --git a/ustctl/marker_cmds.c b/ustctl/marker_cmds.c
new file mode 100644 (file)
index 0000000..6544669
--- /dev/null
@@ -0,0 +1,144 @@
+/* Copyright (C) 2011  Ericsson AB, Nils Carlson <nils.carlson@ericsson.com>
+ *
+ * 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
+ */
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <ust/ustctl.h>
+#include "scanning_functions.h"
+#include "usterr.h"
+#include "cli.h"
+
+static int list_markers(int argc, char *argv[])
+{
+       struct marker_status *cmsf = NULL;
+       int i;
+       pid_t pid;
+
+       pid = parse_pid(argv[1]);
+
+       if (ustctl_get_cmsf(&cmsf, pid)) {
+               ERR("error while trying to list markers for PID %u\n", pid);
+               return -1;
+       }
+       for (i = 0; cmsf[i].channel; i++) {
+               printf("{PID: %u, channel/marker: %s/%s, "
+                      "state: %u, fmt: %s}\n",
+                      (unsigned int) pid,
+                      cmsf[i].channel,
+                      cmsf[i].marker,
+                      cmsf[i].state,
+                      cmsf[i].fs);
+       }
+       ustctl_free_cmsf(cmsf);
+       return 0;
+}
+
+static int enable_marker(int argc, char *argv[])
+{
+       int i, result = 0;
+       pid_t pid;
+       char *channel, *marker;
+
+       pid = parse_pid(argv[1]);
+
+       for (i = 3; i < argc; i++) {
+               channel = NULL;
+               marker = NULL;
+               if (scan_ch_marker(argv[i],
+                                  &channel, &marker)) {
+                       result = -1;
+                       fprintf(stderr, "Failed to scan channel and marker from"
+                               " %s\n", argv[i]);
+                       if (channel)
+                               free(channel);
+                       if (marker)
+                               free(marker);
+               }
+               if (ustctl_set_marker_state(argv[2], channel, marker, 1, pid)) {
+                       PERROR("error while trying to enable marker %s with PID %u",
+                              argv[i], pid);
+                       result = -1;
+               }
+               free(channel);
+               free(marker);
+       }
+
+       return result;
+}
+
+static int disable_marker(int argc, char *argv[])
+{
+       int i, result = 0;
+       pid_t pid;
+       char *channel, *marker;
+
+       pid = parse_pid(argv[1]);
+
+       for (i = 3; i < argc; i++) {
+               channel = NULL;
+               marker = NULL;
+               if (scan_ch_marker(argv[i],
+                                  &channel, &marker)) {
+                       fprintf(stderr, "Failed to scan channel and marker from"
+                               " %s\n", argv[i]);
+                       if (channel)
+                               free(channel);
+                       if (marker)
+                               free(marker);
+                       return -1;
+               }
+               if (ustctl_set_marker_state(argv[2], channel, marker, 0, pid)) {
+                       PERROR("error while trying to disable marker %s with PID %u",
+                              argv[i], pid);
+                       result = -1;
+               }
+               free(channel);
+               free(marker);
+       }
+
+       return result;
+}
+
+struct cli_cmd __cli_cmds marker_cmds[] = {
+       {
+               .name = "list-markers",
+               .description = "List markers for a given pid",
+               .help_text = "list-markers <pid>\n"
+               "List the markers in a process\n",
+               .function = list_markers,
+               .desired_args = 1,
+               .desired_args_op = CLI_EQ,
+       },
+       {
+               .name = "enable-marker",
+               .description = "Enable markers for a given pid",
+               .help_text = "enable-marker <pid> <trace> <channel>/<marker>... \n"
+               "Enable the listed markers for the trace in process pid\n",
+               .function = enable_marker,
+               .desired_args = 3,
+               .desired_args_op = CLI_GE,
+       },
+       {
+              .name = "disable-marker",
+              .description = "Disable markers for a given pid",
+              .help_text = "disable-marker <pid> <trace> <channel>/<marker>... \n"
+              "Disable the listed markers for the trace in process pid\n",
+              .function = disable_marker,
+              .desired_args = 3,
+              .desired_args_op = CLI_GE,
+       }
+};
diff --git a/ustctl/scanning_functions.c b/ustctl/scanning_functions.c
new file mode 100644 (file)
index 0000000..a3eceb5
--- /dev/null
@@ -0,0 +1,84 @@
+/* Copyright (C) 2011  Ericsson AB, Nils Carlson <nils.carlson@ericsson.com>
+ *
+ * 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
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <ust/ustctl.h>
+#include "usterr.h"
+
+
+pid_t parse_pid(const char *pid_string)
+{
+       pid_t pid;
+
+       errno = 0;
+       pid = strtoull(pid_string, NULL, 10);
+       if (errno) {
+               perror("Failed to parse pid");
+               exit(EXIT_FAILURE);
+       }
+
+       return pid;
+}
+
+int scan_ch_marker(const char *channel_marker, char **channel, char **marker)
+{
+       int result;
+
+       *channel = NULL;
+       *marker = NULL;
+
+       result = sscanf(channel_marker, "%a[^/]/%as", channel, marker);
+       if (result != 2) {
+               if (errno) {
+                       PERROR("Failed to read channel and marker names");
+               } else {
+                       ERR("Failed to parse marker and channel names");
+               }
+               if (*channel) {
+                       free(*channel);
+               }
+               if (*marker) {
+                       free(*marker);
+               }
+               return -1;
+       }
+
+       return 0;
+}
+
+int scan_ch_and_num(const char *ch_num, char **channel, unsigned int *num)
+{
+       int result;
+
+       *channel = NULL;
+
+       result = sscanf(ch_num, "%a[^/]/%u", channel, num);
+       if (result != 2) {
+               if (errno) {
+                       PERROR("Failed to parse channel and number");
+               } else {
+                       ERR("Failed to parse channel and number");
+               }
+               if (*channel) {
+                       free(*channel);
+               }
+               return -1;
+       }
+
+       return 0;
+}
diff --git a/ustctl/scanning_functions.h b/ustctl/scanning_functions.h
new file mode 100644 (file)
index 0000000..c37eba1
--- /dev/null
@@ -0,0 +1,26 @@
+/* Copyright (C) 2011  Ericsson AB, Nils Carlson <nils.carlson@ericsson.com>
+ *
+ * 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
+ */
+#ifndef __SCANNING_FUNCTIONS_H
+#define __SCANNING_FUNCTIONS_H
+
+pid_t parse_pid(const char *pid_string);
+
+int scan_ch_marker(const char *channel_marker, char **channel, char **marker);
+
+int scan_ch_and_num(const char *ch_num, char **channel, unsigned int *num);
+
+#endif /* __SCANNING_FUNCTIONS_H */
diff --git a/ustctl/trace_cmds.c b/ustctl/trace_cmds.c
new file mode 100644 (file)
index 0000000..020e5b2
--- /dev/null
@@ -0,0 +1,162 @@
+/* Copyright (C) 2011  Ericsson AB, Nils Carlson <nils.carlson@ericsson.com>
+ *
+ * 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
+ */
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <ust/ustctl.h>
+#include "scanning_functions.h"
+#include "usterr.h"
+#include "cli.h"
+
+
+static int create_trace(int argc, char *argv[])
+{
+       pid_t pid;
+
+       pid = parse_pid(argv[1]);
+
+       if (ustctl_create_trace(argv[2], pid)) {
+               ERR("Failed to create trace %s for PID %u\n", argv[2], pid);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int alloc_trace(int argc, char *argv[])
+{
+       pid_t pid;
+
+       pid = parse_pid(argv[1]);
+
+       if (ustctl_alloc_trace(argv[2], pid)) {
+               ERR("Failed to allocate trace %s for PID %u\n", argv[2], pid);
+               return -1;
+       }
+       return 0;
+}
+
+static int start_trace(int argc, char *argv[])
+{
+       pid_t pid;
+
+       pid = parse_pid(argv[1]);
+
+       if (ustctl_start_trace(argv[2], pid)) {
+               ERR("Failed to start trace %s for PID %u\n", argv[2], pid);
+               return -1;
+       }
+       return 0;
+}
+
+static int stop_trace(int argc, char *argv[])
+{
+       pid_t pid;
+
+       pid = parse_pid(argv[1]);
+
+       if (ustctl_stop_trace(argv[2], pid)) {
+               ERR("Failed to stop trace %s for PID %u\n", argv[2], pid);
+               return -1;
+       }
+       return 0;
+}
+
+static int destroy_trace(int argc, char *argv[])
+{
+       pid_t pid;
+
+       pid = parse_pid(argv[1]);
+
+       if (ustctl_destroy_trace(argv[2], pid)) {
+               ERR("Failed to destroy trace %s for PID %u\n", argv[2], pid);
+               return -1;
+       }
+       return 0;
+}
+
+static int force_subbuf_switch(int argc, char *argv[])
+{
+       pid_t pid;
+
+       pid = parse_pid(argv[1]);
+
+       if (ustctl_force_switch(pid)) {
+               ERR("error while trying to force switch for PID %u\n", pid);
+               return -1;
+       }
+
+       return 0;
+}
+
+struct cli_cmd __cli_cmds trace_cmds[] = {
+       {
+               .name = "create-trace",
+               .description = "Create a trace for a process",
+               .help_text = "create-trace <pid> <trace>\n"
+               "Create a trace for a process\n",
+               .function = create_trace,
+               .desired_args = 2,
+               .desired_args_op = CLI_EQ,
+       },
+       {
+               .name = "alloc-trace",
+               .description = "Allocate a trace for a process",
+               .help_text = "alloc-trace <pid> <trace>\n"
+               "Allocate a trace for a process\n",
+               .function = alloc_trace,
+               .desired_args = 2,
+               .desired_args_op = CLI_EQ,
+       },
+       {
+               .name = "start-trace",
+               .description = "Start a trace for a process",
+               .help_text = "start-trace <pid> <trace>\n"
+               "Start a trace for a process\n",
+               .function = start_trace,
+               .desired_args = 2,
+               .desired_args_op = CLI_EQ,
+       },
+       {
+               .name = "stop-trace",
+               .description = "Stop a trace for a process",
+               .help_text = "stop-trace <pid> <trace>\n"
+               "Stop a trace for a process\n",
+               .function = stop_trace,
+               .desired_args = 2,
+               .desired_args_op = CLI_EQ,
+       },
+       {
+               .name = "destroy-trace",
+               .description = "Destroy a trace for a process",
+               .help_text = "destroy-trace <pid> <trace>\n"
+               "Destroy a trace for a process\n",
+               .function = destroy_trace,
+               .desired_args = 2,
+               .desired_args_op = CLI_EQ,
+       },
+       {
+               .name = "force-subbuf-switch",
+               .description = "Force a subbuffer switch",
+               .help_text = "force-subbuf-switch <pid> <trace>\n"
+               "Force a subbuffer switch for a trace, currently this forces\n"
+               "a subbuffer switch for all traces in a process\n",
+               .function = force_subbuf_switch,
+               .desired_args = 2,
+               .desired_args_op = CLI_EQ,
+       },
+};
index aad3834a4ccfeb597bc21f22bd95b09de80262ee..c1bbe8ce0155289e2975325b6d5631d5ce45e254 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2009  Pierre-Marc Fournier
+ * Copyright (C) 2011  Ericsson AB, Nils Carlson <nils.carlson@ericsson.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
 #include <stdlib.h>
 #include <fcntl.h>
 
-#include "ust/ustcmd.h"
+#include "ust/ustctl.h"
 #include "usterr.h"
+#include "cli.h"
+#include "scanning_functions.h"
 
-enum command {
-       CREATE_TRACE=1000,
-       ALLOC_TRACE,
-       START_TRACE,
-       STOP_TRACE,
-       DESTROY_TRACE,
-       LIST_MARKERS,
-       LIST_TRACE_EVENTS,
-       ENABLE_MARKER,
-       DISABLE_MARKER,
-       GET_ONLINE_PIDS,
-       SET_SUBBUF_SIZE,
-       SET_SUBBUF_NUM,
-       GET_SUBBUF_SIZE,
-       GET_SUBBUF_NUM,
-       GET_SOCK_PATH,
-       SET_SOCK_PATH,
-       FORCE_SWITCH,
-       UNKNOWN
-};
-
-struct ust_opts {
-       enum command cmd;
-       pid_t *pids;
-       char *regex;
-};
-
-char *progname = NULL;
-
-void usage(void)
+void usage(const char *process_name)
 {
-       fprintf(stderr, "usage: %s COMMAND PIDs...\n", progname);
-       fprintf(stderr, "\nControl the tracing of a process that supports LTTng Userspace Tracing.\n\
-\n\
-Commands:\n\
-    --create-trace\t\t\tCreate trace\n\
-    --alloc-trace\t\t\tAlloc trace\n\
-    --start-trace\t\t\tStart tracing\n\
-    --stop-trace\t\t\tStop tracing\n\
-    --destroy-trace\t\t\tDestroy the trace\n\
-    --set-subbuf-size \"CHANNEL/bytes\"\tSet the size of subbuffers per channel\n\
-    --set-subbuf-num \"CHANNEL/n\"\tSet the number of subbuffers per channel\n\
-    --set-sock-path\t\t\tSet the path of the daemon socket\n\
-    --get-subbuf-size \"CHANNEL\"\t\tGet the size of subbuffers per channel\n\
-    --get-subbuf-num \"CHANNEL\"\t\tGet the number of subbuffers per channel\n\
-    --get-sock-path\t\t\tGet the path of the daemon socket\n\
-    --enable-marker \"CHANNEL/MARKER\"\tEnable a marker\n\
-    --disable-marker \"CHANNEL/MARKER\"\tDisable a marker\n\
-    --list-markers\t\t\tList the markers of the process, their\n\t\t\t\t\t  state and format string\n\
-    --list-trace-events\t\t\tList the trace-events of the process\n\
-    --force-switch\t\t\tForce a subbuffer switch\n\
-\
-");
+       fprintf(stderr, "Usage: %s COMMAND [ARGS]...\n", process_name);
+       fprintf(stderr,
+               "Control tracing within a process that supports UST,\n"
+               " the Userspace Tracing libary\n"
+               "Options:\n"
+               "  -h[<cmd>], --help[=<cmd>]        "
+               "help, for a command if provided\n"
+               "  -l, --list                       "
+               "short list of commands\n"
+               "  -e, --extended-list              "
+              "extented list of commands with help\n"
+               "Commands:\n");
+       list_cli_cmds(CLI_DESCRIPTIVE_LIST);
 }
 
-int parse_opts_long(int argc, char **argv, struct ust_opts *opts)
+struct option options[] =
 {
-       int c;
+       {"help", 2, NULL, 'h'},
+       {"list", 0, NULL, 'l'},
+       {"extended-list", 0, NULL, 'e'},
+       {NULL, 0, NULL, 0},
+};
 
-       opts->pids = NULL;
-       opts->regex = NULL;
+int main(int argc, char *argv[])
+{
+       struct cli_cmd *cli_cmd;
+       int opt;
 
-       while (1) {
-               int option_index = 0;
-               static struct option long_options[] = {
-                       { "create-trace", 0, 0, CREATE_TRACE },
-                       { "alloc-trace", 0, 0, ALLOC_TRACE },
-                       { "start-trace", 0, 0, START_TRACE },
-                       { "stop-trace", 0, 0, STOP_TRACE },
-                       { "destroy-trace", 0, 0, DESTROY_TRACE },
-                       { "list-markers", 0, 0, LIST_MARKERS },
-                       { "list-trace-events", 0, 0, LIST_TRACE_EVENTS},
-                       { "enable-marker", 1, 0, ENABLE_MARKER },
-                       { "disable-marker", 1, 0, DISABLE_MARKER },
-                       { "help", 0, 0, 'h' },
-                       { "online-pids", 0, 0, GET_ONLINE_PIDS },
-                       { "set-subbuf-size", 1, 0, SET_SUBBUF_SIZE },
-                       { "set-subbuf-num", 1, 0, SET_SUBBUF_NUM },
-                       { "get-subbuf-size", 1, 0, GET_SUBBUF_SIZE },
-                       { "get-subbuf-num", 1, 0, GET_SUBBUF_NUM },
-                       { "get-sock-path", 0, 0, GET_SOCK_PATH },
-                       { "set-sock-path", 1, 0, SET_SOCK_PATH },
-                       { "force-switch", 0, 0, FORCE_SWITCH },
-                       { 0, 0, 0, 0 }
-               };
+       if(argc <= 1) {
+               fprintf(stderr, "No operation specified.\n");
+               usage(argv[0]);
+               exit(EXIT_FAILURE);
+       }
 
-               c = getopt_long(argc, argv, "h", long_options, &option_index);
-               if (c == -1)
+       while ((opt = getopt_long(argc, argv, "+h::le",
+                                 options, NULL)) != -1) {
+               switch (opt) {
+               case 'h':
+                       if (!optarg) {
+                               usage(argv[0]);
+                       } else {
+                               if (cli_print_help(optarg)) {
+                                       fprintf(stderr, "No such command %s\n",
+                                               optarg);
+                               }
+                       }
+                       exit(EXIT_FAILURE);
                        break;
-
-               if(c >= 1000)
-                       opts->cmd = c;
-
-               switch (c) {
-               case 0:
-                       printf("option %s", long_options[option_index].name);
-                       if (optarg)
-                               printf(" with arg %s", optarg);
-                       printf("\n");
+               case 'l':
+                       list_cli_cmds(CLI_SIMPLE_LIST);
+                       exit(EXIT_FAILURE);
                        break;
-
-               case ENABLE_MARKER:
-               case DISABLE_MARKER:
-               case SET_SUBBUF_SIZE:
-               case SET_SUBBUF_NUM:
-               case GET_SUBBUF_SIZE:
-               case GET_SUBBUF_NUM:
-               case SET_SOCK_PATH:
-                       opts->regex = strdup(optarg);
+               case 'e':
+                       list_cli_cmds(CLI_EXTENDED_LIST);
+                       exit(EXIT_FAILURE);
+               default:
+                       fprintf(stderr, "Unknown option\n");
                        break;
-
-               case 'h':
-                       usage();
-                       exit(0);
-
-               case '?':
-                       fprintf(stderr, "Invalid argument\n\n");
-                       usage();
-                       exit(1);
                }
        }
 
-       if (argc - optind > 0 && opts->cmd != GET_ONLINE_PIDS) {
-               int i;
-               int pididx=0;
-               opts->pids = zmalloc((argc-optind+1) * sizeof(pid_t));
-
-               for(i=optind; i<argc; i++) {
-                       /* don't take any chances, use a long long */
-                       long long tmp;
-                       char *endptr;
-                       tmp = strtoull(argv[i], &endptr, 10);
-                       if(*endptr != '\0') {
-                               ERR("The pid \"%s\" is invalid.", argv[i]);
-                               return 1;
-                       }
-                       opts->pids[pididx++] = (pid_t) tmp;
-               }
-               opts->pids[pididx] = -1;
+       cli_cmd = find_cli_cmd(argv[optind]);
+       if (!cli_cmd) {
+               fprintf(stderr, "No such command %s\n",
+                       argv[optind]);
+               exit(EXIT_FAILURE);
        }
 
+       cli_dispatch_cmd(cli_cmd, argc - optind, &argv[optind]);
+
        return 0;
 }
 
-static int scan_ch_marker(const char *channel_marker, char **channel,
-                       char **marker)
+static int list_trace_events(int argc, char *argv[])
 {
-       int result;
+       struct trace_event_status *tes = NULL;
+       int i;
+       pid_t pid;
 
-       *channel = NULL;
-       *marker = NULL;
+       pid = parse_pid(argv[1]);
 
-       result = sscanf(channel_marker, "%a[^/]/%as", channel, marker);
-       if (result != 2) {
-               if (errno) {
-                       PERROR("Failed to read channel and marker names");
-               } else {
-                       ERR("Failed to parse marker and channel names");
-               }
-               if (*channel) {
-                       free(*channel);
-               }
-               if (*marker) {
-                       free(*marker);
-               }
+       if (ustctl_get_tes(&tes, pid)) {
+               ERR("error while trying to list "
+                   "trace_events for PID %u\n",
+                   pid);
                return -1;
-       } else {
-               return 0;
        }
+       i = 0;
+       for (i = 0; tes[i].name; i++) {
+               printf("{PID: %u, trace_event: %s}\n",
+                      pid,
+                      tes[i].name);
+       }
+       ustctl_free_tes(tes);
+
+       return 0;
 }
 
-static int scan_ch_and_num(const char *ch_num, char **channel, unsigned int *num)
+static int set_sock_path(int argc, char *argv[])
 {
-       int result;
+       pid_t pid;
 
-       *channel = NULL;
+       pid = parse_pid(argv[1]);
 
-       result = sscanf(ch_num, "%a[^/]/%u", channel, num);
-       if (result != 2) {
-               if (errno) {
-                       PERROR("Failed to parse channel and number");
-               } else {
-                       ERR("Failed to parse channel and number");
-               }
-               if (*channel) {
-                       free(*channel);
-               }
+       if (ustctl_set_sock_path(argv[2], pid)) {
+               ERR("error while trying to set sock path for PID %u\n", pid);
                return -1;
        }
-}
 
-char *trace = "auto";
+       return 0;
+}
 
-int main(int argc, char *argv[])
+static int get_sock_path(int argc, char *argv[])
 {
-       pid_t *pidit;
-       int result;
-       int retval = EXIT_SUCCESS;
-       char *tmp;
-       struct ust_opts opts;
+       pid_t pid;
+       char *sock_path;
 
-       progname = argv[0];
+       pid = parse_pid(argv[1]);
 
-       if(argc <= 1) {
-               fprintf(stderr, "No operation specified.\n");
-               usage();
-               exit(EXIT_FAILURE);
-       }
-
-       result = parse_opts_long(argc, argv, &opts);
-       if(result) {
-               fprintf(stderr, "\n");
-               usage();
-               exit(EXIT_FAILURE);
-       }
-
-       if(opts.pids == NULL && opts.cmd != GET_ONLINE_PIDS) {
-               fprintf(stderr, "No pid specified.\n");
-               usage();
-               exit(EXIT_FAILURE);
-       }
-       if(opts.cmd == UNKNOWN) {
-               fprintf(stderr, "No command specified.\n");
-               usage();
-               exit(EXIT_FAILURE);
-       }
-       if (opts.cmd == GET_ONLINE_PIDS) {
-               pid_t *pp = ustcmd_get_online_pids();
-               unsigned int i = 0;
-
-               if (pp) {
-                       while (pp[i] != 0) {
-                               printf("%u\n", (unsigned int) pp[i]);
-                               ++i;
-                       }
-                       free(pp);
-               }
-
-               exit(EXIT_SUCCESS);
-       }
-
-       pidit = opts.pids;
-       struct marker_status *cmsf = NULL;
-       struct trace_event_status *tes = NULL;
-       unsigned int i = 0;
-
-       while(*pidit != -1) {
-               switch (opts.cmd) {
-                       case CREATE_TRACE:
-                               result = ustcmd_create_trace(trace, *pidit);
-                               if (result) {
-                                       ERR("error while trying to create trace with PID %u\n", (unsigned int) *pidit);
-                                       retval = EXIT_FAILURE;
-                                       break;
-                               }
-                               break;
-
-                       case START_TRACE:
-                               result = ustcmd_start_trace(trace, *pidit);
-                               if (result) {
-                                       ERR("error while trying to for trace with PID %u\n", (unsigned int) *pidit);
-                                       retval = EXIT_FAILURE;
-                                       break;
-                               }
-                               break;
-
-                       case STOP_TRACE:
-                               result = ustcmd_stop_trace(trace, *pidit);
-                               if (result) {
-                                       ERR("error while trying to stop trace for PID %u\n", (unsigned int) *pidit);
-                                       retval = EXIT_FAILURE;
-                                       break;
-                               }
-                               break;
-
-                       case DESTROY_TRACE:
-                               result = ustcmd_destroy_trace(trace, *pidit);
-                               if (result) {
-                                       ERR("error while trying to destroy trace with PID %u\n", (unsigned int) *pidit);
-                                       retval = EXIT_FAILURE;
-                                       break;
-                               }
-                               break;
-
-                       case LIST_MARKERS:
-                               cmsf = NULL;
-                               if (ustcmd_get_cmsf(&cmsf, *pidit)) {
-                                       ERR("error while trying to list markers for PID %u\n", (unsigned int) *pidit);
-                                       retval = EXIT_FAILURE;
-                                       break;
-                               }
-                               i = 0;
-                               while (cmsf[i].channel != NULL) {
-                                       printf("{PID: %u, channel/marker: %s/%s, "
-                                               "state: %u, fmt: %s}\n",
-                                               (unsigned int) *pidit,
-                                               cmsf[i].channel,
-                                               cmsf[i].marker,
-                                               cmsf[i].state,
-                                               cmsf[i].fs);
-                                       ++i;
-                               }
-                               ustcmd_free_cmsf(cmsf);
-                               break;
-
-                       case LIST_TRACE_EVENTS:
-                               tes = NULL;
-                               if (ustcmd_get_tes(&tes, *pidit)) {
-                                       ERR("error while trying to list "
-                                           "trace_events for PID %u\n",
-                                           (unsigned int) *pidit);
-                                       break;
-                               }
-                               i = 0;
-                               while (tes[i].name != NULL) {
-                                       printf("{PID: %u, trace_event: %s}\n",
-                                              (unsigned int) *pidit,
-                                              tes[i].name);
-                                       ++i;
-                               }
-                               ustcmd_free_tes(tes);
-
-                               break;
-                       case ENABLE_MARKER:
-                               if (opts.regex) {
-                                       char *channel, *marker;
-
-                                       if (scan_ch_marker(opts.regex,
-                                                          &channel, &marker)) {
-                                               retval = EXIT_FAILURE;
-                                               break;
-                                       }
-                                       if (ustcmd_set_marker_state(trace, channel, marker, 1, *pidit)) {
-                                               PERROR("error while trying to enable marker %s with PID %u",
-                                                      opts.regex, (unsigned int) *pidit);
-                                               retval = EXIT_FAILURE;
-                                       }
-                               }
-
-                               break;
-                       case DISABLE_MARKER:
-                               if (opts.regex) {
-                                       char *channel, *marker;
-
-                                       if (scan_ch_marker(opts.regex,
-                                                          &channel, &marker)) {
-                                               retval = EXIT_FAILURE;
-                                               break;
-                                       }
-                                       if (ustcmd_set_marker_state(trace, channel, marker, 0, *pidit)) {
-                                               ERR("error while trying to disable marker %s with PID %u\n",
-                                                               opts.regex, (unsigned int) *pidit);
-                                               retval = EXIT_FAILURE;
-                                       }
-                               }
-                               break;
-
-                       case SET_SUBBUF_SIZE:
-                               if (opts.regex) {
-                                       char *channel;
-                                       unsigned int size;
-                                       if (scan_ch_and_num(opts.regex, &channel, &size)) {
-                                               retval = EXIT_FAILURE;
-                                               break;
-                                       }
-
-                                       if (ustcmd_set_subbuf_size(trace, channel, size, *pidit)) {
-                                               ERR("error while trying to set the size of subbuffers with PID %u\n",
-                                                               (unsigned int) *pidit);
-                                               retval = EXIT_FAILURE;
-                                       }
-                               }
-                               break;
-
-                       case SET_SUBBUF_NUM:
-                               if (opts.regex) {
-                                       char *channel;
-                                       unsigned int num;
-                                       if (scan_ch_and_num(opts.regex, &channel, &num)) {
-                                               retval = EXIT_FAILURE;
-                                               break;
-                                       }
-
-                                       if (num < 2) {
-                                               ERR("Subbuffer count should be greater or equal to 2");
-                                               retval = EXIT_FAILURE;
-                                               break;
-                                       }
-                                       if (ustcmd_set_subbuf_num(trace, channel, num, *pidit)) {
-                                               ERR("error while trying to set the number of subbuffers with PID %u\n",
-                                                               (unsigned int) *pidit);
-                                               retval = EXIT_FAILURE;
-                                       }
-                               }
-                               break;
-
-                       case GET_SUBBUF_SIZE:
-                               result = ustcmd_get_subbuf_size(trace, opts.regex, *pidit);
-                               if (result == -1) {
-                                       ERR("error while trying to get_subuf_size with PID %u\n", (unsigned int) *pidit);
-                                       retval = EXIT_FAILURE;
-                                       break;
-                               }
-
-                               printf("the size of subbufers is %d\n", result);
-                               break;
-
-                       case GET_SUBBUF_NUM:
-                               result = ustcmd_get_subbuf_num(trace, opts.regex, *pidit);
-                               if (result == -1) {
-                                       ERR("error while trying to get_subuf_num with PID %u\n", (unsigned int) *pidit);
-                                       retval = EXIT_FAILURE;
-                                       break;
-                               }
-
-                               printf("the number of subbufers is %d\n", result);
-                               break;
-
-                       case ALLOC_TRACE:
-                               result = ustcmd_alloc_trace(trace, *pidit);
-                               if (result) {
-                                       ERR("error while trying to alloc trace with PID %u\n", (unsigned int) *pidit);
-                                       retval = EXIT_FAILURE;
-                               }
-                               break;
-
-                       case GET_SOCK_PATH:
-                               result = ustcmd_get_sock_path(&tmp, *pidit);
-                               if (result) {
-                                       ERR("error while trying to get sock path for PID %u\n", (unsigned int) *pidit);
-                                       retval = EXIT_FAILURE;
-                                       break;
-                               }
-                               printf("the socket path is %s\n", tmp);
-                               free(tmp);
-                               break;
-
-                       case SET_SOCK_PATH:
-                               result = ustcmd_set_sock_path(opts.regex, *pidit);
-                               if (result) {
-                                       ERR("error while trying to set sock path for PID %u\n", (unsigned int) *pidit);
-                                       retval = EXIT_FAILURE;
-                               }
-                               break;
-
-                       case FORCE_SWITCH:
-                               result = ustcmd_force_switch(*pidit);
-                               if (result) {
-                                       ERR("error while trying to force switch for PID %u\n", (unsigned int) *pidit);
-                                       retval = EXIT_FAILURE;
-                               }
-                               break;
-
-                       default:
-                               ERR("unknown command\n");
-                               retval = EXIT_FAILURE;
-                               break;
-               }
-
-               pidit++;
-       }
-
-       if (opts.pids != NULL) {
-               free(opts.pids);
-       }
-       if (opts.regex != NULL) {
-               free(opts.regex);
+       if (ustctl_get_sock_path(&sock_path, pid)) {
+               ERR("error while trying to get sock path for PID %u\n", pid);
+               return -1;
        }
+       printf("The socket path is %s\n", sock_path);
+       free(sock_path);
 
-       return retval;
+       return 0;
 }
 
+struct cli_cmd __cli_cmds general_cmds[] = {
+       {
+               .name = "list-trace-events",
+               .description = "List trace-events for a given pid",
+               .help_text = "list-trace-events <pid>\n"
+               "List the trace-events in a process\n",
+               .function = list_trace_events,
+               .desired_args = 1,
+               .desired_args_op = CLI_EQ,
+       },
+       {
+               .name = "set-sock-path",
+               .description = "Set the path to the consumer daemon socket",
+               .help_text = "set-sock-path <pid> <sock-path>\n"
+               "Set the path to the consumer daemon socket\n",
+               .function = set_sock_path,
+               .desired_args = 2,
+               .desired_args_op = CLI_EQ,
+       },
+       {
+               .name = "get-sock-path",
+               .description = "Get the path to the consumer daemon socket",
+               .help_text = "get-sock-path <pid>\n"
+               "Get the path to the consumer daemon socket\n",
+               .function = get_sock_path,
+               .desired_args = 1,
+               .desired_args_op = CLI_EQ,
+       },
+};
This page took 0.074885 seconds and 4 git commands to generate.