summaryrefslogtreecommitdiffstats
path: root/src/appl/gssftp/ftp/pclose.c
blob: 04e481b1920434b100ec4aebf6a6f23c36883068 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * Copyright (c) 1980 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 */

#ifndef lint
static	char sccsid[] = "@(#)pclose.c 1.1 90/04/28 SMI"; /* from UCB 1.2 3/7/86 */
#endif /* not lint */

#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <signal.h>
#include <sys/param.h>
#include <sys/wait.h>
#ifdef HAVE_VFORK_H
#include <vfork.h>
#endif
#define sig_t my_sig_t
#define sigtype krb5_sigtype
typedef sigtype (*sig_t)();

#define	tst(a,b)	(*mode == 'r'? (b) : (a))
#define	RDR	0
#define	WTR	1

static	int *popen_pid;
static	int nfiles;

#ifndef HAVE_GETDTABLESIZE
#include <sys/resource.h>
int getdtablesize() {
  struct rlimit rl;
  getrlimit(RLIMIT_NOFILE, &rl);
  return rl.rlim_cur;
}
#endif

FILE *
mypopen(cmd,mode)
	char *cmd;
	char *mode;
{
	int p[2];
	volatile int myside, hisside;
	int pid;

	if (nfiles <= 0)
		nfiles = getdtablesize();
	if (popen_pid == NULL) {
		popen_pid = (int *)malloc((unsigned) nfiles * sizeof *popen_pid);
		if (popen_pid == NULL)
			return (NULL);
		for (pid = 0; pid < nfiles; pid++)
			popen_pid[pid] = -1;
	}
	if (pipe(p) < 0)
		return (NULL);
	myside = tst(p[WTR], p[RDR]);
	hisside = tst(p[RDR], p[WTR]);
	if ((pid = vfork()) == 0) {
		/* myside and hisside reverse roles in child */
		(void) close(myside);
		if (hisside != tst(0, 1)) {
			(void) dup2(hisside, tst(0, 1));
			(void) close(hisside);
		}
		execl("/bin/sh", "sh", "-c", cmd, (char *)NULL);
		_exit(127);
	}
	if (pid == -1) {
		(void) close(myside);
		(void) close(hisside);
		return (NULL);
	}
	popen_pid[myside] = pid;
	(void) close(hisside);
	return (fdopen(myside, mode));
}

sigtype
pabort(sig)
	int sig;
{
	extern int mflag;

	mflag = 0;
}

mypclose(ptr)
	FILE *ptr;
{
	int child, pid;
#ifdef USE_SIGPROCMASK
	sigset_t old, new;
#else
	int omask;
#endif
	sigtype pabort(), (*istat)();
#ifdef WAIT_USES_INT
	int status;
#else
	union wait status;
#endif

	child = popen_pid[fileno(ptr)];
	popen_pid[fileno(ptr)] = -1;
	(void) fclose(ptr);
	if (child == -1)
		return (-1);
	istat = signal(SIGINT, pabort);
#ifdef USE_SIGPROCMASK
	sigemptyset(&old);
	sigemptyset(&new);
	sigaddset(&new,SIGQUIT);
	sigaddset(&new,SIGHUP);
	sigprocmask(SIG_BLOCK, &new, &old);
	while ((pid = wait(&status)) != child && pid != -1)
		;
	sigprocmask(SIG_SETMASK, &old, NULL);
#else
	omask = sigblock(sigmask(SIGQUIT)|sigmask(SIGHUP));
	while ((pid = wait(&status)) != child && pid != -1)
		;
	sigsetmask(omask);
#endif
	(void) signal(SIGINT, istat);
	return (pid == -1 ? -1 : 0);
}