]> mj.ucw.cz Git - libucw.git/blob - ucw/runcmd.c
Mainloop: Avoid polling for an empty set of events
[libucw.git] / ucw / runcmd.c
1 /*
2  *      UCW 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 <ucw/lib.h>
11 #include <ucw/process.h>
12
13 #include <stdlib.h>
14 #include <string.h>
15 #include <alloca.h>
16 #include <unistd.h>
17 #include <sys/wait.h>
18
19 void NONRET
20 exec_command_v(const char *cmd, va_list args)
21 {
22   va_list cargs;
23   va_copy(cargs, args);
24   int cnt = 2;
25   char *arg;
26   while (arg = va_arg(cargs, char *))
27     cnt++;
28   va_end(cargs);
29   char **argv = alloca(sizeof(char *) * cnt);
30   argv[0] = (char *)cmd;
31   cnt = 1;
32   va_copy(cargs, args);
33   while (arg = va_arg(cargs, char *))
34     argv[cnt++] = arg;
35   va_end(cargs);
36   argv[cnt] = NULL;
37   execv(cmd, argv);
38   char echo[256];
39   echo_command_v(echo, sizeof(echo), cmd, args);
40   msg(L_ERROR, "Cannot execute %s: %m", echo);
41   exit(255);
42 }
43
44 int
45 run_command_v(const char *cmd, va_list args)
46 {
47   pid_t p = fork();
48   if (p < 0)
49     {
50       msg(L_ERROR, "fork() failed: %m");
51       return 0;
52     }
53   else if (!p)
54     exec_command_v(cmd, args);
55   else
56     {
57       int stat;
58       char status_msg[EXIT_STATUS_MSG_SIZE];
59       p = waitpid(p, &stat, 0);
60       if (p < 0)
61         die("waitpid() failed: %m");
62       if (format_exit_status(status_msg, stat))
63         {
64           char echo[256];
65           echo_command_v(echo, sizeof(echo), cmd, args);
66           msg(L_ERROR, "`%s' failed: %s", echo, status_msg);
67           return 0;
68         }
69       return 1;
70     }
71 }
72
73 void
74 echo_command_v(char *buf, int size, const char *cmd, va_list args)
75 {
76   char *limit = buf + size - 4;
77   char *p = buf;
78   const char *arg = cmd;
79   do
80     {
81       int l = strlen(arg);
82       if (p != buf && p < limit)
83         *p++ = ' ';
84       if (p+l > limit)
85         {
86           memcpy(p, arg, limit-p);
87           strcpy(limit, "...");
88           return;
89         }
90       memcpy(p, arg, l);
91       p += l;
92     }
93   while (arg = va_arg(args, char *));
94   *p = 0;
95 }
96
97 int
98 run_command(const char *cmd, ...)
99 {
100   va_list args;
101   va_start(args, cmd);
102   int e = run_command_v(cmd, args);
103   va_end(args);
104   return e;
105 }
106
107 void NONRET
108 exec_command(const char *cmd, ...)
109 {
110   va_list args;
111   va_start(args, cmd);
112   exec_command_v(cmd, args);
113 }
114
115 void
116 echo_command(char *buf, int len, const char *cmd, ...)
117 {
118   va_list args;
119   va_start(args, cmd);
120   echo_command_v(buf, len, cmd, args);
121   va_end(args);
122 }
123
124 #ifdef TEST
125
126 int main(void)
127 {
128   char msg[1024];
129   echo_command(msg, sizeof(msg), "/bin/echo", "datel", "strakapoud", NULL);
130   msg(L_INFO, "Running <%s>", msg);
131   run_command("/bin/echo", "datel", "strakapoud", NULL);
132   return 0;
133 }
134
135 #endif