source: trunk/debathena/third/schroot/sbuild/sbuild-ctty.cc @ 24167

Revision 24167, 2.8 KB checked in by broder, 15 years ago (diff)
Import schroot upstream into subversion.
Line 
1/* Copyright © 2006-2007  Roger Leigh <rleigh@debian.org>
2 *
3 * schroot is free software: you can redistribute it and/or modify it
4 * under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * schroot is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program.  If not, see
15 * <http://www.gnu.org/licenses/>.
16 *
17 *********************************************************************/
18
19#include <config.h>
20
21#include "sbuild-ctty.h"
22
23#include <cerrno>
24#include <cstring>
25
26#include <ext/stdio_filebuf.h>
27
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <fcntl.h>
31#include <unistd.h>
32
33using namespace sbuild;
34
35namespace
36{
37
38  typedef std::pair<ctty_error_code,const char *> emap;
39
40  /**
41   * This is a list of the supported error codes.  It's used to
42   * construct the real error codes map.
43   */
44  emap init_errors[] =
45    {
46      emap(CTTY_CLOEXEC, N_("The controlling terminal close-on-execute flag could not be set")),
47      emap(CTTY_DUP,     N_("The controlling terminal file descriptor could not be duplicated"))
48    };
49
50  /**
51   * Set close-on-exec flag.  An error will be thrown on failure.
52   *
53   * @param fd the file descriptor to set.
54   */
55  void
56  set_cloexec (int fd)
57  {
58    int flags = fcntl(fd, F_GETFD);
59    flags |= FD_CLOEXEC;
60    if (fcntl(fd, F_SETFD, flags) < 0)
61      throw ctty_error(CTTY_CLOEXEC, strerror(errno));
62  }
63
64  /**
65   * Open the controlling terminal and return its file descriptor.
66   *
67   * @returns the CTTY fd, or -1 on failure.
68   */
69  int
70  open_ctty ()
71  {
72    int ctty = open("/dev/tty", O_RDWR|O_NOCTTY);
73    if (ctty >= 0)
74      {
75        set_cloexec(ctty);
76      }
77    else
78      {
79        ctty = -1;
80      }
81
82    return ctty;
83  }
84
85}
86
87template<>
88error<ctty_error_code>::map_type
89error<ctty_error_code>::error_strings
90(init_errors,
91 init_errors + (sizeof(init_errors) / sizeof(init_errors[0])));
92
93const int sbuild::CTTY_FILENO(open_ctty());
94
95namespace
96{
97
98  /**
99   * Get the file descriptor for cttybuf.  An error will be thrown on
100   * failure.
101   *
102   * @returns the CTTY_FILENO file descriptor if there is a CTTY, or a
103   * duplicated file descriptor for stdin otherwise.
104   */
105  int
106  cttybuf_fd ()
107  {
108    int ctty = CTTY_FILENO;
109
110    if (ctty < 0)
111      {
112        ctty = dup(STDIN_FILENO);
113
114        if (ctty < 0)
115          throw ctty_error(CTTY_DUP, strerror(errno));
116
117        set_cloexec(ctty);
118      }
119
120    return ctty;
121  }
122
123  /// A streambuf for cctty.
124  __gnu_cxx::stdio_filebuf<char> cttybuf(cttybuf_fd(),
125                                         std::ios::in|std::ios::out);
126
127}
128
129std::iostream sbuild::cctty(&cttybuf);
Note: See TracBrowser for help on using the repository browser.