~ubuntu-branches/debian/sid/policycoreutils/sid

« back to all changes in this revision

Viewing changes to .pc/all/run_init/open_init_pty.c

  • Committer: Package Import Robot
  • Author(s): Laurent Bigonville
  • Date: 2012-03-20 19:50:46 UTC
  • Revision ID: package-import@ubuntu.com-20120320195046-e0u3p8oxbk1a1qcg
Tags: 2.1.10-5
* Team upload.
* Switch to dh sequence and debhelper 9
* Merge my missing patches
* d/p/fix-ftbfs-hardening-flags.patch: Fix FTBFS with hardening flags
* d/policycoreutils.lintian-overrides: Drop non-standard-toplevel-dir selinux/
* debian/patches/0006-default-config.patch: Properly disable sandbox by
  default
* Rewrite maintainer scripts to use debhelper generated stanza.
  (Should closes: #660345)
* debian/control: Update Vcs-* fields
* Add debian/gbp.conf file
* debian/control:
  - Add Pre-Depends: ${misc:Pre-Depends} field
  - Make policycoreutils arch:linux-any
  - Put under the Debian SELinux team maintenance
  - Bump python-setools dependency to >= 3.3.7-2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*                               -*- Mode: C -*- 
2
 
 * open_init_pty.c --- 
3
 
 * Author           : Manoj Srivastava ( srivasta@glaurung.internal.golden-gryphon.com ) 
4
 
 * Created On       : Fri Jan 14 10:48:28 2005
5
 
 * Created On Node  : glaurung.internal.golden-gryphon.com
6
 
 * Last Modified By : Manoj Srivastava
7
 
 * Last Modified On : Thu Sep 15 00:57:00 2005
8
 
 * Last Machine Used: glaurung.internal.golden-gryphon.com
9
 
 * Update Count     : 92
10
 
 * Status           : Unknown, Use with caution!
11
 
 * HISTORY          : 
12
 
 * Description      : 
13
 
 *
14
 
 * Distributed under the terms of the GNU General Public License v2
15
 
 *
16
 
 * open_init_pty
17
 
 *
18
 
 * SYNOPSIS:
19
 
 *
20
 
 * This program allows a systems administrator to execute daemons
21
 
 * which need to work in the initrc domain, and which need to have
22
 
 * pty's as system_u:system_r:initrc_t
23
 
 *
24
 
 * USAGE:
25
 
 *
26
 
 * * arch-tag: a5583d39-72b9-4cdf-ba1b-5678ea4cbe20
27
 
 */
28
 
 
29
 
#include <stdio.h>
30
 
#include <stdlib.h>
31
 
#include <unistd.h>
32
 
#include <signal.h>
33
 
#include <errno.h>
34
 
 
35
 
#include <sysexits.h>
36
 
 
37
 
#include <pty.h>                /* for openpty and forkpty */
38
 
#include <utmp.h>               /* for login_tty */
39
 
#include <termios.h>
40
 
#include <fcntl.h>
41
 
 
42
 
#include <sys/select.h>
43
 
 
44
 
static struct termios saved_termios;
45
 
static int saved_fd = -1;
46
 
static enum { RESET, RAW, CBREAK } tty_state = RESET;
47
 
 
48
 
static int tty_semi_raw(int fd)
49
 
{
50
 
        struct termios buf;
51
 
 
52
 
        if (tty_state == RESET) {
53
 
                if (tcgetattr(fd, &saved_termios) < 0) {
54
 
                        return -1;
55
 
                }
56
 
        }
57
 
 
58
 
        buf = saved_termios;
59
 
        /*
60
 
         * echo off, canonical mode off, extended input processing off,
61
 
         * signal chars off 
62
 
         */
63
 
        buf.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
64
 
        /*
65
 
         * no SIGINT on break, CR-to-NL off, input parity check off, do not
66
 
         * strip 8th bit on input,output flow control off
67
 
         */
68
 
        buf.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
69
 
        /* Clear size bits, parity checking off */
70
 
        buf.c_cflag &= ~(CSIZE | PARENB);
71
 
        /* set 8 bits/char */
72
 
        buf.c_cflag |= CS8;
73
 
        /* Output processing off 
74
 
           buf.c_oflag    &= ~(OPOST); */
75
 
 
76
 
        buf.c_cc[VMIN] = 1;     /* one byte at a time, no timer */
77
 
        buf.c_cc[VTIME] = 0;
78
 
        if (tcsetattr(fd, TCSANOW, &buf) < 0) {
79
 
                return -1;
80
 
        }                       /* end of if(tcsetattr(fileno(stdin), TCSANOW, &buf) < 0) */
81
 
        tty_state = RAW;
82
 
        saved_fd = fd;
83
 
        return 0;
84
 
}
85
 
 
86
 
void tty_atexit(void)
87
 
{
88
 
        if (tty_state != CBREAK && tty_state != RAW) {
89
 
                return;
90
 
        }
91
 
 
92
 
        if (tcsetattr(saved_fd, TCSANOW, &saved_termios) < 0) {
93
 
                return;
94
 
        }                       /* end of if(tcsetattr(fileno(stdin), TCSANOW, &buf) < 0) */
95
 
        tty_state = RESET;
96
 
        return;
97
 
}
98
 
 
99
 
int main(int argc, char *argv[])
100
 
{
101
 
        pid_t child_pid;
102
 
        struct termios tty_attr;
103
 
        struct winsize window_size;
104
 
        int pty_master;
105
 
        int retval = 0;
106
 
 
107
 
        /* for select */
108
 
        fd_set readfds;
109
 
        fd_set writefds;
110
 
        fd_set exceptfds;
111
 
 
112
 
        int err_count = 0;
113
 
 
114
 
        /* for sigtimedwait() */
115
 
        struct timespec timeout;
116
 
        char buf[16384];
117
 
 
118
 
        if (argc == 1) {
119
 
                printf("usage: %s PROGRAM [ARGS]...\n", argv[0]);
120
 
                exit(1);
121
 
        }
122
 
 
123
 
        sigset_t signal_set;
124
 
        siginfo_t signalinfo;
125
 
 
126
 
        /* set up SIGCHLD */
127
 
        sigemptyset(&signal_set);       /* no signals */
128
 
        sigaddset(&signal_set, SIGCHLD);        /* Add sig child  */
129
 
        sigprocmask(SIG_BLOCK, &signal_set, NULL);      /* Block the signal */
130
 
 
131
 
        /* Set both to 0, so sigtimed wait just does a poll */
132
 
        timeout.tv_sec = 0;
133
 
        timeout.tv_nsec = 0;
134
 
 
135
 
        if (isatty(fileno(stdin))) {
136
 
                /* get terminal parameters associated with stdout */
137
 
                if (tcgetattr(fileno(stdout), &tty_attr) < 0) {
138
 
                        perror("tcgetattr:");
139
 
                        exit(EX_OSERR);
140
 
                }
141
 
 
142
 
                /* end of if(tcsetattr(&tty_attr)) */
143
 
                /* get window size */
144
 
                if (ioctl(fileno(stdout), TIOCGWINSZ, &window_size) < 0) {
145
 
                        perror("ioctl stdout:");
146
 
                        exit(1);
147
 
                }
148
 
 
149
 
                child_pid = forkpty(&pty_master, NULL, &tty_attr, &window_size);
150
 
        } /* end of if(isatty(fileno(stdin))) */
151
 
        else {                  /* not interactive */
152
 
                child_pid = forkpty(&pty_master, NULL, NULL, NULL);
153
 
        }
154
 
 
155
 
        if (child_pid < 0) {
156
 
                perror("forkpty():");
157
 
                fflush(stdout);
158
 
                fflush(stderr);
159
 
                exit(EX_OSERR);
160
 
        }                       /* end of if(child_pid < 0) */
161
 
        if (child_pid == 0) {
162
 
                /* in the child */
163
 
                struct termios s_tty_attr;
164
 
                if (tcgetattr(fileno(stdin), &s_tty_attr)) {
165
 
                        perror("Child:");
166
 
                        fflush(stdout);
167
 
                        fflush(stderr);
168
 
                        exit(EXIT_FAILURE);
169
 
                }
170
 
                /* Turn off echo */
171
 
                s_tty_attr.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
172
 
                /* Also turn of NL to CR?LF on output */
173
 
                s_tty_attr.c_oflag &= ~(ONLCR);
174
 
                if (tcsetattr(fileno(stdin), TCSANOW, &s_tty_attr)) {
175
 
                        perror("Child:");
176
 
                        exit(EXIT_FAILURE);
177
 
                }
178
 
                {               /* There is no reason to block sigchild for the process we
179
 
                                   shall exec here */
180
 
                        sigset_t chld_signal_set;
181
 
                        /* release SIGCHLD */
182
 
                        sigemptyset(&chld_signal_set);  /* no signals */
183
 
                        sigaddset(&chld_signal_set, SIGCHLD);   /* Add sig child  */
184
 
                        sigprocmask(SIG_UNBLOCK, &chld_signal_set, NULL);       /* Unblock the signal */
185
 
                }
186
 
 
187
 
                if (execvp(argv[1], argv + 1)) {
188
 
                        perror("Exec:");
189
 
                        fflush(stdout);
190
 
                        fflush(stderr);
191
 
                        exit(EXIT_FAILURE);
192
 
                }
193
 
        }
194
 
 
195
 
        /* end of if(child_pid == 0) */
196
 
        /* 
197
 
         * OK. Prepare to handle IO from the child. We need to transfer
198
 
         * everything from the child's stdout to ours.
199
 
         */
200
 
        FD_ZERO(&readfds);
201
 
        FD_ZERO(&writefds);
202
 
        FD_ZERO(&exceptfds);
203
 
 
204
 
        /*
205
 
         * Read current file descriptor flags, preparing to do non blocking reads
206
 
         */
207
 
        retval = fcntl(pty_master, F_GETFL);
208
 
        if (retval < 0) {
209
 
                perror("fcntl_get");
210
 
                fflush(stdout);
211
 
                fflush(stderr);
212
 
                exit(EX_IOERR);
213
 
        }
214
 
 
215
 
        /* Set the connection to be non-blocking */
216
 
        if (fcntl(pty_master, F_SETFL, retval | O_NONBLOCK) < 0) {
217
 
                perror("fcnt_setFlag_nonblock:");
218
 
                fflush(stdout);
219
 
                fflush(stderr);
220
 
                exit(1);
221
 
        }
222
 
 
223
 
        FD_SET(pty_master, &readfds);
224
 
        FD_SET(pty_master, &writefds);
225
 
        FD_SET(fileno(stdin), &readfds);
226
 
        if (isatty(fileno(stdin))) {
227
 
                if (tty_semi_raw(fileno(stdin)) < 0) {
228
 
                        perror("Error: settingraw mode:");
229
 
                        fflush(stdout);
230
 
                        fflush(stderr);
231
 
                }               /* end of if(tty_raw(fileno(stdin)) < 0) */
232
 
                if (atexit(tty_atexit) < 0) {
233
 
                        perror("Atexit setup:");
234
 
                        fflush(stdout);
235
 
                        fflush(stderr);
236
 
                }               /* end of if(atexit(tty_atexit) < 0) */
237
 
        }
238
 
 
239
 
        /* ignore return from nice, but lower our priority */
240
 
        int ignore __attribute__ ((unused)) = nice(19);
241
 
 
242
 
        /* while no signal, we loop around */
243
 
        int done = 0;
244
 
        while (!done) {
245
 
                struct timeval interval;
246
 
                fd_set t_readfds;
247
 
                fd_set t_writefds;
248
 
                fd_set t_exceptfds;
249
 
                /*
250
 
                 * We still use a blocked signal, and check for SIGCHLD every
251
 
                 * loop, since waiting infinitely did not really help the load
252
 
                 * when running, say, top. 
253
 
                 */
254
 
                interval.tv_sec = 0;
255
 
                interval.tv_usec = 200000;      /* so, check for signals every 200 milli
256
 
                                                   seconds */
257
 
 
258
 
                t_readfds = readfds;
259
 
                t_writefds = writefds;
260
 
                t_exceptfds = exceptfds;
261
 
 
262
 
                /* check for the signal */
263
 
                retval = sigtimedwait(&signal_set, &signalinfo, &timeout);
264
 
 
265
 
                if (retval == SIGCHLD) {
266
 
                        /* child terminated */
267
 
                        done = 1;       /* in case they do not close off their
268
 
                                           file descriptors */
269
 
                } else {
270
 
                        if (retval < 0) {
271
 
                                if (errno != EAGAIN) {
272
 
                                        perror("sigtimedwait");
273
 
                                        fflush(stdout);
274
 
                                        fflush(stderr);
275
 
                                        exit(EX_IOERR);
276
 
                                } else {
277
 
                                        /* No signal in set was delivered within the timeout period specified */
278
 
                                }
279
 
                        }
280
 
                }               /* end of else */
281
 
 
282
 
                if (select
283
 
                    (pty_master + 1, &t_readfds, &t_writefds, &t_exceptfds,
284
 
                     &interval) < 0) {
285
 
                        perror("Select:");
286
 
                        fflush(stdout);
287
 
                        fflush(stderr);
288
 
                        exit(EX_IOERR);
289
 
                }
290
 
 
291
 
                if (FD_ISSET(pty_master, &t_readfds)) {
292
 
                        retval = read(pty_master, buf, (unsigned int)16384);
293
 
                        if (retval < 0) {
294
 
                                if (errno != EINTR && errno != EAGAIN) {        /* Nothing left to read?  */
295
 
                                        fflush(stdout);
296
 
                                        fflush(stderr);
297
 
                                        /* fprintf(stderr, "DEBUG: %d: Nothing left to read?\n", __LINE__); */
298
 
                                        exit(EXIT_SUCCESS);
299
 
                                }       /* end of else */
300
 
                        } /* end of if(retval < 0) */
301
 
                        else {
302
 
                                if (retval == 0) {
303
 
                                        if (++err_count > 5) {  /* child closed connection */
304
 
                                                fflush(stdout);
305
 
                                                fflush(stderr);
306
 
                                                /*fprintf(stderr, "DEBUG: %d: child closed connection?\n", __LINE__); */
307
 
                                                exit(EXIT_SUCCESS);
308
 
                                        }
309
 
                                } /* end of if(retval == 0) */
310
 
                                else {
311
 
                                        ssize_t nleft = retval;
312
 
                                        ssize_t nwritten = 0;
313
 
                                        char *ptr = buf;
314
 
                                        while (nleft > 0) {
315
 
                                                if ((nwritten =
316
 
                                                     write(fileno(stdout), ptr,
317
 
                                                           (unsigned int)nleft))
318
 
                                                    <= 0) {
319
 
                                                        if (errno == EINTR) {
320
 
                                                                nwritten = 0;
321
 
                                                        } /* end of if(errno == EINTR) */
322
 
                                                        else {
323
 
                                                                perror("write");
324
 
                                                                fflush(stdout);
325
 
                                                                fflush(stderr);
326
 
                                                                exit(EXIT_SUCCESS);
327
 
                                                        }       /* end of else */
328
 
                                                }       /* end of if((nwritten = write(sockfd, ptr, nleft)) <= 0) */
329
 
                                                nleft -= nwritten;
330
 
                                                ptr += nwritten;
331
 
                                        }       /* end of while(nleft > 0) */
332
 
 
333
 
                                        /* fprintf(stderr, "DEBUG: %d: wrote %d\n", __LINE__, retval); */
334
 
                                        fflush(stdout);
335
 
                                }       /* end of else */
336
 
                        }       /* end of else */
337
 
                }
338
 
                if (FD_ISSET(fileno(stdin), &t_readfds)) {
339
 
                        if (FD_ISSET(pty_master, &t_writefds)) {
340
 
                                retval =
341
 
                                    read(fileno(stdin), buf,
342
 
                                         (unsigned int)16384);
343
 
                                if (retval < 0) {
344
 
                                        if (errno != EINTR && errno != EAGAIN) {        /* Nothing left to read?  */
345
 
                                                fflush(stdout);
346
 
                                                fflush(stderr);
347
 
                                                exit(EXIT_SUCCESS);
348
 
                                        }       /* end of else */
349
 
                                } /* end of if(retval < 0) */
350
 
                                else {
351
 
                                        if (retval == 0) {
352
 
                                                if (++err_count > 5) {  /* lost controlling tty */
353
 
                                                        fflush(stdout);
354
 
                                                        fflush(stderr);
355
 
                                                        exit(EXIT_SUCCESS);
356
 
                                                }
357
 
                                        } /* end of if(retval == 0) */
358
 
                                        else {
359
 
                                                ssize_t nleft = retval;
360
 
                                                ssize_t nwritten = 0;
361
 
                                                char *ptr = buf;
362
 
                                                while (nleft > 0) {
363
 
                                                        if ((nwritten =
364
 
                                                             write(pty_master,
365
 
                                                                   ptr,
366
 
                                                                   (unsigned
367
 
                                                                    int)nleft))
368
 
                                                            <= 0) {
369
 
                                                                if (errno ==
370
 
                                                                    EINTR) {
371
 
                                                                        nwritten
372
 
                                                                            = 0;
373
 
                                                                } /* end of if(errno == EINTR) */
374
 
                                                                else {
375
 
                                                                        perror
376
 
                                                                            ("write");
377
 
                                                                        fflush
378
 
                                                                            (stdout);
379
 
                                                                        fflush
380
 
                                                                            (stderr);
381
 
                                                                        exit(EXIT_SUCCESS);
382
 
                                                                }       /* end of else */
383
 
                                                        }       /* end of if((nwritten = write(sockfd, ptr, nleft)) <= 0) */
384
 
                                                        nleft -= nwritten;
385
 
                                                        ptr += nwritten;
386
 
                                                }       /* end of while(nleft > 0) */
387
 
 
388
 
                                                fflush(stdout);
389
 
                                        }       /* end of else */
390
 
                                }       /* end of else */
391
 
                        }       /* end of if(FD_ISSET(pty_master, &writefds)) */
392
 
                }               /* something to read on stdin */
393
 
        }                       /* Loop */
394
 
 
395
 
        fflush(stdout);
396
 
        fflush(stderr);
397
 
 
398
 
        exit(EXIT_SUCCESS);
399
 
}                               /* end of main() */