1 /*****************************************************************************
2  *  Written by Chris Dunlap <cdunlap@llnl.gov>.
3  *  Copyright (C) 2007-2018 Lawrence Livermore National Security, LLC.
4  *  Copyright (C) 2001-2007 The Regents of the University of California.
5  *  UCRL-CODE-2002-009.
6  *
7  *  This file is part of ConMan: The Console Manager.
8  *  For details, see <https://dun.github.io/conman/>.
9  *
10  *  ConMan is free software: you can redistribute it and/or modify it under
11  *  the terms of the GNU General Public License as published by the Free
12  *  Software Foundation, either version 3 of the License, or (at your option)
13  *  any later version.
14  *
15  *  ConMan is distributed in the hope that it will be useful, but WITHOUT
16  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18  *  for more details.
19  *
20  *  You should have received a copy of the GNU General Public License along
21  *  with ConMan.  If not, see <http://www.gnu.org/licenses/>.
22  *****************************************************************************/
23 
24 
25 #if HAVE_CONFIG_H
26 #  include <config.h>
27 #endif /* HAVE_CONFIG_H */
28 
29 #include <assert.h>
30 #include <errno.h>
31 #include <stdlib.h>
32 #include <termios.h>
33 #include <unistd.h>
34 #include "common.h"
35 #include "log.h"
36 #include "util-str.h"
37 #include "util.h"
38 
39 
40 const char *conman_license = \
41     "ConMan: The Console Manager\n"                                           \
42     "https://dun.github.io/conman/\n"                                         \
43     "\n"                                                                      \
44     "Written by Chris Dunlap <cdunlap@llnl.gov>.\n"                           \
45     "Copyright (C) 2007-2018 Lawrence Livermore National Security, LLC.\n"    \
46     "Copyright (C) 2001-2007 The Regents of the University of California.\n"  \
47     "\n"                                                                      \
48     "ConMan is free software: you can redistribute it and/or modify it\n"     \
49     "under the terms of the GNU General Public License as published by\n"     \
50     "the Free Software Foundation; either version 3 of the License, or\n"     \
51     "(at your option) any later version.\n"                                   \
52     "\n";
53 
54 
55 char *proto_strs[] = {
56 /*
57  *  Keep strings in sync w/ common.h:proto_toks enum.
58  *  These must be sorted in a case-insensitive manner.
59  */
60     "BROADCAST",
61     "CODE",
62     "CONNECT",
63     "CONSOLE",
64     "ERROR",
65     "FORCE",
66     "HELLO",
67     "JOIN",
68     "MESSAGE",
69     "MONITOR",
70     "OK",
71     "OPTION",
72     "QUERY",
73     "QUIET",
74     "REGEX",
75     "RESET",
76     "TTY",
77     "USER",
78     NULL
79 };
80 
81 
create_req(void)82 req_t * create_req(void)
83 {
84 /*  Creates and returns a request struct.
85  */
86     req_t *req;
87 
88     if (!(req = malloc(sizeof(req_t))))
89         out_of_memory();
90     req->sd = -1;
91     req->user = NULL;
92     req->tty = NULL;
93     req->fqdn = NULL;
94     req->host = NULL;
95     req->ip = NULL;
96     req->port = 0;
97     req->consoles = list_create((ListDelF) destroy_string);
98     req->command = CONMAN_CMD_NONE;
99     req->enableBroadcast = 0;
100     req->enableEcho = 0;
101     req->enableForce = 0;
102     req->enableJoin = 0;
103     req->enableQuiet = 0;
104     req->enableRegex = 0;
105     req->enableReset = 0;
106     return(req);
107 }
108 
109 
destroy_req(req_t * req)110 void destroy_req(req_t *req)
111 {
112 /*  Destroys a request struct.
113  */
114     if (!req)
115         return;
116 
117     if (req->sd >= 0) {
118         if (close(req->sd) < 0)
119             log_err(errno, "close() failed on fd=%d", req->sd);
120         req->sd = -1;
121     }
122     if (req->user)
123         free(req->user);
124     if (req->tty)
125         free(req->tty);
126     if (req->fqdn)
127         free(req->fqdn);
128     if (req->host)
129         free(req->host);
130     if (req->ip)
131         free(req->ip);
132     if (req->consoles)
133         list_destroy(req->consoles);
134 
135     free(req);
136     return;
137 }
138 
139 
get_tty_mode(struct termios * tty,int fd)140 void get_tty_mode(struct termios *tty, int fd)
141 {
142 /*  Gets the tty values associated with 'fd' and stores them in 'tty'.
143  */
144     assert(fd >= 0);
145     assert(tty != NULL);
146 
147     if (!isatty(fd))
148         return;
149     if (tcgetattr(fd, tty) < 0)
150         log_err(errno, "tcgetattr() failed on fd=%d", fd);
151     return;
152 }
153 
154 
set_tty_mode(struct termios * tty,int fd)155 void set_tty_mode(struct termios *tty, int fd)
156 {
157 /*  Sets the tty values associated with 'fd' to those stored in 'tty'.
158  *
159  *  FIXME: tcsetattr() returns 0 (success) if it is able to perform ANY of the
160  *    requested actions.  Therefore, after calling tcsetattr(), one must call
161  *    tcgetattr() and compare the actual terminal's attributes to the desired
162  *    attributes to detect any differences.  (APUE2 18.4)
163  */
164     assert(fd >= 0);
165     assert(tty != NULL);
166 
167     if (!isatty(fd))
168         return;
169     if (tcsetattr(fd, TCSAFLUSH, tty) < 0)
170         log_err(errno, "tcgetattr() failed on fd=%d", fd);
171     return;
172 }
173 
174 
get_tty_raw(struct termios * tty,int fd)175 void get_tty_raw(struct termios *tty, int fd)
176 {
177 /*  Gets the tty values associated with 'fd' and stores them in 'tty',
178  *    adjusting them to reflect the device is operating in "raw" mode.
179  *  Note that the 'fd' device is not placed in raw mode by this call;
180  *    to do so, invoke set_tty_mode() with the updated termios struct.
181  */
182     assert(tty != NULL);
183 
184     get_tty_mode(tty, fd);
185 
186     /*  Disable SIGINT on BREAK, CR-to-NL, input parity check,
187      *    stripping 8th bit on input, and output flow control.
188      */
189     tty->c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
190 
191     /*  Disable output processing.
192      */
193     tty->c_oflag &= ~(OPOST);
194 
195     /*  Set 8 bits/char.
196      */
197     tty->c_cflag &= ~CSIZE;
198     tty->c_cflag |= CS8;
199 
200     /*  Disable parity checking.
201      */
202     tty->c_cflag &= ~PARENB;
203 
204     /*  Ignore modem status lines for locally attached device.
205      */
206     tty->c_cflag |= CLOCAL;
207 
208     /*  Disable echo, canonical mode, extended input processing, signal chars.
209      */
210     tty->c_lflag &= ~(ECHO | ECHOCTL | ICANON | IEXTEN | ISIG);
211 
212     /*  read() does not return until data is present (may block indefinitely).
213      */
214     tty->c_cc[VMIN] = 1;
215     tty->c_cc[VTIME] = 0;
216     return;
217 }
218