]> mj.ucw.cz Git - libucw.git/blob - lib/runcmd.c
actually, the number of runs is halved during each pass, so take it into
[libucw.git] / lib / runcmd.c
1 /*
2  *      Sherlock Library -- Running of Commands
3  *
4  *      (c) 2004 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include "lib/lib.h"
11
12 #include <stdlib.h>
13 #include <string.h>
14 #include <alloca.h>
15 #include <unistd.h>
16 #include <sys/wait.h>
17
18 void NONRET
19 exec_command_v(byte *cmd, va_list args)
20 {
21   va_list cargs = args;
22   int cnt = 2;
23   byte *arg;
24   while (arg = va_arg(cargs, byte *))
25     cnt++;
26   char **argv = alloca(sizeof(byte *) * cnt);
27   argv[0] = cmd;
28   cnt = 1;
29   cargs = args;
30   while (arg = va_arg(cargs, byte *))
31     argv[cnt++] = arg;
32   argv[cnt] = NULL;
33   execv(cmd, argv);
34   byte echo[256];
35   echo_command_v(echo, sizeof(echo), cmd, args);
36   log(L_ERROR, "Cannot execute %s: %m", echo);
37   exit(255);
38 }
39
40 int
41 run_command_v(byte *cmd, va_list args)
42 {
43   pid_t p = fork();
44   if (p < 0)
45     {
46       log(L_ERROR, "fork() failed: %m");
47       return 0;
48     }
49   else if (!p)
50     exec_command_v(cmd, args);
51   else
52     {
53       int stat;
54       byte msg[EXIT_STATUS_MSG_SIZE];
55       p = waitpid(p, &stat, 0);
56       if (p < 0)
57         die("waitpid() failed: %m");
58       if (format_exit_status(msg, stat))
59         {
60           byte echo[256];
61           echo_command_v(echo, sizeof(echo), cmd, args);
62           log(L_ERROR, "`%s' failed: %s", echo, msg);
63           return 0;
64         }
65       return 1;
66     }
67 }
68
69 void
70 echo_command_v(byte *buf, int size, byte *cmd, va_list args)
71 {
72   byte *limit = buf + size - 4;
73   byte *p = buf;
74   byte *arg = cmd;
75   va_list cargs = args;
76   do
77     {
78       int l = strlen(arg);
79       if (p != buf && p < limit)
80         *p++ = ' ';
81       if (p+l > limit)
82         {
83           memcpy(p, arg, limit-p);
84           strcpy(limit, "...");
85           return;
86         }
87       memcpy(p, arg, l);
88       p += l;
89     }
90   while (arg = va_arg(cargs, byte *));
91   *p = 0;
92 }
93
94 int
95 run_command(byte *cmd, ...)
96 {
97   va_list args;
98   va_start(args, cmd);
99   int e = run_command_v(cmd, args);
100   va_end(args);
101   return e;
102 }
103
104 void NONRET
105 exec_command(byte *cmd, ...)
106 {
107   va_list args;
108   va_start(args, cmd);
109   exec_command_v(cmd, args);
110 }
111
112 void
113 echo_command(byte *buf, int len, byte *cmd, ...)
114 {
115   va_list args;
116   va_start(args, cmd);
117   echo_command_v(buf, len, cmd, args);
118   va_end(args);
119 }
120
121 #ifdef TEST
122
123 int main(void)
124 {
125   byte msg[1024];
126   echo_command(msg, sizeof(msg), "/bin/echo", "datel", "strakapoud", NULL);
127   log(L_INFO, "Running <%s>", msg);
128   run_command("/bin/echo", "datel", "strakapoud", NULL);
129   return 0;
130 }
131
132 #endif