Initial import package mtools: Programs for accessing MS-DOS disks without mounting...
[profile/ivi/mtools.git] / expand.c
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 #define EXPAND_BUF      2048
22
23 #include "sysincludes.h"
24 #include "mtools.h"
25
26 #ifndef OS_mingw32msvc
27 int safePopenOut(const char **command, char *output, int len)
28 {
29         int pipefd[2];
30         pid_t pid;
31         int status;
32         int last;
33
34         if(pipe(pipefd)) {
35                 return -2;
36         }
37         switch((pid=fork())){
38                 case -1:
39                         return -2;
40                 case 0: /* the son */
41                         close(pipefd[0]);
42                         destroy_privs();
43                         close(1);
44                         close(2); /* avoid nasty error messages on stderr */
45                         if(dup(pipefd[1]) < 0) {
46                                 perror("Dup error");
47                                 exit(1);
48                         }
49                         close(pipefd[1]);
50                         execvp(command[0], (char**)(command+1));
51                         exit(1);
52                 default:
53                         close(pipefd[1]);
54                         break;
55         }
56         last=read(pipefd[0], output, len);
57         kill(pid,9);
58         wait(&status);
59         if(last<0) {
60                 return -1;
61         }
62         return last;
63 }
64 #endif
65
66
67 const char *expand(const char *input, char *ans)
68 {
69 #ifndef OS_mingw32msvc
70         int last;
71         char buf[256];
72         const char *command[] = { "/bin/sh", "sh", "-c", 0, 0 };
73
74         ans[EXPAND_BUF-1]='\0';
75
76         if (input == NULL)
77                 return(NULL);
78         if (*input == '\0')
79                 return("");
80                                         /* any thing to expand? */
81         if (!strpbrk(input, "$*(){}[]\\?`~")) {
82                 strncpy(ans, input, EXPAND_BUF-1);
83                 return(ans);
84         }
85                                         /* popen an echo */
86 #ifdef HAVE_SNPRINTF
87         snprintf(buf, 255, "echo %s", input);
88 #else
89         sprintf(buf, "echo %s", input);
90 #endif
91
92         command[3]=buf;
93         last=safePopenOut(command, ans, EXPAND_BUF-1);
94         if(last<0) {
95                 perror("Pipe read error");
96                 exit(1);
97         }
98         if(last)
99                 ans[last-1] = '\0';
100         else
101                 strncpy(ans, input, EXPAND_BUF-1);
102         return ans;
103 #else
104         strncpy(ans, input, EXPAND_BUF-1);
105         ans[EXPAND_BUF-1]='\0';
106         return ans;
107 #endif
108 }