[systemd-devel] [PATCH] systemctl: add systemctl cat

2013-11-30 Thread Shawn Landden
---
 TODO  |   2 -
 man/systemctl.xml |   9 
 src/shared/fileio.c   |  73 ++-
 src/shared/fileio.h   |   1 +
 src/shared/util.c |   2 +
 src/systemctl/systemctl.c | 107 ++
 6 files changed, 191 insertions(+), 3 deletions(-)

diff --git a/TODO b/TODO
index 6ba4b31..7c6003b 100644
--- a/TODO
+++ b/TODO
@@ -125,8 +125,6 @@ Features:
 
 * optimize the cgroup propagation bits, especially unit_get_members_mask(), 
cgroup_context_get_mask()
 
-* systemctl cat or systemctl view command or or so, that cats the backing 
unit file of a service, plus its drop-ins and shows them in a pager
-
 * rfkill,backlight: we probably should run the load tools inside of the udev 
rules so that the state is properly initialized by the time other software sees 
it
 
 * tmpfiles: when applying ownership to /run/log/journal, also do this for the 
journal fails contained in it
diff --git a/man/systemctl.xml b/man/systemctl.xml
index 33a2935..8a66130 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -727,7 +727,16 @@ kobject-uevent 1 systemd-udevd-kernel.socket 
systemd-udevd.service
 human-readable output./para
   /listitem
 /varlistentry
+varlistentry
+  termcommandcat 
replaceableNAME/replaceable.../command/term
 
+  listitem
+paraShow backing files of one or more units.
+Prints the fragment, drop-ins, and source (sysvinit compat)
+of units. Each file is preceded by a comment which includes the
+file name./para
+  /listitem
+/varlistentry
 varlistentry
   termcommandset-property replaceableNAME/replaceable 
replaceableASSIGNMENT/replaceable.../command/term
 
diff --git a/src/shared/fileio.c b/src/shared/fileio.c
index 733b320..ac1b409 100644
--- a/src/shared/fileio.c
+++ b/src/shared/fileio.c
@@ -20,6 +20,7 @@
 ***/
 
 #include unistd.h
+#include sys/sendfile.h
 #include fileio.h
 #include util.h
 #include strv.h
@@ -117,6 +118,77 @@ int read_one_line_file(const char *fn, char **line) {
 return 0;
 }
 
+ssize_t sendfile_full(int out_fd, const char *fn) {
+_cleanup_fclose_ FILE *f;
+struct stat st;
+int r;
+ssize_t s;
+
+size_t n, l;
+_cleanup_free_ char *buf = NULL;
+
+assert(out_fd  0);
+assert(fn);
+
+f = fopen(fn, r);
+if (!f)
+return -errno;
+
+r = fstat(fileno(f), st);
+if (r  0)
+return -errno;
+
+s = sendfile(out_fd, fileno(f), NULL, st.st_size);
+if (s  0)
+if (errno == EINVAL || errno == ENOSYS) {
+/* continue below */
+} else
+return -errno;
+else
+return s;
+
+/* sendfile() failed, fall back to read/write */
+
+/* Safety check */
+if (st.st_size  4*1024*1024)
+return -E2BIG;
+
+n = st.st_size  0 ? st.st_size : LINE_MAX;
+l = 0;
+
+while (true) {
+char *t;
+size_t k;
+
+t = realloc(buf, n);
+if (!t)
+return -ENOMEM;
+
+buf = t;
+k = fread(buf + l, 1, n - l, f);
+
+if (k = 0) {
+if (ferror(f))
+return -errno;
+
+break;
+}
+
+l += k;
+n *= 2;
+
+/* Safety check */
+if (n  4*1024*1024)
+return -E2BIG;
+}
+
+r = write(out_fd, buf, l);
+if (r  0)
+return -errno;
+
+return (ssize_t) l;
+}
+
 int read_full_file(const char *fn, char **contents, size_t *size) {
 _cleanup_fclose_ FILE *f = NULL;
 size_t n, l;
@@ -168,7 +240,6 @@ int read_full_file(const char *fn, char **contents, size_t 
*size) {
 
 buf[l] = 0;
 *contents = buf;
-buf = NULL;
 
 if (size)
 *size = l;
diff --git a/src/shared/fileio.h b/src/shared/fileio.h
index 59e4150..06c2887 100644
--- a/src/shared/fileio.h
+++ b/src/shared/fileio.h
@@ -31,6 +31,7 @@ int write_string_file_atomic(const char *fn, const char 
*line);
 
 int read_one_line_file(const char *fn, char **line);
 int read_full_file(const char *fn, char **contents, size_t *size);
+ssize_t sendfile_full(int out_fd, const char *fn);
 
 int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
 int load_env_file(const char *fname, const char *separator, char ***l);
diff --git a/src/shared/util.c b/src/shared/util.c
index deb74c4..e6a32b9 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -5904,6 +5904,8 @@ void* greedy_realloc(void **p, size_t *allocated, size_t 
need) {
 size_t a;
   

Re: [systemd-devel] [PATCH] systemctl: add systemctl cat

2013-11-30 Thread Zbigniew Jędrzejewski-Szmek
On Sat, Nov 30, 2013 at 04:09:26PM -0800, Shawn Landden wrote:
 ---
  TODO  |   2 -
  man/systemctl.xml |   9 
  src/shared/fileio.c   |  73 ++-
  src/shared/fileio.h   |   1 +
  src/shared/util.c |   2 +
  src/systemctl/systemctl.c | 107 
 ++
  6 files changed, 191 insertions(+), 3 deletions(-)
 
 diff --git a/TODO b/TODO
 index 6ba4b31..7c6003b 100644
 --- a/TODO
 +++ b/TODO
 @@ -125,8 +125,6 @@ Features:
  
  * optimize the cgroup propagation bits, especially unit_get_members_mask(), 
 cgroup_context_get_mask()
  
 -* systemctl cat or systemctl view command or or so, that cats the 
 backing unit file of a service, plus its drop-ins and shows them in a pager
 -
Hi Shawn,
applied, I think this willl prove to be useful tool. 

I removed the part that shows the SourcePath. E.g. with mount units
generated from /proc/self/mountinfo most of the lines shown
are irrelevant. I think it would be nice to teach systemd about the
line/lines in SourcePath that the unit comes from, and then say that
this unit was generated based on  Nevertheless, I don't think it
ever makes sense to show the contents of SourcePath, since it doesn't
mix with the rest of the output, since it is in a different format.

Also, when the unit doesn't exist, nothing is printed, and no error is
shown, and return value is 0.  This doesn't seem to be correct, I
think that a check if the unit is actually known to systemd should be
added. Since we can have units without any source whatsoever, the
lack of fragment path/drop-ins cannot be considered a good enough
indication. I'm not sure what's the best way to implement this check.

Zbyszek
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH] systemctl: add systemctl cat

2013-11-28 Thread Shawn Landden
---
 TODO  |  2 -
 src/shared/fileio.c   | 73 ++-
 src/shared/fileio.h   |  1 +
 src/shared/util.c |  2 +
 src/systemctl/systemctl.c | 97 +++
 5 files changed, 172 insertions(+), 3 deletions(-)

diff --git a/TODO b/TODO
index 6ba4b31..7c6003b 100644
--- a/TODO
+++ b/TODO
@@ -125,8 +125,6 @@ Features:
 
 * optimize the cgroup propagation bits, especially unit_get_members_mask(), 
cgroup_context_get_mask()
 
-* systemctl cat or systemctl view command or or so, that cats the backing 
unit file of a service, plus its drop-ins and shows them in a pager
-
 * rfkill,backlight: we probably should run the load tools inside of the udev 
rules so that the state is properly initialized by the time other software sees 
it
 
 * tmpfiles: when applying ownership to /run/log/journal, also do this for the 
journal fails contained in it
diff --git a/src/shared/fileio.c b/src/shared/fileio.c
index 733b320..ac1b409 100644
--- a/src/shared/fileio.c
+++ b/src/shared/fileio.c
@@ -20,6 +20,7 @@
 ***/
 
 #include unistd.h
+#include sys/sendfile.h
 #include fileio.h
 #include util.h
 #include strv.h
@@ -117,6 +118,77 @@ int read_one_line_file(const char *fn, char **line) {
 return 0;
 }
 
+ssize_t sendfile_full(int out_fd, const char *fn) {
+_cleanup_fclose_ FILE *f;
+struct stat st;
+int r;
+ssize_t s;
+
+size_t n, l;
+_cleanup_free_ char *buf = NULL;
+
+assert(out_fd  0);
+assert(fn);
+
+f = fopen(fn, r);
+if (!f)
+return -errno;
+
+r = fstat(fileno(f), st);
+if (r  0)
+return -errno;
+
+s = sendfile(out_fd, fileno(f), NULL, st.st_size);
+if (s  0)
+if (errno == EINVAL || errno == ENOSYS) {
+/* continue below */
+} else
+return -errno;
+else
+return s;
+
+/* sendfile() failed, fall back to read/write */
+
+/* Safety check */
+if (st.st_size  4*1024*1024)
+return -E2BIG;
+
+n = st.st_size  0 ? st.st_size : LINE_MAX;
+l = 0;
+
+while (true) {
+char *t;
+size_t k;
+
+t = realloc(buf, n);
+if (!t)
+return -ENOMEM;
+
+buf = t;
+k = fread(buf + l, 1, n - l, f);
+
+if (k = 0) {
+if (ferror(f))
+return -errno;
+
+break;
+}
+
+l += k;
+n *= 2;
+
+/* Safety check */
+if (n  4*1024*1024)
+return -E2BIG;
+}
+
+r = write(out_fd, buf, l);
+if (r  0)
+return -errno;
+
+return (ssize_t) l;
+}
+
 int read_full_file(const char *fn, char **contents, size_t *size) {
 _cleanup_fclose_ FILE *f = NULL;
 size_t n, l;
@@ -168,7 +240,6 @@ int read_full_file(const char *fn, char **contents, size_t 
*size) {
 
 buf[l] = 0;
 *contents = buf;
-buf = NULL;
 
 if (size)
 *size = l;
diff --git a/src/shared/fileio.h b/src/shared/fileio.h
index 59e4150..06c2887 100644
--- a/src/shared/fileio.h
+++ b/src/shared/fileio.h
@@ -31,6 +31,7 @@ int write_string_file_atomic(const char *fn, const char 
*line);
 
 int read_one_line_file(const char *fn, char **line);
 int read_full_file(const char *fn, char **contents, size_t *size);
+ssize_t sendfile_full(int out_fd, const char *fn);
 
 int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
 int load_env_file(const char *fname, const char *separator, char ***l);
diff --git a/src/shared/util.c b/src/shared/util.c
index deb74c4..e6a32b9 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -5904,6 +5904,8 @@ void* greedy_realloc(void **p, size_t *allocated, size_t 
need) {
 size_t a;
 void *q;
 
+assert(allocated);
+
 if (*allocated = need)
 return *p;
 
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 6cb7a82..633c07d 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -3665,6 +3665,101 @@ static int show_all(
 return 0;
 }
 
+static int cat(sd_bus *bus, char **args) {
+int r = 0;
+char **name;
+
+_cleanup_free_ char *unit = NULL, *n = NULL;
+
+assert(bus);
+assert(args);
+
+pager_open_if_enabled();
+
+STRV_FOREACH(name, args+1) {
+_cleanup_free_ char *fragment_path = NULL;
+_cleanup_strv_free_ char **dropin_paths = NULL;
+sd_bus_error error;
+FILE *stdout;
+char **path;
+
+n = unit_name_mangle(*name);

[systemd-devel] [PATCH] systemctl: add systemctl cat

2013-11-28 Thread Shawn Landden
v3: log_warning() inserts a trailing newline
---
 TODO  |  2 -
 src/shared/fileio.c   | 73 ++-
 src/shared/fileio.h   |  1 +
 src/shared/util.c |  2 +
 src/systemctl/systemctl.c | 97 +++
 5 files changed, 172 insertions(+), 3 deletions(-)

diff --git a/TODO b/TODO
index 6ba4b31..7c6003b 100644
--- a/TODO
+++ b/TODO
@@ -125,8 +125,6 @@ Features:
 
 * optimize the cgroup propagation bits, especially unit_get_members_mask(), 
cgroup_context_get_mask()
 
-* systemctl cat or systemctl view command or or so, that cats the backing 
unit file of a service, plus its drop-ins and shows them in a pager
-
 * rfkill,backlight: we probably should run the load tools inside of the udev 
rules so that the state is properly initialized by the time other software sees 
it
 
 * tmpfiles: when applying ownership to /run/log/journal, also do this for the 
journal fails contained in it
diff --git a/src/shared/fileio.c b/src/shared/fileio.c
index 733b320..ac1b409 100644
--- a/src/shared/fileio.c
+++ b/src/shared/fileio.c
@@ -20,6 +20,7 @@
 ***/
 
 #include unistd.h
+#include sys/sendfile.h
 #include fileio.h
 #include util.h
 #include strv.h
@@ -117,6 +118,77 @@ int read_one_line_file(const char *fn, char **line) {
 return 0;
 }
 
+ssize_t sendfile_full(int out_fd, const char *fn) {
+_cleanup_fclose_ FILE *f;
+struct stat st;
+int r;
+ssize_t s;
+
+size_t n, l;
+_cleanup_free_ char *buf = NULL;
+
+assert(out_fd  0);
+assert(fn);
+
+f = fopen(fn, r);
+if (!f)
+return -errno;
+
+r = fstat(fileno(f), st);
+if (r  0)
+return -errno;
+
+s = sendfile(out_fd, fileno(f), NULL, st.st_size);
+if (s  0)
+if (errno == EINVAL || errno == ENOSYS) {
+/* continue below */
+} else
+return -errno;
+else
+return s;
+
+/* sendfile() failed, fall back to read/write */
+
+/* Safety check */
+if (st.st_size  4*1024*1024)
+return -E2BIG;
+
+n = st.st_size  0 ? st.st_size : LINE_MAX;
+l = 0;
+
+while (true) {
+char *t;
+size_t k;
+
+t = realloc(buf, n);
+if (!t)
+return -ENOMEM;
+
+buf = t;
+k = fread(buf + l, 1, n - l, f);
+
+if (k = 0) {
+if (ferror(f))
+return -errno;
+
+break;
+}
+
+l += k;
+n *= 2;
+
+/* Safety check */
+if (n  4*1024*1024)
+return -E2BIG;
+}
+
+r = write(out_fd, buf, l);
+if (r  0)
+return -errno;
+
+return (ssize_t) l;
+}
+
 int read_full_file(const char *fn, char **contents, size_t *size) {
 _cleanup_fclose_ FILE *f = NULL;
 size_t n, l;
@@ -168,7 +240,6 @@ int read_full_file(const char *fn, char **contents, size_t 
*size) {
 
 buf[l] = 0;
 *contents = buf;
-buf = NULL;
 
 if (size)
 *size = l;
diff --git a/src/shared/fileio.h b/src/shared/fileio.h
index 59e4150..06c2887 100644
--- a/src/shared/fileio.h
+++ b/src/shared/fileio.h
@@ -31,6 +31,7 @@ int write_string_file_atomic(const char *fn, const char 
*line);
 
 int read_one_line_file(const char *fn, char **line);
 int read_full_file(const char *fn, char **contents, size_t *size);
+ssize_t sendfile_full(int out_fd, const char *fn);
 
 int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
 int load_env_file(const char *fname, const char *separator, char ***l);
diff --git a/src/shared/util.c b/src/shared/util.c
index deb74c4..e6a32b9 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -5904,6 +5904,8 @@ void* greedy_realloc(void **p, size_t *allocated, size_t 
need) {
 size_t a;
 void *q;
 
+assert(allocated);
+
 if (*allocated = need)
 return *p;
 
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 6cb7a82..284020c 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -3665,6 +3665,101 @@ static int show_all(
 return 0;
 }
 
+static int cat(sd_bus *bus, char **args) {
+int r = 0;
+char **name;
+
+_cleanup_free_ char *unit = NULL, *n = NULL;
+
+assert(bus);
+assert(args);
+
+pager_open_if_enabled();
+
+STRV_FOREACH(name, args+1) {
+_cleanup_free_ char *fragment_path = NULL;
+_cleanup_strv_free_ char **dropin_paths = NULL;
+sd_bus_error error;
+FILE *stdout;
+char **path;
+

Re: [systemd-devel] [PATCH] systemctl: add systemctl cat

2013-11-28 Thread Zbigniew Jędrzejewski-Szmek
On Thu, Nov 28, 2013 at 10:34:10AM -0800, Shawn Landden wrote:
 v3: log_warning() inserts a trailing newline
 ---
  TODO  |  2 -
  src/shared/fileio.c   | 73 ++-
  src/shared/fileio.h   |  1 +
  src/shared/util.c |  2 +
  src/systemctl/systemctl.c | 97 
 +++
  5 files changed, 172 insertions(+), 3 deletions(-)

Hm, this seems to still need some more work:

% build/systemctl cat session-1.scope
Failed to cat : No such file or directory
# 

session-1.scope has no fragment path, just an override:
% build/systemctl show session-1.scope|grep -E 'Frag|Drop'
DropInPaths=/run/systemd/system/session-1.scope.d/90-After-systemd-user-sessions\x2eservice.conf
 /run/systemd/system/session-1.scope.d/90-Description.conf 
/run/systemd/system/session-1.scope.d/90-KillMode.conf 
/run/systemd/system/session-1.scope.d/90-SendSIGHUP.conf 
/run/systemd/system/session-1.scope.d/90-Slice.conf 
/run/systemd/system/session-1.scope.d/90-TimeoutStopUSec.conf

Also, manpage should be updated and shell completion scripts
would be nice to update too.

Zbyszek
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel