Root/cpp.c

1/*
2 * cpp.c - CPP subprocess
3 *
4 * Written 2002-2004, 2006, 2008 by Werner Almesberger
5 * Copyright 2002, 2003 California Institute of Technology
6 * Copyright 2004, 2006 Werner Almesberger
7 * Copyright 2008 by OpenMoko, Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 */
14
15
16#include <stdlib.h>
17#include <stdio.h>
18#include <unistd.h>
19#include <string.h>
20#include <fcntl.h>
21#include <signal.h>
22#include <sys/types.h>
23#include <sys/wait.h>
24
25#include "cpp.h"
26
27
28const char *cpp_command = CPP;
29
30static pid_t cpp_pid;
31static int cpp_argc = 0;
32static const char **cpp_argv = NULL;
33static int real_stdin = -1;
34
35
36void add_cpp_arg(const char *arg)
37{
38    if (!cpp_argc)
39    cpp_argc = 1;
40    cpp_argv = realloc(cpp_argv,sizeof(const char *)*(cpp_argc+1));
41    if (!cpp_argv) {
42    perror("realloc");
43    exit(1);
44    }
45    if (cpp_argc == 1)
46    cpp_argv[0] = cpp_command;
47    if (arg) {
48    arg = strdup(arg);
49    if (!arg) {
50        perror("strdup");
51        exit(1);
52    }
53    }
54    cpp_argv[cpp_argc++] = arg;
55}
56
57
58void add_cpp_Wp(const char *arg)
59{
60    char *tmp = strdup(arg);
61    char *curr,*end;
62
63    if (!tmp) {
64    perror("strdup");
65    exit(1);
66    }
67    curr = tmp;
68    do {
69    end = strchr(curr,',');
70    if (end)
71        *end++ = 0;
72    add_cpp_arg(curr);
73    curr = end;
74    }
75    while (end);
76    free(tmp);
77}
78
79
80static void kill_cpp(void)
81{
82    if (cpp_pid)
83    (void) kill(cpp_pid,SIGTERM);
84}
85
86
87static void run_cpp(const char *name,int fd,int close_fd)
88{
89    char **arg;
90    int fds[2];
91
92    if (pipe(fds) < 0) {
93        perror("pipe");
94        exit(1);
95    }
96    if (name)
97    add_cpp_arg(name);
98    add_cpp_arg(NULL);
99    cpp_pid = fork();
100    if (cpp_pid < 0) {
101        perror("fork");
102        exit(1);
103    }
104    if (!cpp_pid) {
105    if (close(fds[0]) < 0) {
106        perror("close");
107        exit(1);
108    }
109    if (close_fd != -1 && close(close_fd) < 0) {
110        perror("close");
111        exit(1);
112    }
113    if (fd != -1 && dup2(fd,0) < 0) {
114        perror("dup2");
115        exit(1);
116    }
117    if (dup2(fds[1],1) < 0) {
118        perror("dup2");
119        exit(1);
120    }
121    if (execvp(cpp_command,(char **) cpp_argv) < 0) {
122      /* prototype is weird */
123        perror(cpp_command);
124        exit(1);
125    }
126    /* not reached */
127    }
128    if (close(fds[1]) < 0) {
129    perror("close");
130    exit(1);
131    }
132    real_stdin = dup(0);
133    if (real_stdin < 0) {
134    perror("dup");
135    exit(1);
136    }
137    if (fd != -1 && close(fd) < 0) {
138    perror("close");
139    exit(1);
140    }
141    if (dup2(fds[0],0) < 0) {
142    perror("dup2");
143    exit(1);
144    }
145    for (arg = (char **) cpp_argv+1; *arg; arg++)
146    free(*arg);
147    free(cpp_argv);
148    cpp_argv = NULL;
149    cpp_argc = 0;
150}
151
152
153void run_cpp_on_file(const char *name)
154{
155    run_cpp(name,name ? -1 : 0,-1);
156    atexit(kill_cpp);
157}
158
159
160void run_cpp_on_string(const char *str)
161{
162    int fds[2];
163    pid_t pid;
164    int left,wrote;
165
166    if (pipe(fds) < 0) {
167        perror("pipe");
168        exit(1);
169    }
170    run_cpp(NULL,fds[0],fds[1]);
171    pid = fork();
172    if (pid < 0) {
173    perror("fork");
174    exit(1);
175    }
176    if (!pid) {
177    for (left = strlen(str); left; left -= wrote) {
178        wrote = write(fds[1],str,left);
179        if (wrote < 0)
180        break; /* die silently */
181        str += wrote;
182    }
183    exit(0);
184    }
185    if (close(fds[1]) < 0) {
186    perror("close");
187    exit(1);
188    }
189    atexit(kill_cpp);
190}
191
192
193void reap_cpp(void)
194{
195    int status;
196
197    cpp_pid = 0;
198    if (waitpid(cpp_pid,&status,0) < 0) {
199    perror("waitpid");
200    exit(1);
201    }
202    if (!status) {
203    if (dup2(real_stdin,0) < 0) {
204        perror("dup2");
205        exit(1);
206    }
207    return;
208    }
209    if (WIFEXITED(status))
210    exit(WEXITSTATUS(status));
211    if (WIFSIGNALED(status))
212    fprintf(stderr,"cpp terminated with signal %d\n",WTERMSIG(status));
213    else
214    fprintf(stderr,"cpp terminated with incomprehensible status %d\n",
215      status);
216    exit(1);
217}
218

Archive Download this file

Branches:
master



interactive