/* */
This source file includes following definitions.
- myopen
- myfopen
- mypopen
- mypclose
1 /*===========================================================================
2 Copyright (c) 1998-2000, The Santa Cruz Operation
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 *Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10
11 *Redistributions in binary form must reproduce the above copyright notice,
12 this list of conditions and the following disclaimer in the documentation
13 and/or other materials provided with the distribution.
14
15 *Neither name of The Santa Cruz Operation nor the names of its contributors
16 may be used to endorse or promote products derived from this software
17 without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
20 IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30 DAMAGE.
31 =========================================================================*/
32
33 #include <stdio.h>
34 #include <signal.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <sys/types.h>
38 #include "global-cscope.h" /* pid_t, RETSIGTYPE, shell, and mybasename() */
39
40 #if defined(__DJGPP__) || (defined(_WIN32) && !defined(__CYGWIN__))
41 #define MS_OS
42 #else
43 #include <sys/wait.h>
44 #endif
45
46 #define tst(a,b) (*mode == 'r'? (b) : (a))
47 #define RDR 0
48 #define WTR 1
49
50 /* HBB 20010312: make this a bit safer --- don't blindly assume it's 1 */
51 #ifdef FD_CLOEXEC
52 # define CLOSE_ON_EXEC FD_CLOEXEC
53 #else
54 # define CLOSE_ON_EXEC 1
55 #endif
56
57 #ifdef HAVE_IO_H
58 # include <io.h> /* for setmode() */
59 #endif
60
61 static char const rcsid[] = "$Id: mypopen.c,v 1.3 2012/10/13 07:02:07 shigio Exp $";
62
63 static pid_t popen_pid[20];
64 static RETSIGTYPE (*tstat)(int);
65
66 /** opens a file descriptor and then sets close-on-exec for the file */
67 int
68 myopen(char *path, int flag, int mode)
69 {
70 /* opens a file descriptor and then sets close-on-exec for the file */
71 int fd;
72
73 /* 20020103: if file is not explicitly in Binary mode, make
74 * sure we override silly Cygwin behaviour of automatic binary
75 * mode for files in "binary mounted" paths */
76 #if O_BINARY != O_TEXT
77 if (! (flag | O_BINARY))
78 flag |= O_TEXT;
79 #endif
80 if(mode)
81 fd = open(path, flag, mode);
82 else
83 fd = open(path, flag);
84
85 #ifdef MS_OS /* FIXME: test feature, not platform */
86 /* HBB 20010312: DOS GCC doesn't have FD_CLOEXEC (yet), so it
87 * always fails this call. Have to skip that step */
88 if(fd != -1)
89 return(fd);
90 #else
91 if(fd != -1 && (fcntl(fd, F_SETFD, CLOSE_ON_EXEC) != -1))
92 return(fd);
93 #endif
94 else
95 {
96 /* Ensure that if the fcntl fails and fd is valid, then
97 the file is closed properly. In general this should
98 not happen. */
99 if (fd != -1)
100 {
101 close (fd);
102 }
103
104 return(-1);
105 }
106 }
107
108 /** opens a file pointer and then sets close-on-exec for the file */
109 FILE *
110 myfopen(char *path, char *mode)
111 {
112 /* opens a file pointer and then sets close-on-exec for the file */
113 FILE *fp;
114
115 fp = fopen(path, mode);
116
117 #ifdef SETMODE
118 if (fp && ! strchr(mode, 'b')) {
119 SETMODE(fileno(fp), O_TEXT);
120 }
121 #endif /* SETMODE */
122
123 #ifdef MS_OS /* FIXME: test feature, not platform */
124 /* HBB 20010312: DOS GCC doesn't have FD_CLOEXEC (yet), so it
125 * always fails this call. Have to skip that step */
126 if(fp)
127 #else
128 if(fp && (fcntl(fileno(fp), F_SETFD, CLOSE_ON_EXEC) != -1))
129 #endif
130 return(fp);
131
132 else
133 return(NULL);
134 }
135
136 FILE *
137 mypopen(char *cmd, char *mode)
138 {
139 #ifdef MS_OS
140 /* HBB 20010312: Has its own implementation of popen(), which
141 * is better suited to the platform than cscope's */
142 return (popen)(cmd, mode);
143 #else
144 int p[2];
145 pid_t *poptr;
146 int myside, yourside;
147 pid_t pid;
148
149 if(pipe(p) < 0)
150 return(NULL);
151 myside = tst(p[WTR], p[RDR]);
152 yourside = tst(p[RDR], p[WTR]);
153 if((pid = fork()) == 0) {
154 /* myside and yourside reverse roles in child */
155 int stdio;
156
157 /* close all pipes from other popen's */
158 for (poptr = popen_pid; poptr < popen_pid+20; poptr++) {
159 if(*poptr)
160 (void) close(poptr - popen_pid);
161 }
162 stdio = tst(0, 1);
163 close(myside);
164 close(stdio);
165 #if V9
166 dup2(yourside, stdio);
167 #else
168 fcntl(yourside, F_DUPFD, stdio);
169 #endif
170 close(yourside);
171 execlp(shell, mybasename(shell), "-c", cmd, (void *)0);
172 _exit(1);
173 } else if (pid > 0)
174 tstat = signal(SIGTSTP, SIG_DFL);
175 if(pid == -1)
176 return(NULL);
177 popen_pid[myside] = pid;
178 (void) close(yourside);
179 return(fdopen(myside, mode));
180 #endif /* MS_OS */
181 }
182
183 /* HBB 20010705: renamed from 'pclose', which would collide with
184 * system-supplied function of same name */
185 int
186 mypclose(FILE *ptr)
187 {
188 int f;
189 pid_t r;
190 int status;
191 sighandler_t hstat, istat, qstat;
192
193 #ifdef MS_OS
194 /* HBB 20010705: This system has its own pclose(), which we
195 * don't want to replace */
196 return (pclose)(ptr);
197 #else
198 f = fileno(ptr);
199 (void) fclose(ptr);
200 istat = signal(SIGINT, SIG_IGN);
201 qstat = signal(SIGQUIT, SIG_IGN);
202 hstat = signal(SIGHUP, SIG_IGN);
203 while((r = wait(&status)) != popen_pid[f] && r != -1)
204 ;
205 if(r == -1)
206 status = -1;
207 (void) signal(SIGINT, istat);
208 (void) signal(SIGQUIT, qstat);
209 (void) signal(SIGHUP, hstat);
210 (void) signal(SIGTSTP, tstat);
211 /* mark this pipe closed */
212 popen_pid[f] = 0;
213 return(status);
214 #endif /* MS_OS */
215 }
/* */