I'm not sure if we can add a test for this one. Writing to people's
home directories doesn't seem very nice.
I'm guessing 'pinky' doesn't do getenv ("HOME") because 'finger'
doesn't?
$ env HOME=/ finger -l collin | tail -n 2 && ls /.plan
Plan:
abc
ls: cannot access '/.plan': No such file or directory
-- 8< --
In some cases 'pinky' could run forever until interrupted:
$ ln -s /dev/zero ~/.plan
$ ln -s /dev/zero ~/.project
$ timeout -v 5 pinky -l collin > /dev/full
timeout: sending signal TERM to command ‘pinky’
After this change it will exit upon failing to write to standard output:
$ timeout -v 5 ./src/pinky -l collin > /dev/full
pinky: write error: No space left on device
* src/pinky.c: Include fadvise.h, filenamecat.h, full-write.h, and
ioblksize.h.
(cat_file): New function.
(print_entry): Check if standard output has it's error flag set after
printing a user entry.
(print_long_entry): Likewise. Use the new cat_file function.
* NEWS: Mention the improvement.
---
NEWS | 3 ++
src/pinky.c | 83 +++++++++++++++++++++++++----------------------------
2 files changed, 42 insertions(+), 44 deletions(-)
diff --git a/NEWS b/NEWS
index 127d70ae0..b283b6908 100644
--- a/NEWS
+++ b/NEWS
@@ -48,6 +48,9 @@ GNU coreutils NEWS -*-
outline -*-
csplit, ls, and sort, now handle a more complete set of terminating signals.
+ 'pinky' will now exit immediately upon receiving a write error, which is
+ significant when reading large plan or project files.
+
'timeout' on Linux will always terminate the child in the case where the
timeout process itself dies, like when it receives a KILL signal for example.
diff --git a/src/pinky.c b/src/pinky.c
index b49096b35..6414446bd 100644
--- a/src/pinky.c
+++ b/src/pinky.c
@@ -26,7 +26,11 @@
#include "system.h"
#include "canon-host.h"
+#include "fadvise.h"
+#include "filenamecat.h"
+#include "full-write.h"
#include "hard-locale.h"
+#include "ioblksize.h"
#include "readutmp.h"
/* The official name of this program (e.g., no 'g' prefix). */
@@ -309,6 +313,36 @@ print_entry (STRUCT_UTMP const *utmp_ent)
#endif
putchar ('\n');
+
+ if (ferror (stdout))
+ write_error ();
+}
+
+/* If FILE exists in HOME, print it to standard output, preceded by HEADER. */
+
+static void
+cat_file (char const *header, char const *home, char const *file)
+{
+ char *full_name = file_name_concat (home, file, nullptr);
+ int fd = open (full_name, O_RDONLY);
+
+ if (0 <= fd)
+ {
+ idx_t header_len = strlen (header);
+ if (write (STDOUT_FILENO, header, header_len) != header_len)
+ write_error ();
+
+ fdadvise (fd, 0, 0, FADVISE_SEQUENTIAL);
+
+ char buf[IO_BUFSIZE];
+ for (ssize_t bytes_read; 0 < (bytes_read = read (fd, buf, sizeof buf));)
+ if (full_write (STDOUT_FILENO, buf, bytes_read) != bytes_read)
+ write_error ();
+
+ close (fd);
+ }
+
+ free (full_name);
}
/* Display a verbose line of information about UTMP_ENT. */
@@ -355,54 +389,15 @@ print_long_entry (const char name[])
}
if (include_project)
- {
- FILE *stream;
- char buf[1024];
- char const *const baseproject = "/.project";
- char *const project =
- xmalloc (strlen (pw->pw_dir) + strlen (baseproject) + 1);
- stpcpy (stpcpy (project, pw->pw_dir), baseproject);
-
- stream = fopen (project, "r");
- if (stream)
- {
- size_t bytes;
-
- printf (_("Project: "));
-
- while ((bytes = fread (buf, 1, sizeof (buf), stream)) > 0)
- fwrite (buf, 1, bytes, stdout);
- fclose (stream);
- }
-
- free (project);
- }
+ cat_file (_("Project: "), pw->pw_dir, ".project");
if (include_plan)
- {
- FILE *stream;
- char buf[1024];
- char const *const baseplan = "/.plan";
- char *const plan =
- xmalloc (strlen (pw->pw_dir) + strlen (baseplan) + 1);
- stpcpy (stpcpy (plan, pw->pw_dir), baseplan);
-
- stream = fopen (plan, "r");
- if (stream)
- {
- size_t bytes;
-
- printf (_("Plan:\n"));
-
- while ((bytes = fread (buf, 1, sizeof (buf), stream)) > 0)
- fwrite (buf, 1, bytes, stdout);
- fclose (stream);
- }
-
- free (plan);
- }
+ cat_file (_("Plan:\n"), pw->pw_dir, ".plan");
putchar ('\n');
+
+ if (ferror (stdout))
+ write_error ();
}
/* Print the username of each valid entry and the number of valid entries
--
2.52.0