~ubuntu-branches/ubuntu/trusty/maloc/trusty-proposed

« back to all changes in this revision

Viewing changes to src/vsh/vpup.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Banck
  • Date: 2006-06-29 15:21:06 UTC
  • Revision ID: james.westby@ubuntu.com-20060629152106-kyqdw6qlc3vmqum3
Tags: upstream-0.2
ImportĀ upstreamĀ versionĀ 0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ***************************************************************************
 
3
 * MALOC = < Minimal Abstraction Layer for Object-oriented C >
 
4
 * Copyright (C) 1994--2000  Michael Holst
 
5
 * 
 
6
 * This program is free software; you can redistribute it and/or modify it
 
7
 * under the terms of the GNU General Public License as published by the
 
8
 * Free Software Foundation; either version 2 of the License, or (at your
 
9
 * 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.
 
14
 * See the GNU General Public License for more details.
 
15
 * 
 
16
 * You should have received a copy of the GNU General Public License along
 
17
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
18
 * 675 Mass Ave, Cambridge, MA 02139, USA.
 
19
 * 
 
20
 * rcsid="$Id: vpup.c,v 1.8 2002/10/01 21:29:45 mholst Exp $"
 
21
 * ***************************************************************************
 
22
 */
 
23
 
 
24
/*
 
25
 * ***************************************************************************
 
26
 * File:     vpup.c
 
27
 *
 
28
 * Purpose:  Handle the following useful features of a shell like bash:
 
29
 *
 
30
 *               (1) input/output redirection from/into files
 
31
 *               (2) pipes of arbitrary length and complexity
 
32
 *               (3) execv/execvp of the actual user commands
 
33
 *
 
34
 * Notes:    These five routines were twisted somewhat from the examples
 
35
 *           in the book "Practical Unix Programming" by Robbins and Robbins.
 
36
 *           The five routines are:
 
37
 *
 
38
 *               VPUBLIC  Vpup_execCmd
 
39
 *               VPRIVATE Vpup_makeargv
 
40
 *               VPRIVATE Vpup_parseDelim
 
41
 *               VPRIVATE Vpup_reDir
 
42
 *               VPRIVATE Vpup_connPipe
 
43
 *
 
44
 * Author:   Michael Holst
 
45
 * ***************************************************************************
 
46
 */
 
47
 
 
48
#include "vsh_p.h"
 
49
#include "vpup.h"
 
50
 
 
51
VEMBED(rcsid="$Id: vpup.c,v 1.8 2002/10/01 21:29:45 mholst Exp $")
 
52
 
 
53
/* define VPUP_SHELL 1 */
 
54
 
 
55
#if !defined(HAVE_WINSOCK_H) && defined(VPUP_SHELL)
 
56
    VPRIVATE int Vpup_makeargv(char *s, const char *delimiters, char ***argvp);
 
57
    VPRIVATE int Vpup_parseDelim(char *s, char delimiter, char **v);
 
58
    VPRIVATE int Vpup_reDir(char *infilename, char *outfilename);
 
59
    VPRIVATE int Vpup_connPipe(char *cmd, int *frontfd, int *backfd);
 
60
#endif
 
61
 
 
62
/*
 
63
 * ***************************************************************************
 
64
 * Class Vsig: Inlineable methods
 
65
 * ***************************************************************************
 
66
 */
 
67
#if !defined(VINLINE_MALOC)
 
68
 
 
69
#endif /* if !defined(VINLINE_MALOC) */
 
70
/*
 
71
 * ***************************************************************************
 
72
 * Class Vsig: Non-inlineable methods
 
73
 * ***************************************************************************
 
74
 */
 
75
 
 
76
#if !defined(HAVE_WINSOCK_H) && defined(VPUP_SHELL)
 
77
/*
 
78
 * ***************************************************************************
 
79
 * Routine:  Vpup_execCmd
 
80
 *
 
81
 * Purpose:  Execute a shell command.
 
82
 *
 
83
 * Author:   Michael Holst
 
84
 * ***************************************************************************
 
85
 */
 
86
VPUBLIC void Vpup_execCmd(const char *PR, int argc, char **argv, char *inbuf)
 
87
{
 
88
    char **chargv;
 
89
    pid_t child_pid;
 
90
    char *cmd;
 
91
    char *nextcmd;
 
92
    int frontfd[2];
 
93
    int backfd[2];
 
94
  
 
95
    frontfd[0] = -1;
 
96
    frontfd[1] = -1;
 
97
    backfd[0]  = -1;
 
98
    backfd[1]  = -1;
 
99
    child_pid  = 0;
 
100
 
 
101
    if ((nextcmd = inbuf) == VNULL) exit(1);
 
102
 
 
103
    while (1) {
 
104
 
 
105
        cmd = nextcmd;
 
106
        if (cmd == VNULL) break;
 
107
 
 
108
        /* if last in pipeline, do not fork another */
 
109
        if ((nextcmd = strchr(nextcmd, VPIPE_SYMBOL)) == VNULL) {
 
110
            backfd[1] = -1;
 
111
            child_pid = 0;
 
112
 
 
113
        /* else fork a child to execute next pipeline command */
 
114
        } else {
 
115
            *nextcmd = VNULL_SYMBOL;
 
116
            nextcmd++;
 
117
            if (pipe(backfd)== -1) {
 
118
                perror(PR);
 
119
                exit(1);
 
120
            } else if ((child_pid = fork()) == -1) {
 
121
                perror(PR);
 
122
                exit(1);
 
123
            }
 
124
        }
 
125
 
 
126
        /* the child execs the command */
 
127
        if (child_pid == 0) {
 
128
            if (Vpup_connPipe(cmd, frontfd, backfd) == -1) {
 
129
                perror(PR);
 
130
                exit(1);
 
131
            } else if (Vpup_makeargv(cmd, VBLANK_STRING, &chargv) > 0) {
 
132
                if (execvp(chargv[0], chargv) == -1) {
 
133
                    perror(PR);
 
134
                    /* Vnm_system("play sorry.au"); */
 
135
                }
 
136
            }
 
137
            exit(1);
 
138
        }
 
139
 
 
140
        /* the parent closes front pipe and makes back pipe, front */
 
141
        close(frontfd[0]);
 
142
        close(frontfd[1]);
 
143
        frontfd[0] = backfd[0];
 
144
        frontfd[1] = backfd[1];
 
145
    }
 
146
    close(backfd[0]);
 
147
    close(backfd[1]);
 
148
    exit(1);
 
149
}
 
150
 
 
151
/*
 
152
 * ***************************************************************************
 
153
 * Routine:  Vpup_makeargv
 
154
 *
 
155
 * Purpose:  Create a set of tokens from the input buffer.
 
156
 *
 
157
 * Author:   Michael Holst
 
158
 * ***************************************************************************
 
159
 */
 
160
VPRIVATE int Vpup_makeargv(char *s, const char *delimiters, char ***argvp)
 
161
{
 
162
    char         *t;
 
163
    char         *snew;
 
164
    int          numtokens;
 
165
    int          i;
 
166
    unsigned int size;
 
167
 
 
168
    /* snew is real start of string after skipping leading delimiters */
 
169
    snew = s + strspn(s, delimiters);
 
170
 
 
171
    /* try to create space for a copy of snew in t */
 
172
    if ((t = calloc(strlen(snew) + 1, sizeof(char))) == VNULL) {
 
173
        *argvp = VNULL;
 
174
        numtokens = -1;
 
175
 
 
176
    /* if space creation successful, parse the string */
 
177
    } else {
 
178
 
 
179
        /* count the number of tokens in snew */
 
180
        strcpy(t, snew);
 
181
        if (strtok(t, delimiters) == VNULL)
 
182
            numtokens = 0;
 
183
        else
 
184
            for (numtokens=1; strtok(VNULL,delimiters) != VNULL; numtokens++);  
 
185
 
 
186
        /* create an argument array to contain ptrs to tokens */
 
187
        size = (unsigned int)(numtokens + 1);
 
188
        if ((*argvp = calloc(size, sizeof(char *))) == VNULL) {
 
189
            free(t);
 
190
            numtokens = -1;
 
191
 
 
192
        /* if successful, insert pointers to tokens into the array */
 
193
        } else {
 
194
            if (numtokens > 0) {
 
195
                strcpy(t, snew);
 
196
                **argvp = strtok(t, delimiters);
 
197
                for (i=1; i<numtokens+1; i++)
 
198
                   *((*argvp)+i) = strtok(VNULL, delimiters);
 
199
            } else {
 
200
                **argvp = VNULL;
 
201
                free(t);
 
202
            }
 
203
        }
 
204
    }   
 
205
    return numtokens;
 
206
}
 
207
 
 
208
/*
 
209
 * ***************************************************************************
 
210
 * Routine:  Vpup_parseDelim
 
211
 *
 
212
 * Purpose:  buffer.
 
213
 *
 
214
 * Author:   Michael Holst
 
215
 * ***************************************************************************
 
216
 */
 
217
VPRIVATE int Vpup_parseDelim(char *s, char delimiter, char **v)
 
218
{
 
219
    char *p;
 
220
    char *q;
 
221
    int offset;
 
222
    int error = 0;
 
223
 
 
224
    /* Find position of the delimiting character */
 
225
    *v = NULL;
 
226
    if ((p = strchr(s, delimiter)) != NULL)  {
 
227
 
 
228
        /* Split off the token following delimiter */
 
229
        if ((q = (char *)malloc(strlen(p + 1) + 1)) == NULL)
 
230
            error = -1;
 
231
 
 
232
        else {
 
233
            strcpy(q, p + 1);
 
234
            if ((*v = strtok(q, VDELIM_SET)) == NULL) error = -1;
 
235
            offset = strlen(q);
 
236
            strcpy(p, p + offset + 1);
 
237
        } 
 
238
    }
 
239
    return error;
 
240
}
 
241
 
 
242
/*
 
243
 * ***************************************************************************
 
244
 * Routine:  Vpup_reDir
 
245
 *
 
246
 * Purpose:  Do a redirection.
 
247
 *
 
248
 * Author:   Michael Holst
 
249
 * ***************************************************************************
 
250
 */
 
251
VPRIVATE int Vpup_reDir(char *infilename, char *outfilename)
 
252
{
 
253
    int indes;
 
254
    int outdes;
 
255
 
 
256
    /* redirect standard in to infilename */
 
257
    if (infilename != VNULL) {
 
258
        if ((indes = open(infilename, O_RDONLY, VSTDMODE)) == -1)
 
259
            return -1;
 
260
        if (dup2(indes, STDIN_FILENO) == -1) {
 
261
            close(indes);
 
262
            return -1;
 
263
        }  
 
264
        close(indes);
 
265
    }
 
266
 
 
267
    /* redirect standard out to outfilename */
 
268
    if (outfilename != VNULL) {
 
269
        if ((outdes=open(outfilename,O_WRONLY|O_CREAT|O_TRUNC,VSTDMODE))==-1)
 
270
            return -1;
 
271
        if (dup2(outdes, STDOUT_FILENO) == -1) {
 
272
            close(outdes);
 
273
            return -1;
 
274
        }
 
275
        close(outdes);
 
276
    }   
 
277
    return 0;
 
278
}
 
279
 
 
280
/*
 
281
 * ***************************************************************************
 
282
 * Routine:  Vpup_connPipe
 
283
 *
 
284
 * Purpose:  Connect up some pipes.
 
285
 *
 
286
 * Author:   Michael Holst
 
287
 * ***************************************************************************
 
288
 */
 
289
VPRIVATE int Vpup_connPipe(char *cmd, int *frontfd, int *backfd)
 
290
{
 
291
    int error = 0;
 
292
    char *infilename, *outfilename;
 
293
 
 
294
    /* look for stdin redirect */
 
295
    if (Vpup_parseDelim(cmd, VRDIN_SYMBOL, &infilename) == -1)
 
296
        error = -1;
 
297
 
 
298
    /* no redirection allowed at front of pipeline */
 
299
    else if (infilename != VNULL && frontfd[0] != -1)
 
300
        error = -1;
 
301
 
 
302
    /* look for stdout redirect */
 
303
    else if (Vpup_parseDelim(cmd, VRDOUT_SYMBOL, &outfilename) == -1)
 
304
        error = -1;
 
305
 
 
306
    /* no redirection allowed at back of pipeline */
 
307
    else if (outfilename != VNULL && backfd[1] != -1)
 
308
        error = -1;
 
309
 
 
310
    /* do any required redirections */
 
311
    else if (Vpup_reDir(infilename, outfilename) == -1)
 
312
        error = -1;
 
313
 
 
314
    /* now connect up appropriate pipes */
 
315
    else { 
 
316
        if (frontfd[0] != -1) {
 
317
            if (dup2(frontfd[0], STDIN_FILENO) == -1)
 
318
            error = -1;
 
319
        } 
 
320
        if (backfd[1] != -1) {
 
321
            if (dup2(backfd[1], STDOUT_FILENO) == -1)
 
322
                error = -1;
 
323
        } 
 
324
    }
 
325
 
 
326
    /* close unneeded file descriptors */
 
327
    close (frontfd[0]);
 
328
    close (frontfd[1]);
 
329
    close (backfd[0]);
 
330
    close (backfd[1]);
 
331
    return error;
 
332
}
 
333
#else
 
334
 
 
335
/*
 
336
 * ***************************************************************************
 
337
 * Routine:  Vpup_execCmd
 
338
 *
 
339
 * Purpose:  A simple shell command exec.
 
340
 *
 
341
 * Author:   Michael Holst
 
342
 * ***************************************************************************
 
343
 */
 
344
VPUBLIC void Vpup_execCmd(const char *PR, int argc, char **argv, char *inbuf)
 
345
{
 
346
    Vnm_exec(argc,argv);
 
347
}
 
348
#endif /* if !defined(HAVE_WINSOCK_H) */
 
349