1 /* Copyright 1986-1992 Emmet P. Gray.
2 * Copyright 1996-2002,2007,2009 Alain Knaff.
3 * This file is part of mtools.
4 *
5 * Mtools is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * Mtools is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * Do filename expansion with the shell.
19 */
20
21 #include "sysincludes.h"
22 #include "mtools.h"
23
24 #ifndef OS_mingw32msvc
safePopenOut(const char ** command,char * output,size_t len)25 ssize_t safePopenOut(const char **command, char *output, size_t len)
26 {
27 int pipefd[2];
28 pid_t pid;
29 int status;
30 ssize_t last;
31
32 if(pipe(pipefd)) {
33 return -2;
34 }
35 switch((pid=fork())){
36 case -1:
37 return -2;
38 case 0: /* the son */
39 close(pipefd[0]);
40 destroy_privs();
41 close(1);
42 close(2); /* avoid nasty error messages on stderr */
43 if(dup(pipefd[1]) < 0) {
44 perror("Dup error");
45 exit(1);
46 }
47 close(pipefd[1]);
48 execvp(command[0], (char**)(command+1));
49 exit(1);
50 default:
51 close(pipefd[1]);
52 break;
53 }
54 last=read(pipefd[0], output, len);
55 kill(pid,9);
56 wait(&status);
57 if(last<0) {
58 return -1;
59 }
60 return last;
61 }
62 #endif
63
64
expand(const char * input,char * ans)65 const char *expand(const char *input, char *ans)
66 {
67 #ifndef OS_mingw32msvc
68 ssize_t last;
69 char buf[256];
70 const char *command[] = { "/bin/sh", "sh", "-c", 0, 0 };
71
72 ans[EXPAND_BUF-1]='\0';
73
74 if (input == NULL)
75 return(NULL);
76 if (*input == '\0')
77 return("");
78 /* any thing to expand? */
79 if (!strpbrk(input, "$*(){}[]\\?`~")) {
80 strncpy(ans, input, EXPAND_BUF-1);
81 return(ans);
82 }
83 /* popen an echo */
84 #ifdef HAVE_SNPRINTF
85 snprintf(buf, 255, "echo %s", input);
86 #else
87 sprintf(buf, "echo %s", input);
88 #endif
89
90 command[3]=buf;
91 last=safePopenOut(command, ans, EXPAND_BUF-1);
92 if(last<0) {
93 perror("Pipe read error");
94 exit(1);
95 }
96 if(last)
97 ans[last-1] = '\0';
98 else
99 strncpy(ans, input, EXPAND_BUF-1);
100 return ans;
101 #else
102 strncpy(ans, input, EXPAND_BUF-1);
103 ans[EXPAND_BUF-1]='\0';
104 return ans;
105 #endif
106 }
107