1 /*
2
3 $Header: utils.c[1.14] Wed Sep 9 16:34:03 1992 nickel@cs.tu-berlin.de proposed $
4 This file is part of socket(1).
5 Copyright (C) 1992 by Juergen Nickelsen <nickel@cs.tu-berlin.de>
6 Please read the file COPYRIGHT for further details.
7
8 */
9
10 #ifdef sgi
11 #define _BSD_SIGNALS
12 #define SIG_HANDLER_RET int
13 #else /* !sgi */
14 #define SIG_HANDLER_RET void
15 #endif
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <signal.h>
20 #include <sys/wait.h>
21 #include <sys/time.h>
22 #include <fcntl.h>
23 #include <sys/ioctl.h>
24 #ifdef ISC
25 #define WNOHANG 1
26 #else
27 #include <sys/resource.h>
28 #endif
29 #include <unistd.h>
30 #include "globals.h"
31
32 extern void initialize_siglist A((void)) ;
33
34 /* Signal handler, print message and exit */
exitsig(sig)35 SIG_HANDLER_RET exitsig(sig)
36 int sig ;
37 {
38 if (sig != SIGUSR1) {
39 fprintf(stderr, "\n%s occured, exiting\n", sys_siglist[sig]) ;
40 }
41 exit(-sig) ;
42 }
43
44 /* Give usage message */
usage()45 void usage()
46 {
47 static char ustring[] =
48 "Usage: %s [-bclqrvw] [-p prog] [-s | host] port\n" ;
49
50 fprintf(stderr, ustring, progname) ;
51 }
52
53 /* perror with progname */
perror2(s)54 void perror2(s)
55 char *s ;
56 {
57 fprintf(stderr, "%s: ", progname) ;
58 perror(s) ;
59 }
60
61 /* is s a number? */
is_number(s)62 int is_number(s)
63 char *s ;
64 {
65 while (*s) {
66 if (*s < '0' || *s > '9') {
67 return 0 ;
68 }
69 s++ ;
70 }
71 return 1 ;
72 }
73
74 /* set up signal handling. All except TSTP, CONT, CLD, and QUIT
75 * are caught with exitsig(). */
init_signals()76 void init_signals()
77 {
78 int i ;
79 #ifdef SIG_SETMASK /* only with BSD signals */
80 static struct sigvec svec = { exitsig, ~0, 0 } ;
81 #endif
82
83 initialize_siglist() ; /* shamelessly stolen from BASH */
84
85 for (i = 0; i < NSIG; i++) {
86 switch (i) {
87 #ifdef SIGTSTP
88 case SIGTSTP:
89 case SIGTTOU:
90 case SIGTTIN:
91 case SIGSTOP:
92 case SIGCONT:
93 continue ;
94 #endif
95 #ifdef SIGINFO
96 case SIGINFO:
97 continue ;
98 #endif
99 #if !defined (SIGCHLD) && defined (SIGCLD)
100 #define SIGCHLD SIGCLD
101 #endif
102 #ifdef SIGCHLD
103 case SIGCHLD:
104 continue ;
105 #endif
106 #ifdef SIGWINCH
107 case SIGWINCH: /* it is ridiculous to exit on WINCH */
108 continue ;
109 #endif
110 case SIGQUIT: /* if the user wants a core dump, */
111 continue ; /* they can have it. */
112 default:
113 #ifdef SIG_SETMASK
114 sigvec(i, &svec, NULL) ;
115 #else
116 signal(i, exitsig) ;
117 #endif
118 }
119 }
120 }
121
122 /* connect stdin with prog's stdout/stderr and stdout
123 * with prog's stdin. */
open_pipes(prog)124 void open_pipes(prog)
125 char *prog ;
126 {
127 int from_cld[2] ; /* from child process */
128 int to_cld[2] ; /* to child process */
129
130 /* create pipes */
131 if (pipe(from_cld) == -1) {
132 perror2("pipe") ;
133 exit(errno) ;
134 }
135 if (pipe(to_cld) == -1) {
136 perror2("pipe") ;
137 exit(errno) ;
138 }
139
140 /* for child process */
141 switch (fork()) {
142 case 0: /* this is the child process */
143 /* connect stdin to pipe */
144 close(0) ;
145 close(to_cld[1]) ;
146 dup2(to_cld[0], 0) ;
147 close(to_cld[0]) ;
148 /* connect stdout to pipe */
149 close(1) ;
150 close(from_cld[0]) ;
151 dup2(from_cld[1], 1) ;
152 /* connect stderr to pipe */
153 close(2) ;
154 dup2(from_cld[1], 2) ;
155 close(from_cld[1]) ;
156 /* call program via sh */
157 execl("/bin/sh", "sh", "-c", prog, NULL) ;
158 perror2("exec /bin/sh") ;
159 /* terminate parent silently */
160 kill(getppid(), SIGUSR1) ;
161 exit(255) ;
162 case -1:
163 perror2("fork") ; /* fork failed */
164 exit(errno) ;
165 default: /* parent process */
166 /* connect stderr to pipe */
167 close(0) ;
168 close(from_cld[1]) ;
169 dup2(from_cld[0], 0) ;
170 close(from_cld[0]) ;
171 /* connect stderr to pipe */
172 close(1) ;
173 close(to_cld[0]) ;
174 dup2(to_cld[1], 1) ;
175 close(to_cld[1]) ;
176 }
177 }
178
179 /* remove zombie child processes */
wait_for_children()180 void wait_for_children()
181 {
182 int wret, status ;
183 #ifndef ISC
184 struct rusage rusage ;
185 #endif
186
187 /* Just do a wait, forget result */
188 #ifndef ISC
189 while ((wret = wait3(&status, WNOHANG, &rusage)) > 0) ;
190 #else
191 while ((wret = waitpid(-1, &status, WNOHANG)) > 0) ;
192 #endif
193 }
194
195 /* expand LF characters to CRLF and adjust *sizep */
add_crs(from,to,sizep)196 void add_crs(from, to, sizep)
197 char *from, *to ; /* *from is copied to *to */
198 int *sizep ;
199 {
200 int countdown ; /* counter */
201
202 countdown = *sizep ;
203 while (countdown) {
204 if (*from == '\n') {
205 *to++ = '\r' ;
206 (*sizep)++ ;
207 }
208 *to++ = *from++ ;
209 countdown-- ;
210 }
211 }
212
213 /* strip CR characters from buffer and adjust *sizep */
strip_crs(from,to,sizep)214 void strip_crs(from, to, sizep)
215 char *from, *to ; /* *from is copied to *to */
216 int *sizep ;
217 {
218
219 int countdown ; /* counter */
220
221 countdown = *sizep ;
222 while (countdown) {
223 if (*from == '\r') {
224 from++ ;
225 (*sizep)-- ;
226 } else {
227 *to++ = *from++ ;
228 }
229 countdown-- ;
230 }
231 }
232
233 #define NULL_DEVICE "/dev/null"
234
235 /* put yourself in the background */
background()236 void background()
237 {
238 int child_pid ; /* PID of child process */
239 int nulldev_fd ; /* file descriptor for null device */
240
241 child_pid = fork() ;
242 switch (child_pid) {
243 case -1:
244 perror2("fork") ;
245 exit(1) ;
246 case 0:
247 #ifdef NOSETSID
248 ioctl(0, TIOCNOTTY, 0) ;
249 #else
250 setsid() ;
251 #endif
252 chdir("/") ;
253 if ((nulldev_fd = open(NULL_DEVICE, O_RDWR, 0)) != -1) {
254 int i ;
255
256 for (i = 0; i < 3; i++) {
257 if (isatty(i)) {
258 dup2(nulldev_fd, i) ;
259 }
260 }
261 close(nulldev_fd) ;
262 }
263 break ;
264 default:
265 exit(0) ;
266 }
267 }
268