1 /*
2  * $Id$
3  *
4  * Copyright (C) 2003 ETC s.r.o.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19  * 02111-1307, USA.
20  *
21  * Written by Marcel Telka <marcel@telka.sk>, 2003.
22  * shell.c added by djf
23  */
24 
25 #include <sysdep.h>
26 
27 #include <sys/types.h>
28 #include <unistd.h>
29 
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 
34 #include <urjtag/error.h>
35 #include <urjtag/cmd.h>
36 
37 #include "cmd.h"
38 
39 static int
cmd_shell_run(urj_chain_t * chain,char * params[])40 cmd_shell_run (urj_chain_t *chain, char *params[])
41 {
42     int i, n = urj_cmd_params (params);
43     size_t len;
44     char *shell_cmd;
45 
46     if ((n = urj_cmd_params (params)) == 1)
47     {
48         urj_error_set (URJ_ERROR_SYNTAX,
49                        "%s: #parameters should be >= %d, not %d",
50                        params[0], 2, urj_cmd_params (params));
51         return URJ_STATUS_FAIL;
52     }
53 
54     /* I must apologize to everyone who knows what they are doing for
55      * the following. If you can pass a shell argument past strtok the
56      * please fix this.
57      */
58     /* The problem is the parser which splits commands into params[]
59      * and doesn't allow quoting. So we concatenate the params[] here
60      * with single spaces, although the original might have different
61      * whitespace (more than one space, tabs, ...) - kawk */
62 
63     for (i = 1, len = 0; i < n; i++)
64         len += (1 + strlen (params[i]));
65 
66     shell_cmd = malloc (len);
67     if (shell_cmd == NULL)
68     {
69         urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "malloc(%zu) fails",
70                        len);
71         return URJ_STATUS_FAIL;
72     }
73 
74     strcpy (shell_cmd, params[1]);
75     for (i = 2; i < n; i++)
76     {
77         strcat (shell_cmd, " ");
78         strcat (shell_cmd, params[i]);
79     }
80     urj_log (URJ_LOG_LEVEL_NORMAL, "Executing '%s'\n", shell_cmd);
81 
82     i = system (shell_cmd);
83     free (shell_cmd);
84 
85     if (i)
86         urj_log (URJ_LOG_LEVEL_NORMAL, "shell returned %i\n", i);
87 
88     return URJ_STATUS_OK;
89 }
90 
91 static void
cmd_shell_complete(urj_chain_t * chain,char *** matches,size_t * match_cnt,char * const * tokens,const char * text,size_t text_len,size_t token_point)92 cmd_shell_complete (urj_chain_t *chain, char ***matches, size_t *match_cnt,
93                     char * const *tokens, const char *text, size_t text_len,
94                     size_t token_point)
95 {
96     /* XXX: Should first token complete via $PATH ? */
97     urj_completion_mayben_add_file (matches, match_cnt, text, text_len, false);
98 }
99 
100 static void
cmd_shell_help(void)101 cmd_shell_help (void)
102 {
103     urj_log (URJ_LOG_LEVEL_NORMAL,
104              _("Usage: %s CMD\n"
105                "Shell out to the OS for a command.\n"
106                "\n" "CMD OS Shell Command\n"),
107              "shell");
108 }
109 
110 const urj_cmd_t urj_cmd_shell = {
111     "shell",
112     N_("run a shell command"),
113     cmd_shell_help,
114     cmd_shell_run,
115     cmd_shell_complete,
116 };
117