Deleted Added
full compact
main.c (22989) main.c (26415)
1/*-
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char copyright[] =
36"@(#) Copyright (c) 1980, 1993\n\
37 The Regents of the University of California. All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41/*static char sccsid[] = "from: @(#)main.c 8.1 (Berkeley) 6/20/93";*/
1/*-
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char copyright[] =
36"@(#) Copyright (c) 1980, 1993\n\
37 The Regents of the University of California. All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41/*static char sccsid[] = "from: @(#)main.c 8.1 (Berkeley) 6/20/93";*/
42static char rcsid[] = "$Id$";
42static char rcsid[] = "$Id: main.c,v 1.19 1997/02/22 14:21:39 peter Exp $";
43#endif /* not lint */
44
45#include <sys/param.h>
46#include <sys/stat.h>
47#include <sys/ioctl.h>
48#include <sys/resource.h>
49#include <sys/ttydefaults.h>
50#include <sys/utsname.h>
51#include <errno.h>
52#include <signal.h>
53#include <fcntl.h>
54#include <time.h>
55#include <ctype.h>
56#include <fcntl.h>
57#include <libutil.h>
58#include <locale.h>
59#include <setjmp.h>
60#include <signal.h>
61#include <stdlib.h>
62#include <string.h>
63#include <syslog.h>
64#include <termios.h>
65#include <time.h>
66#include <unistd.h>
67
68#include "gettytab.h"
69#include "pathnames.h"
70#include "extern.h"
71
72/*
73 * Set the amount of running time that getty should accumulate
74 * before deciding that something is wrong and exit.
75 */
76#define GETTY_TIMEOUT 60 /* seconds */
77
78#undef CTRL
79#define CTRL(x) (x&037)
80
81/* defines for auto detection of incoming PPP calls (->PAP/CHAP) */
82
83#define PPP_FRAME 0x7e /* PPP Framing character */
84#define PPP_STATION 0xff /* "All Station" character */
85#define PPP_ESCAPE 0x7d /* Escape Character */
86#define PPP_CONTROL 0x03 /* PPP Control Field */
87#define PPP_CONTROL_ESCAPED 0x23 /* PPP Control Field, escaped */
88#define PPP_LCP_HI 0xc0 /* LCP protocol - high byte */
89#define PPP_LCP_LOW 0x21 /* LCP protocol - low byte */
90
91struct termios tmode, omode;
92
93int crmod, digit, lower, upper;
94
95char hostname[MAXHOSTNAMELEN];
96char name[MAXLOGNAME*3];
97char dev[] = _PATH_DEV;
98char ttyn[32];
99
100#define OBUFSIZ 128
101#define TABBUFSIZ 512
102
103char defent[TABBUFSIZ];
104char tabent[TABBUFSIZ];
105
106char *env[128];
107
108char partab[] = {
109 0001,0201,0201,0001,0201,0001,0001,0201,
110 0202,0004,0003,0205,0005,0206,0201,0001,
111 0201,0001,0001,0201,0001,0201,0201,0001,
112 0001,0201,0201,0001,0201,0001,0001,0201,
113 0200,0000,0000,0200,0000,0200,0200,0000,
114 0000,0200,0200,0000,0200,0000,0000,0200,
115 0000,0200,0200,0000,0200,0000,0000,0200,
116 0200,0000,0000,0200,0000,0200,0200,0000,
117 0200,0000,0000,0200,0000,0200,0200,0000,
118 0000,0200,0200,0000,0200,0000,0000,0200,
119 0000,0200,0200,0000,0200,0000,0000,0200,
120 0200,0000,0000,0200,0000,0200,0200,0000,
121 0000,0200,0200,0000,0200,0000,0000,0200,
122 0200,0000,0000,0200,0000,0200,0200,0000,
123 0200,0000,0000,0200,0000,0200,0200,0000,
124 0000,0200,0200,0000,0200,0000,0000,0201
125};
126
127#define ERASE tmode.c_cc[VERASE]
128#define KILL tmode.c_cc[VKILL]
129#define EOT tmode.c_cc[VEOF]
130
131static void dingdong __P((int));
132static int getname __P((void));
133static void interrupt __P((int));
134static void oflush __P((void));
135static void prompt __P((void));
136static void putchr __P((int));
137static void putf __P((const char *));
138static void putpad __P((const char *));
139static void puts __P((const char *));
140static void timeoverrun __P((int));
141static char *getline __P((int));
142static void setttymode __P((const char *, int));
143static void setdefttymode __P((const char *));
144static int opentty __P((const char *, int));
145
146int main __P((int, char **));
147
148jmp_buf timeout;
149
150static void
151dingdong(signo)
152 int signo;
153{
154 alarm(0);
155 longjmp(timeout, 1);
156}
157
158jmp_buf intrupt;
159
160static void
161interrupt(signo)
162 int signo;
163{
164 longjmp(intrupt, 1);
165}
166
167/*
168 * Action to take when getty is running too long.
169 */
170static void
171timeoverrun(signo)
172 int signo;
173{
174
175 syslog(LOG_ERR, "getty exiting due to excessive running time\n");
176 exit(1);
177}
178
179int
180main(argc, argv)
181 int argc;
182 char **argv;
183{
184 extern char **environ;
185 const char *tname;
186 int repcnt = 0, failopenlogged = 0;
187 int first_sleep = 1, first_time = 1;
188 struct rlimit limit;
189 int rval;
190
191 signal(SIGINT, SIG_IGN);
192 signal(SIGQUIT, SIG_IGN);
193
194 openlog("getty", LOG_ODELAY|LOG_CONS|LOG_PID, LOG_AUTH);
195 gethostname(hostname, sizeof(hostname));
196 if (hostname[0] == '\0')
197 strcpy(hostname, "Amnesiac");
198
199 /*
200 * Limit running time to deal with broken or dead lines.
201 */
202 (void)signal(SIGXCPU, timeoverrun);
203 limit.rlim_max = RLIM_INFINITY;
204 limit.rlim_cur = GETTY_TIMEOUT;
205 (void)setrlimit(RLIMIT_CPU, &limit);
206
207 gettable("default", defent);
208 gendefaults();
209 tname = "default";
210 if (argc > 1)
211 tname = argv[1];
212
213 /*
214 * The following is a work around for vhangup interactions
215 * which cause great problems getting window systems started.
216 * If the tty line is "-", we do the old style getty presuming
217 * that the file descriptors are already set up for us.
218 * J. Gettys - MIT Project Athena.
219 */
220 if (argc <= 2 || strcmp(argv[2], "-") == 0)
221 strcpy(ttyn, ttyname(STDIN_FILENO));
222 else {
223 int i;
224
225 strcpy(ttyn, dev);
226 strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
227 if (strcmp(argv[0], "+") != 0) {
228 chown(ttyn, 0, 0);
229 chmod(ttyn, 0600);
230 revoke(ttyn);
231
232 gettable(tname, tabent);
233
234 /* Init modem sequence has been specified
235 */
236 if (IC) {
237 if (!opentty(ttyn, O_RDWR|O_NONBLOCK))
238 exit(1);
239 setdefttymode(tname);
240 if (getty_chat(IC, CT, DC) > 0) {
241 syslog(LOG_ERR, "modem init problem on %s", ttyn);
242 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
243 exit(1);
244 }
245 }
246
247 if (AC) {
248 int i, rfds;
249 struct timeval timeout;
250
251 if (!opentty(ttyn, O_RDWR|O_NONBLOCK))
252 exit(1);
253 setdefttymode(tname);
254 rfds = 1 << 0; /* FD_SET */
255 timeout.tv_sec = RT;
256 timeout.tv_usec = 0;
257 i = select(32, (fd_set*)&rfds, (fd_set*)NULL,
258 (fd_set*)NULL, RT ? &timeout : NULL);
259 if (i < 0) {
260 syslog(LOG_ERR, "select %s: %m", ttyn);
261 } else if (i == 0) {
262 syslog(LOG_NOTICE, "recycle tty %s", ttyn);
263 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
264 exit(0); /* recycle for init */
265 }
266 i = getty_chat(AC, CT, DC);
267 if (i > 0) {
268 syslog(LOG_ERR, "modem answer problem on %s", ttyn);
269 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
270 exit(1);
271 }
272 } else { /* blocking open */
273 if (!opentty(ttyn, O_RDWR))
274 exit(1);
275 }
276 }
277 }
278
279 /* Start with default tty settings */
280 if (tcgetattr(STDIN_FILENO, &tmode) < 0) {
281 syslog(LOG_ERR, "tcgetattr %s: %m", ttyn);
282 exit(1);
283 }
284 /*
285 * Don't rely on the driver too much, and initialize crucial
286 * things according to <sys/ttydefaults.h>. Avoid clobbering
287 * the c_cc[] settings however, the console drivers might wish
288 * to leave their idea of the preferred VERASE key value
289 * there.
290 */
291 tmode.c_iflag = TTYDEF_IFLAG;
292 tmode.c_oflag = TTYDEF_OFLAG;
293 tmode.c_lflag = TTYDEF_LFLAG;
294 tmode.c_cflag = TTYDEF_CFLAG;
295 omode = tmode;
296
297 for (;;) {
298
299 /*
300 * if a delay was specified then sleep for that
301 * number of seconds before writing the initial prompt
302 */
303 if (first_sleep && DE) {
304 sleep(DE);
305 /* remove any noise */
306 (void)tcflush(STDIN_FILENO, TCIOFLUSH);
307 }
308 first_sleep = 0;
309
310 setttymode(tname, 0);
311 if (AB) {
312 tname = autobaud();
313 continue;
314 }
315 if (PS) {
316 tname = portselector();
317 continue;
318 }
319 if (CL && *CL)
320 putpad(CL);
321 edithost(HE);
322
323 /* if this is the first time through this, and an
324 issue file has been given, then send it */
325 if (first_time && IF) {
326 int fd;
327
328 if ((fd = open(IF, O_RDONLY)) != -1) {
329 char * cp;
330
331 while ((cp = getline(fd)) != NULL) {
332 putf(cp);
333 }
334 close(fd);
335 }
336 }
337 first_time = 0;
338
339 if (IM && *IM)
340 putf(IM);
341 if (setjmp(timeout)) {
342 cfsetispeed(&tmode, B0);
343 cfsetospeed(&tmode, B0);
344 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
345 exit(1);
346 }
347 if (TO) {
348 signal(SIGALRM, dingdong);
349 alarm(TO);
350 }
351 if ((rval = getname()) == 2) {
43#endif /* not lint */
44
45#include <sys/param.h>
46#include <sys/stat.h>
47#include <sys/ioctl.h>
48#include <sys/resource.h>
49#include <sys/ttydefaults.h>
50#include <sys/utsname.h>
51#include <errno.h>
52#include <signal.h>
53#include <fcntl.h>
54#include <time.h>
55#include <ctype.h>
56#include <fcntl.h>
57#include <libutil.h>
58#include <locale.h>
59#include <setjmp.h>
60#include <signal.h>
61#include <stdlib.h>
62#include <string.h>
63#include <syslog.h>
64#include <termios.h>
65#include <time.h>
66#include <unistd.h>
67
68#include "gettytab.h"
69#include "pathnames.h"
70#include "extern.h"
71
72/*
73 * Set the amount of running time that getty should accumulate
74 * before deciding that something is wrong and exit.
75 */
76#define GETTY_TIMEOUT 60 /* seconds */
77
78#undef CTRL
79#define CTRL(x) (x&037)
80
81/* defines for auto detection of incoming PPP calls (->PAP/CHAP) */
82
83#define PPP_FRAME 0x7e /* PPP Framing character */
84#define PPP_STATION 0xff /* "All Station" character */
85#define PPP_ESCAPE 0x7d /* Escape Character */
86#define PPP_CONTROL 0x03 /* PPP Control Field */
87#define PPP_CONTROL_ESCAPED 0x23 /* PPP Control Field, escaped */
88#define PPP_LCP_HI 0xc0 /* LCP protocol - high byte */
89#define PPP_LCP_LOW 0x21 /* LCP protocol - low byte */
90
91struct termios tmode, omode;
92
93int crmod, digit, lower, upper;
94
95char hostname[MAXHOSTNAMELEN];
96char name[MAXLOGNAME*3];
97char dev[] = _PATH_DEV;
98char ttyn[32];
99
100#define OBUFSIZ 128
101#define TABBUFSIZ 512
102
103char defent[TABBUFSIZ];
104char tabent[TABBUFSIZ];
105
106char *env[128];
107
108char partab[] = {
109 0001,0201,0201,0001,0201,0001,0001,0201,
110 0202,0004,0003,0205,0005,0206,0201,0001,
111 0201,0001,0001,0201,0001,0201,0201,0001,
112 0001,0201,0201,0001,0201,0001,0001,0201,
113 0200,0000,0000,0200,0000,0200,0200,0000,
114 0000,0200,0200,0000,0200,0000,0000,0200,
115 0000,0200,0200,0000,0200,0000,0000,0200,
116 0200,0000,0000,0200,0000,0200,0200,0000,
117 0200,0000,0000,0200,0000,0200,0200,0000,
118 0000,0200,0200,0000,0200,0000,0000,0200,
119 0000,0200,0200,0000,0200,0000,0000,0200,
120 0200,0000,0000,0200,0000,0200,0200,0000,
121 0000,0200,0200,0000,0200,0000,0000,0200,
122 0200,0000,0000,0200,0000,0200,0200,0000,
123 0200,0000,0000,0200,0000,0200,0200,0000,
124 0000,0200,0200,0000,0200,0000,0000,0201
125};
126
127#define ERASE tmode.c_cc[VERASE]
128#define KILL tmode.c_cc[VKILL]
129#define EOT tmode.c_cc[VEOF]
130
131static void dingdong __P((int));
132static int getname __P((void));
133static void interrupt __P((int));
134static void oflush __P((void));
135static void prompt __P((void));
136static void putchr __P((int));
137static void putf __P((const char *));
138static void putpad __P((const char *));
139static void puts __P((const char *));
140static void timeoverrun __P((int));
141static char *getline __P((int));
142static void setttymode __P((const char *, int));
143static void setdefttymode __P((const char *));
144static int opentty __P((const char *, int));
145
146int main __P((int, char **));
147
148jmp_buf timeout;
149
150static void
151dingdong(signo)
152 int signo;
153{
154 alarm(0);
155 longjmp(timeout, 1);
156}
157
158jmp_buf intrupt;
159
160static void
161interrupt(signo)
162 int signo;
163{
164 longjmp(intrupt, 1);
165}
166
167/*
168 * Action to take when getty is running too long.
169 */
170static void
171timeoverrun(signo)
172 int signo;
173{
174
175 syslog(LOG_ERR, "getty exiting due to excessive running time\n");
176 exit(1);
177}
178
179int
180main(argc, argv)
181 int argc;
182 char **argv;
183{
184 extern char **environ;
185 const char *tname;
186 int repcnt = 0, failopenlogged = 0;
187 int first_sleep = 1, first_time = 1;
188 struct rlimit limit;
189 int rval;
190
191 signal(SIGINT, SIG_IGN);
192 signal(SIGQUIT, SIG_IGN);
193
194 openlog("getty", LOG_ODELAY|LOG_CONS|LOG_PID, LOG_AUTH);
195 gethostname(hostname, sizeof(hostname));
196 if (hostname[0] == '\0')
197 strcpy(hostname, "Amnesiac");
198
199 /*
200 * Limit running time to deal with broken or dead lines.
201 */
202 (void)signal(SIGXCPU, timeoverrun);
203 limit.rlim_max = RLIM_INFINITY;
204 limit.rlim_cur = GETTY_TIMEOUT;
205 (void)setrlimit(RLIMIT_CPU, &limit);
206
207 gettable("default", defent);
208 gendefaults();
209 tname = "default";
210 if (argc > 1)
211 tname = argv[1];
212
213 /*
214 * The following is a work around for vhangup interactions
215 * which cause great problems getting window systems started.
216 * If the tty line is "-", we do the old style getty presuming
217 * that the file descriptors are already set up for us.
218 * J. Gettys - MIT Project Athena.
219 */
220 if (argc <= 2 || strcmp(argv[2], "-") == 0)
221 strcpy(ttyn, ttyname(STDIN_FILENO));
222 else {
223 int i;
224
225 strcpy(ttyn, dev);
226 strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
227 if (strcmp(argv[0], "+") != 0) {
228 chown(ttyn, 0, 0);
229 chmod(ttyn, 0600);
230 revoke(ttyn);
231
232 gettable(tname, tabent);
233
234 /* Init modem sequence has been specified
235 */
236 if (IC) {
237 if (!opentty(ttyn, O_RDWR|O_NONBLOCK))
238 exit(1);
239 setdefttymode(tname);
240 if (getty_chat(IC, CT, DC) > 0) {
241 syslog(LOG_ERR, "modem init problem on %s", ttyn);
242 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
243 exit(1);
244 }
245 }
246
247 if (AC) {
248 int i, rfds;
249 struct timeval timeout;
250
251 if (!opentty(ttyn, O_RDWR|O_NONBLOCK))
252 exit(1);
253 setdefttymode(tname);
254 rfds = 1 << 0; /* FD_SET */
255 timeout.tv_sec = RT;
256 timeout.tv_usec = 0;
257 i = select(32, (fd_set*)&rfds, (fd_set*)NULL,
258 (fd_set*)NULL, RT ? &timeout : NULL);
259 if (i < 0) {
260 syslog(LOG_ERR, "select %s: %m", ttyn);
261 } else if (i == 0) {
262 syslog(LOG_NOTICE, "recycle tty %s", ttyn);
263 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
264 exit(0); /* recycle for init */
265 }
266 i = getty_chat(AC, CT, DC);
267 if (i > 0) {
268 syslog(LOG_ERR, "modem answer problem on %s", ttyn);
269 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
270 exit(1);
271 }
272 } else { /* blocking open */
273 if (!opentty(ttyn, O_RDWR))
274 exit(1);
275 }
276 }
277 }
278
279 /* Start with default tty settings */
280 if (tcgetattr(STDIN_FILENO, &tmode) < 0) {
281 syslog(LOG_ERR, "tcgetattr %s: %m", ttyn);
282 exit(1);
283 }
284 /*
285 * Don't rely on the driver too much, and initialize crucial
286 * things according to <sys/ttydefaults.h>. Avoid clobbering
287 * the c_cc[] settings however, the console drivers might wish
288 * to leave their idea of the preferred VERASE key value
289 * there.
290 */
291 tmode.c_iflag = TTYDEF_IFLAG;
292 tmode.c_oflag = TTYDEF_OFLAG;
293 tmode.c_lflag = TTYDEF_LFLAG;
294 tmode.c_cflag = TTYDEF_CFLAG;
295 omode = tmode;
296
297 for (;;) {
298
299 /*
300 * if a delay was specified then sleep for that
301 * number of seconds before writing the initial prompt
302 */
303 if (first_sleep && DE) {
304 sleep(DE);
305 /* remove any noise */
306 (void)tcflush(STDIN_FILENO, TCIOFLUSH);
307 }
308 first_sleep = 0;
309
310 setttymode(tname, 0);
311 if (AB) {
312 tname = autobaud();
313 continue;
314 }
315 if (PS) {
316 tname = portselector();
317 continue;
318 }
319 if (CL && *CL)
320 putpad(CL);
321 edithost(HE);
322
323 /* if this is the first time through this, and an
324 issue file has been given, then send it */
325 if (first_time && IF) {
326 int fd;
327
328 if ((fd = open(IF, O_RDONLY)) != -1) {
329 char * cp;
330
331 while ((cp = getline(fd)) != NULL) {
332 putf(cp);
333 }
334 close(fd);
335 }
336 }
337 first_time = 0;
338
339 if (IM && *IM)
340 putf(IM);
341 if (setjmp(timeout)) {
342 cfsetispeed(&tmode, B0);
343 cfsetospeed(&tmode, B0);
344 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
345 exit(1);
346 }
347 if (TO) {
348 signal(SIGALRM, dingdong);
349 alarm(TO);
350 }
351 if ((rval = getname()) == 2) {
352 oflush();
353 alarm(0);
352 execle(PP, "ppplogin", ttyn, (char *) 0, env);
353 syslog(LOG_ERR, "%s: %m", PP);
354 exit(1);
355 } else if (rval) {
356 register int i;
357
358 oflush();
359 alarm(0);
360 signal(SIGALRM, SIG_DFL);
361 if (name[0] == '-') {
362 puts("user names may not start with '-'.");
363 continue;
364 }
365 if (!(upper || lower || digit))
366 continue;
367 setflags(2);
368 if (crmod) {
369 tmode.c_iflag |= ICRNL;
370 tmode.c_oflag |= ONLCR;
371 }
372#if REALLY_OLD_TTYS
373 if (upper || UC)
374 tmode.sg_flags |= LCASE;
375 if (lower || LC)
376 tmode.sg_flags &= ~LCASE;
377#endif
378 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
379 syslog(LOG_ERR, "tcsetattr %s: %m", ttyn);
380 exit(1);
381 }
382 signal(SIGINT, SIG_DFL);
383 for (i = 0; environ[i] != (char *)0; i++)
384 env[i] = environ[i];
385 makeenv(&env[i]);
386
387 limit.rlim_max = RLIM_INFINITY;
388 limit.rlim_cur = RLIM_INFINITY;
389 (void)setrlimit(RLIMIT_CPU, &limit);
390 execle(LO, "login", "-p", name, (char *) 0, env);
391 syslog(LOG_ERR, "%s: %m", LO);
392 exit(1);
393 }
394 alarm(0);
395 signal(SIGALRM, SIG_DFL);
396 signal(SIGINT, SIG_IGN);
397 if (NX && *NX)
398 tname = NX;
399 }
400}
401
402static int
403opentty(const char *ttyn, int flags)
404{
405 int i, j = 0;
406 int failopenlogged = 0;
407
408 while (j < 10 && (i = open(ttyn, flags)) == -1)
409 {
410 if (((j % 10) == 0) && (errno != ENXIO || !failopenlogged)) {
411 syslog(LOG_ERR, "open %s: %m", ttyn);
412 failopenlogged = 1;
413 }
414 j++;
415 sleep(60);
416 }
417 if (i == -1) {
418 syslog(LOG_ERR, "open %s: %m", ttyn);
419 return 0;
420 }
421 else {
422 login_tty(i);
423 return 1;
424 }
425}
426
427static void
428setdefttymode(tname)
429 const char * tname;
430{
431 if (tcgetattr(STDIN_FILENO, &tmode) < 0) {
432 syslog(LOG_ERR, "tcgetattr %s: %m", ttyn);
433 exit(1);
434 }
435 tmode.c_iflag = TTYDEF_IFLAG;
436 tmode.c_oflag = TTYDEF_OFLAG;
437 tmode.c_lflag = TTYDEF_LFLAG;
438 tmode.c_cflag = TTYDEF_CFLAG;
439 omode = tmode;
440 setttymode(tname, 1);
441}
442
443static void
444setttymode(tname, raw)
445 const char * tname;
446 int raw;
447{
448 int off = 0;
449
450 gettable(tname, tabent);
451 if (OPset || EPset || APset)
452 APset++, OPset++, EPset++;
453 setdefaults();
454 (void)tcflush(STDIN_FILENO, TCIOFLUSH); /* clear out the crap */
455 ioctl(STDIN_FILENO, FIONBIO, &off); /* turn off non-blocking mode */
456 ioctl(STDIN_FILENO, FIOASYNC, &off); /* ditto for async mode */
457
458 if (IS)
459 cfsetispeed(&tmode, speed(IS));
460 else if (SP)
461 cfsetispeed(&tmode, speed(SP));
462 if (OS)
463 cfsetospeed(&tmode, speed(OS));
464 else if (SP)
465 cfsetospeed(&tmode, speed(SP));
466 setflags(0);
467 setchars();
468 if (raw)
469 cfmakeraw(&tmode);
470 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
471 syslog(LOG_ERR, "tcsetattr %s: %m", ttyn);
472 exit(1);
473 }
474}
475
476
477static int
478getname()
479{
480 register int c;
481 register char *np;
482 unsigned char cs;
483 int ppp_state = 0;
484 int ppp_connection = 0;
485
486 /*
487 * Interrupt may happen if we use CBREAK mode
488 */
489 if (setjmp(intrupt)) {
490 signal(SIGINT, SIG_IGN);
491 return (0);
492 }
493 signal(SIGINT, interrupt);
494 setflags(1);
495 prompt();
496 oflush();
497 if (PF > 0) {
498 sleep(PF);
499 PF = 0;
500 }
501 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
502 syslog(LOG_ERR, "%s: %m", ttyn);
503 exit(1);
504 }
505 crmod = digit = lower = upper = 0;
506 np = name;
507 for (;;) {
508 oflush();
509 if (read(STDIN_FILENO, &cs, 1) <= 0)
510 exit(0);
511 if ((c = cs&0177) == 0)
512 return (0);
513
514 /* PPP detection state machine..
515 Look for sequences:
516 PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or
517 PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC)
518 See RFC1662.
519 Derived from code from Michael Hancock, <michaelh@cet.co.jp>
520 and Erik 'PPP' Olson, <eriko@wrq.com>
521 */
522
523 if (PP && (cs == PPP_FRAME)) {
524 ppp_state = 1;
525 } else if (ppp_state == 1 && cs == PPP_STATION) {
526 ppp_state = 2;
527 } else if (ppp_state == 2 && cs == PPP_ESCAPE) {
528 ppp_state = 3;
529 } else if ((ppp_state == 2 && cs == PPP_CONTROL)
530 || (ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) {
531 ppp_state = 4;
532 } else if (ppp_state == 4 && cs == PPP_LCP_HI) {
533 ppp_state = 5;
534 } else if (ppp_state == 5 && cs == PPP_LCP_LOW) {
535 ppp_connection = 1;
536 break;
537 } else {
538 ppp_state = 0;
539 }
540
541 if (c == EOT || c == CTRL('d'))
542 exit(1);
543 if (c == '\r' || c == '\n' || np >= &name[sizeof name-1]) {
544 putf("\r\n");
545 break;
546 }
547 if (islower(c))
548 lower = 1;
549 else if (isupper(c))
550 upper = 1;
551 else if (c == ERASE || c == '\b' || c == 0177) {
552 if (np > name) {
553 np--;
554 if (cfgetospeed(&tmode) >= 1200)
555 puts("\b \b");
556 else
557 putchr(cs);
558 }
559 continue;
560 } else if (c == KILL || c == CTRL('u')) {
561 putchr('\r');
562 if (cfgetospeed(&tmode) < 1200)
563 putchr('\n');
564 /* this is the way they do it down under ... */
565 else if (np > name)
566 puts(" \r");
567 prompt();
568 np = name;
569 continue;
570 } else if (isdigit(c))
571 digit++;
572 if (IG && (c <= ' ' || c > 0176))
573 continue;
574 *np++ = c;
575 putchr(cs);
576 }
577 signal(SIGINT, SIG_IGN);
578 *np = 0;
579 if (c == '\r')
580 crmod = 1;
581 if ((upper && !lower && !LC) || UC)
582 for (np = name; *np; np++)
583 if (isupper(*np))
584 *np = tolower(*np);
585 return (1 + ppp_connection);
586}
587
588static void
589putpad(s)
590 register const char *s;
591{
592 register pad = 0;
593 speed_t ospeed = cfgetospeed(&tmode);
594
595 if (isdigit(*s)) {
596 while (isdigit(*s)) {
597 pad *= 10;
598 pad += *s++ - '0';
599 }
600 pad *= 10;
601 if (*s == '.' && isdigit(s[1])) {
602 pad += s[1] - '0';
603 s += 2;
604 }
605 }
606
607 puts(s);
608 /*
609 * If no delay needed, or output speed is
610 * not comprehensible, then don't try to delay.
611 */
612 if (pad == 0 || ospeed <= 0)
613 return;
614
615 /*
616 * Round up by a half a character frame, and then do the delay.
617 * Too bad there are no user program accessible programmed delays.
618 * Transmitting pad characters slows many terminals down and also
619 * loads the system.
620 */
621 pad = (pad * ospeed + 50000) / 100000;
622 while (pad--)
623 putchr(*PC);
624}
625
626static void
627puts(s)
628 register const char *s;
629{
630 while (*s)
631 putchr(*s++);
632}
633
634char outbuf[OBUFSIZ];
635int obufcnt = 0;
636
637static void
638putchr(cc)
639 int cc;
640{
641 char c;
642
643 c = cc;
644 if (!NP) {
645 c |= partab[c&0177] & 0200;
646 if (OP)
647 c ^= 0200;
648 }
649 if (!UB) {
650 outbuf[obufcnt++] = c;
651 if (obufcnt >= OBUFSIZ)
652 oflush();
653 } else
654 write(STDOUT_FILENO, &c, 1);
655}
656
657static void
658oflush()
659{
660 if (obufcnt)
661 write(STDOUT_FILENO, outbuf, obufcnt);
662 obufcnt = 0;
663}
664
665static void
666prompt()
667{
668
669 putf(LM);
670 if (CO)
671 putchr('\n');
672}
673
674
675static char *
676getline(fd)
677 int fd;
678{
679 int i = 0;
680 static char linebuf[512];
681
682 /*
683 * This is certainly slow, but it avoids having to include
684 * stdio.h unnecessarily. Issue files should be small anyway.
685 */
686 while (i < (sizeof linebuf - 3) && read(fd, linebuf+i, 1)==1) {
687 if (linebuf[i] == '\n') {
688 /* Don't rely on newline mode, assume raw */
689 linebuf[i++] = '\r';
690 linebuf[i++] = '\n';
691 linebuf[i] = '\0';
692 return linebuf;
693 }
694 ++i;
695 }
696 linebuf[i] = '\0';
697 return i ? linebuf : 0;
698}
699
700static void
701putf(cp)
702 register const char *cp;
703{
704 extern char editedhost[];
705 time_t t;
706 char *slash, db[100];
707
708 static struct utsname kerninfo;
709
710 if (!*kerninfo.sysname)
711 uname(&kerninfo);
712
713 while (*cp) {
714 if (*cp != '%') {
715 putchr(*cp++);
716 continue;
717 }
718 switch (*++cp) {
719
720 case 't':
721 slash = strrchr(ttyn, '/');
722 if (slash == (char *) 0)
723 puts(ttyn);
724 else
725 puts(&slash[1]);
726 break;
727
728 case 'h':
729 puts(editedhost);
730 break;
731
732 case 'd': {
733 t = (time_t)0;
734 (void)time(&t);
735 if (Lo)
736 (void)setlocale(LC_TIME, Lo);
737 (void)strftime(db, sizeof(db), "%+", localtime(&t));
738 puts(db);
739 break;
740
741 case 's':
742 puts(kerninfo.sysname);
743 break;
744
745 case 'm':
746 puts(kerninfo.machine);
747 break;
748
749 case 'r':
750 puts(kerninfo.release);
751 break;
752
753 case 'v':
754 puts(kerninfo.version);
755 break;
756 }
757
758 case '%':
759 putchr('%');
760 break;
761 }
762 cp++;
763 }
764}
354 execle(PP, "ppplogin", ttyn, (char *) 0, env);
355 syslog(LOG_ERR, "%s: %m", PP);
356 exit(1);
357 } else if (rval) {
358 register int i;
359
360 oflush();
361 alarm(0);
362 signal(SIGALRM, SIG_DFL);
363 if (name[0] == '-') {
364 puts("user names may not start with '-'.");
365 continue;
366 }
367 if (!(upper || lower || digit))
368 continue;
369 setflags(2);
370 if (crmod) {
371 tmode.c_iflag |= ICRNL;
372 tmode.c_oflag |= ONLCR;
373 }
374#if REALLY_OLD_TTYS
375 if (upper || UC)
376 tmode.sg_flags |= LCASE;
377 if (lower || LC)
378 tmode.sg_flags &= ~LCASE;
379#endif
380 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
381 syslog(LOG_ERR, "tcsetattr %s: %m", ttyn);
382 exit(1);
383 }
384 signal(SIGINT, SIG_DFL);
385 for (i = 0; environ[i] != (char *)0; i++)
386 env[i] = environ[i];
387 makeenv(&env[i]);
388
389 limit.rlim_max = RLIM_INFINITY;
390 limit.rlim_cur = RLIM_INFINITY;
391 (void)setrlimit(RLIMIT_CPU, &limit);
392 execle(LO, "login", "-p", name, (char *) 0, env);
393 syslog(LOG_ERR, "%s: %m", LO);
394 exit(1);
395 }
396 alarm(0);
397 signal(SIGALRM, SIG_DFL);
398 signal(SIGINT, SIG_IGN);
399 if (NX && *NX)
400 tname = NX;
401 }
402}
403
404static int
405opentty(const char *ttyn, int flags)
406{
407 int i, j = 0;
408 int failopenlogged = 0;
409
410 while (j < 10 && (i = open(ttyn, flags)) == -1)
411 {
412 if (((j % 10) == 0) && (errno != ENXIO || !failopenlogged)) {
413 syslog(LOG_ERR, "open %s: %m", ttyn);
414 failopenlogged = 1;
415 }
416 j++;
417 sleep(60);
418 }
419 if (i == -1) {
420 syslog(LOG_ERR, "open %s: %m", ttyn);
421 return 0;
422 }
423 else {
424 login_tty(i);
425 return 1;
426 }
427}
428
429static void
430setdefttymode(tname)
431 const char * tname;
432{
433 if (tcgetattr(STDIN_FILENO, &tmode) < 0) {
434 syslog(LOG_ERR, "tcgetattr %s: %m", ttyn);
435 exit(1);
436 }
437 tmode.c_iflag = TTYDEF_IFLAG;
438 tmode.c_oflag = TTYDEF_OFLAG;
439 tmode.c_lflag = TTYDEF_LFLAG;
440 tmode.c_cflag = TTYDEF_CFLAG;
441 omode = tmode;
442 setttymode(tname, 1);
443}
444
445static void
446setttymode(tname, raw)
447 const char * tname;
448 int raw;
449{
450 int off = 0;
451
452 gettable(tname, tabent);
453 if (OPset || EPset || APset)
454 APset++, OPset++, EPset++;
455 setdefaults();
456 (void)tcflush(STDIN_FILENO, TCIOFLUSH); /* clear out the crap */
457 ioctl(STDIN_FILENO, FIONBIO, &off); /* turn off non-blocking mode */
458 ioctl(STDIN_FILENO, FIOASYNC, &off); /* ditto for async mode */
459
460 if (IS)
461 cfsetispeed(&tmode, speed(IS));
462 else if (SP)
463 cfsetispeed(&tmode, speed(SP));
464 if (OS)
465 cfsetospeed(&tmode, speed(OS));
466 else if (SP)
467 cfsetospeed(&tmode, speed(SP));
468 setflags(0);
469 setchars();
470 if (raw)
471 cfmakeraw(&tmode);
472 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
473 syslog(LOG_ERR, "tcsetattr %s: %m", ttyn);
474 exit(1);
475 }
476}
477
478
479static int
480getname()
481{
482 register int c;
483 register char *np;
484 unsigned char cs;
485 int ppp_state = 0;
486 int ppp_connection = 0;
487
488 /*
489 * Interrupt may happen if we use CBREAK mode
490 */
491 if (setjmp(intrupt)) {
492 signal(SIGINT, SIG_IGN);
493 return (0);
494 }
495 signal(SIGINT, interrupt);
496 setflags(1);
497 prompt();
498 oflush();
499 if (PF > 0) {
500 sleep(PF);
501 PF = 0;
502 }
503 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
504 syslog(LOG_ERR, "%s: %m", ttyn);
505 exit(1);
506 }
507 crmod = digit = lower = upper = 0;
508 np = name;
509 for (;;) {
510 oflush();
511 if (read(STDIN_FILENO, &cs, 1) <= 0)
512 exit(0);
513 if ((c = cs&0177) == 0)
514 return (0);
515
516 /* PPP detection state machine..
517 Look for sequences:
518 PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or
519 PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC)
520 See RFC1662.
521 Derived from code from Michael Hancock, <michaelh@cet.co.jp>
522 and Erik 'PPP' Olson, <eriko@wrq.com>
523 */
524
525 if (PP && (cs == PPP_FRAME)) {
526 ppp_state = 1;
527 } else if (ppp_state == 1 && cs == PPP_STATION) {
528 ppp_state = 2;
529 } else if (ppp_state == 2 && cs == PPP_ESCAPE) {
530 ppp_state = 3;
531 } else if ((ppp_state == 2 && cs == PPP_CONTROL)
532 || (ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) {
533 ppp_state = 4;
534 } else if (ppp_state == 4 && cs == PPP_LCP_HI) {
535 ppp_state = 5;
536 } else if (ppp_state == 5 && cs == PPP_LCP_LOW) {
537 ppp_connection = 1;
538 break;
539 } else {
540 ppp_state = 0;
541 }
542
543 if (c == EOT || c == CTRL('d'))
544 exit(1);
545 if (c == '\r' || c == '\n' || np >= &name[sizeof name-1]) {
546 putf("\r\n");
547 break;
548 }
549 if (islower(c))
550 lower = 1;
551 else if (isupper(c))
552 upper = 1;
553 else if (c == ERASE || c == '\b' || c == 0177) {
554 if (np > name) {
555 np--;
556 if (cfgetospeed(&tmode) >= 1200)
557 puts("\b \b");
558 else
559 putchr(cs);
560 }
561 continue;
562 } else if (c == KILL || c == CTRL('u')) {
563 putchr('\r');
564 if (cfgetospeed(&tmode) < 1200)
565 putchr('\n');
566 /* this is the way they do it down under ... */
567 else if (np > name)
568 puts(" \r");
569 prompt();
570 np = name;
571 continue;
572 } else if (isdigit(c))
573 digit++;
574 if (IG && (c <= ' ' || c > 0176))
575 continue;
576 *np++ = c;
577 putchr(cs);
578 }
579 signal(SIGINT, SIG_IGN);
580 *np = 0;
581 if (c == '\r')
582 crmod = 1;
583 if ((upper && !lower && !LC) || UC)
584 for (np = name; *np; np++)
585 if (isupper(*np))
586 *np = tolower(*np);
587 return (1 + ppp_connection);
588}
589
590static void
591putpad(s)
592 register const char *s;
593{
594 register pad = 0;
595 speed_t ospeed = cfgetospeed(&tmode);
596
597 if (isdigit(*s)) {
598 while (isdigit(*s)) {
599 pad *= 10;
600 pad += *s++ - '0';
601 }
602 pad *= 10;
603 if (*s == '.' && isdigit(s[1])) {
604 pad += s[1] - '0';
605 s += 2;
606 }
607 }
608
609 puts(s);
610 /*
611 * If no delay needed, or output speed is
612 * not comprehensible, then don't try to delay.
613 */
614 if (pad == 0 || ospeed <= 0)
615 return;
616
617 /*
618 * Round up by a half a character frame, and then do the delay.
619 * Too bad there are no user program accessible programmed delays.
620 * Transmitting pad characters slows many terminals down and also
621 * loads the system.
622 */
623 pad = (pad * ospeed + 50000) / 100000;
624 while (pad--)
625 putchr(*PC);
626}
627
628static void
629puts(s)
630 register const char *s;
631{
632 while (*s)
633 putchr(*s++);
634}
635
636char outbuf[OBUFSIZ];
637int obufcnt = 0;
638
639static void
640putchr(cc)
641 int cc;
642{
643 char c;
644
645 c = cc;
646 if (!NP) {
647 c |= partab[c&0177] & 0200;
648 if (OP)
649 c ^= 0200;
650 }
651 if (!UB) {
652 outbuf[obufcnt++] = c;
653 if (obufcnt >= OBUFSIZ)
654 oflush();
655 } else
656 write(STDOUT_FILENO, &c, 1);
657}
658
659static void
660oflush()
661{
662 if (obufcnt)
663 write(STDOUT_FILENO, outbuf, obufcnt);
664 obufcnt = 0;
665}
666
667static void
668prompt()
669{
670
671 putf(LM);
672 if (CO)
673 putchr('\n');
674}
675
676
677static char *
678getline(fd)
679 int fd;
680{
681 int i = 0;
682 static char linebuf[512];
683
684 /*
685 * This is certainly slow, but it avoids having to include
686 * stdio.h unnecessarily. Issue files should be small anyway.
687 */
688 while (i < (sizeof linebuf - 3) && read(fd, linebuf+i, 1)==1) {
689 if (linebuf[i] == '\n') {
690 /* Don't rely on newline mode, assume raw */
691 linebuf[i++] = '\r';
692 linebuf[i++] = '\n';
693 linebuf[i] = '\0';
694 return linebuf;
695 }
696 ++i;
697 }
698 linebuf[i] = '\0';
699 return i ? linebuf : 0;
700}
701
702static void
703putf(cp)
704 register const char *cp;
705{
706 extern char editedhost[];
707 time_t t;
708 char *slash, db[100];
709
710 static struct utsname kerninfo;
711
712 if (!*kerninfo.sysname)
713 uname(&kerninfo);
714
715 while (*cp) {
716 if (*cp != '%') {
717 putchr(*cp++);
718 continue;
719 }
720 switch (*++cp) {
721
722 case 't':
723 slash = strrchr(ttyn, '/');
724 if (slash == (char *) 0)
725 puts(ttyn);
726 else
727 puts(&slash[1]);
728 break;
729
730 case 'h':
731 puts(editedhost);
732 break;
733
734 case 'd': {
735 t = (time_t)0;
736 (void)time(&t);
737 if (Lo)
738 (void)setlocale(LC_TIME, Lo);
739 (void)strftime(db, sizeof(db), "%+", localtime(&t));
740 puts(db);
741 break;
742
743 case 's':
744 puts(kerninfo.sysname);
745 break;
746
747 case 'm':
748 puts(kerninfo.machine);
749 break;
750
751 case 'r':
752 puts(kerninfo.release);
753 break;
754
755 case 'v':
756 puts(kerninfo.version);
757 break;
758 }
759
760 case '%':
761 putchr('%');
762 break;
763 }
764 cp++;
765 }
766}