1 /*
2 ** 1998-09-18 - Maintain an instance of the 'file' external command as a child process, and
3 ** feed it typing requests when necessary. We will only start 'file' ONCE per
4 ** entire gentoo session (typically), thus amortizing its startup costs over
5 ** a very (?) long time. The aim of all this is hopefully to make typing using
6 ** the file rules cheaper.
7 ** 2002-01-03 - It's a while later, the file command on your system might now have the -n
8 ** option which causes it to flush its output, and enables this module to do
9 ** it's thing in the way intended. Used by cmd_info.c.
10 */
11
12 #include "gentoo.h"
13
14 #include <fcntl.h>
15 #include <ctype.h>
16 #include <stdlib.h>
17 #include <signal.h>
18 #include <unistd.h>
19
20 #include "dialog.h"
21 #include "errors.h"
22 #include "children.h"
23 #include "file.h"
24
25 /* ----------------------------------------------------------------------------------------- */
26
27 static struct {
28 gint file_in; /* Writing end of pipe connected to command's stdin. */
29 gint file_out; /* Reading end of pipe connected to command's stdout. */
30 } file_info = { -1, -1 };
31
32 /* ----------------------------------------------------------------------------------------- */
33
start_file(MainInfo * min,const gchar * cmd)34 static void start_file(MainInfo *min, const gchar *cmd)
35 {
36 gchar *argv[] = { "file", "file", "-n", "-f", "-", NULL };
37 GPid child;
38 GError *err = NULL;
39
40 if(g_spawn_async_with_pipes(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &child, &file_info.file_in, &file_info.file_out, NULL, &err))
41 {
42 chd_register("file", child, CGF_RUNINBG, 0);
43 }
44 else
45 {
46 gchar buf[1024];
47
48 g_snprintf(buf, sizeof buf, "Couldn't run the 'file' command:\n%s", err->message);
49 dlg_dialog_async_new_error(buf);
50 g_error_free(err);
51 }
52 }
53
54 /* ----------------------------------------------------------------------------------------- */
55
56 /* 1998-09-18 - Run 'file' on the supplied file name, and return a pointer to its result line.
57 ** The returned string will be the result of 'file', minus the header and the
58 ** trailing newline. The returned string is static, and only valid up until the
59 ** next call to this function. If the execution fails, NULL is returned.
60 */
fle_file(MainInfo * min,const gchar * name)61 const gchar * fle_file(MainInfo *min, const gchar *name)
62 {
63 if(file_info.file_in < 0)
64 start_file(min, "file");
65 if(file_info.file_in > 0) /* File command running? */
66 {
67 static gchar resp[PATH_MAX + 256];
68 gchar line[PATH_MAX + 32];
69 gint len, got;
70 fd_set fds_read;
71 struct timeval to;
72
73 len = g_snprintf(line, sizeof line, "%s\n", name);
74 if(write(file_info.file_in, line, len) != len)
75 {
76 perror("Write to pipe");
77 return NULL;
78 }
79 FD_ZERO(&fds_read);
80 FD_SET(file_info.file_out, &fds_read);
81 to.tv_sec = 1U;
82 to.tv_usec = 0U;
83 if((select(file_info.file_out + 1, &fds_read, NULL, NULL, &to)) > 0)
84 {
85 if(FD_ISSET(file_info.file_out, &fds_read))
86 {
87 if((got = read(file_info.file_out, resp, sizeof resp - 1)) > 0)
88 {
89 const gchar *cp;
90
91 resp[got - 1] = '\0';
92 if((cp = strrchr(resp, ':')) != NULL)
93 {
94 cp++;
95 while(*cp && isspace((guchar) *cp))
96 cp++;
97 return cp;
98 }
99 }
100 }
101 }
102 }
103 return NULL;
104 }
105