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