1 /*****************************************************************************/
2 /* */
3 /* (C) Copyright 1994-1996 Alberto Pasquale */
4 /* Portions (C) Copyright 1999 Per Lundberg */
5 /* */
6 /* A L L R I G H T S R E S E R V E D */
7 /* */
8 /*****************************************************************************/
9 /* */
10 /* How to contact the author: Alberto Pasquale of 2:332/504@fidonet */
11 /* Viale Verdi 106 */
12 /* 41100 Modena */
13 /* Italy */
14 /* */
15 /*****************************************************************************/
16
17 #include "apgenlib.hpp"
18 #include <string.h>
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #if !defined (__FreeBSD__)
22 # include <malloc.h>
23 #endif
24
StrQTok(char * & c)25 static char *StrQTok (char *&c)
26 {
27 char *start;
28
29 c += strspn (c, " \t\n"); // skip blank
30 if (*c == '\0')
31 return NULL; // return NULL if no token available
32
33 start = c;
34
35 BOOL InQuotes = FALSE;
36 BOOL TokEnd = FALSE;
37
38 while ((*c) && !TokEnd) {
39 switch (*c) {
40 case ' ':
41 case '\t':
42 case '\n':
43 if (InQuotes)
44 c ++;
45 else
46 TokEnd = TRUE;
47 break;
48 case '"':
49 InQuotes = !InQuotes;
50 c ++;
51 break;
52 default:
53 c ++;
54 break;
55 }
56 }
57
58 if (*c) {
59 *c = '\0'; // terminate token
60 c++;
61 c += strspn (c, " \t\n"); // advance c to next token or terminating NULL
62 }
63
64 return start;
65 }
66
67
68 #define _Quotes_Delimited_ TRUE
69
70
71 // Builds command line, one space between tokens, double trailing zero.
72 // Triple trailing zero in case of empty args string.
73 // Just to be sure, a triple zero is always appended.
74
BuildCmd(char * cmdline,uint cmdlinesize,int nargs,char const * args[],BOOL delimited=FALSE)75 static void BuildCmd (char *cmdline, uint cmdlinesize, int nargs,
76 char const *args[], BOOL delimited = FALSE)
77 {
78 char *p = cmdline;
79 *p = '\0'; // init empty command line string
80
81 if (nargs == 0) // nothing to do
82 return;
83
84 if (args[0][0] == '\0') // empty command name
85 return;
86
87 cmdlinesize -= 3; // leave space for trailing zeros
88
89 if (strlen (args[0]) > cmdlinesize) // too long command name
90 return;
91
92 p = fl_stpcpy (p, args[0]); // command name
93
94 for (int i = 1; i < nargs; i++) {
95 if (((p - cmdline) + 1 + strlen (args[i]) + (delimited ? 2 : 0)) > cmdlinesize)
96 break;
97
98 *p++ = ' ';
99
100 if (delimited)
101 *p++ = '"';
102 p = fl_stpcpy (p, args[i]);
103 if (delimited)
104 *p++ = '"';
105 }
106
107 *p++ = '\0'; // assure double trailing zero in any case
108 *p++ = '\0'; // double trailing zero
109 *p++ = '\0';
110 }
111
RunCmd(const char * cmd,RCShow rcs,const char * prmlst,...)112 int RunCmd (const char *cmd, RCShow rcs, const char *prmlst, ...)
113 {
114 #define MAXARGS 21
115 #define MAXSUBS 10
116
117 char const *subs[MAXSUBS];
118 char const *args[MAXARGS];
119 int j;
120
121 if (!cmd)
122 return -1;
123
124 int nsubs = __min (strlen (prmlst), MAXSUBS);
125
126 va_list vargs;
127 va_start (vargs, prmlst);
128 for (j = 0; j < nsubs; j++) // init prm substitutions
129 subs[j] = va_arg (vargs, char *);
130 va_end (vargs);
131
132 char *workline = newcpy (cmd);
133 char *c = workline;
134
135 int i = 0;
136 args[i++] = StrQTok (c); // Prg name
137
138 if (args[0] == NULL) {
139 if (rcs)
140 rcs (RC_EMPTY);
141 delete[] workline;
142 return -1;
143 }
144
145 while (i < MAXARGS-1) {
146 char *arg = StrQTok (c);
147 if (!arg)
148 break;
149 if ((strlen (arg) == 2) && (arg[0] == '%')) { // can be a substitution parameter
150 BOOL found = FALSE;
151 for (j = 0; j < nsubs; j ++)
152 if (arg[1] == prmlst[j]) {
153 args[i++] = subs[j];
154 found = TRUE;
155 break;
156 }
157 if (found)
158 continue;
159 }
160 args[i++] = arg;
161 }
162
163 int nargs = i;
164 args[i] = NULL; // necessary for spawn function
165
166 char *rescmdline = new char[4 * PATH_MAX];
167 BuildCmd (rescmdline, 4 * PATH_MAX, nargs, args);
168 if (rcs)
169 rcs (RC_DOING, rescmdline);
170
171 int code = system (rescmdline);
172
173 delete[] rescmdline;
174 delete[] workline;
175
176 if (rcs)
177 rcs (RC_EXIT, code);
178
179 return code;
180
181 #undef MAXSUBS
182 #undef MAXARGS
183 }
184