mirror of
https://https.git.savannah.gnu.org/git/coreutils.git
synced 2026-01-26 15:29:07 +00:00
pinky: promptly diagnose write errors
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.
This commit is contained in:
parent
796b8d1a66
commit
3c405ae0b6
3
NEWS
3
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.
|
||||
|
||||
|
||||
83
src/pinky.c
83
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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user