Deleted Added
full compact
main.c (9875) main.c (15645)
1/*-
1/*-
2 * Copyright (c) 1980 The Regents of the University of California.
3 * All rights reserved.
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

--- 15 unchanged lines hidden (view full) ---

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
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

--- 15 unchanged lines hidden (view full) ---

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
35char copyright[] =
36"@(#) Copyright (c) 1980 The Regents of the University of California.\n\
37 All rights reserved.\n";
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
38#endif /* not lint */
39
40#ifndef lint
41static char sccsid[] = "@(#)main.c 5.16 (Berkeley) 3/27/91";
41/*static char sccsid[] = "from: @(#)main.c 8.1 (Berkeley) 6/20/93";*/
42static char rcsid[] = "$Id: main.c,v 1.1.1.2 1996/04/13 15:33:11 joerg Exp $";
42#endif /* not lint */
43
43#endif /* not lint */
44
44#define USE_OLD_TTY
45
46#include <sys/param.h>
47#include <sys/stat.h>
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>
48#include <signal.h>
49#include <fcntl.h>
52#include <signal.h>
53#include <fcntl.h>
50#include <sgtty.h>
51#include <time.h>
52#include <ctype.h>
54#include <time.h>
55#include <ctype.h>
56#include <fcntl.h>
57#include <libutil.h>
58#include <locale.h>
53#include <setjmp.h>
59#include <setjmp.h>
54#include <syslog.h>
55#include <unistd.h>
56#include <ctype.h>
60#include <signal.h>
57#include <stdlib.h>
58#include <string.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
59#include "gettytab.h"
60#include "pathnames.h"
68#include "gettytab.h"
69#include "pathnames.h"
70#include "extern.h"
61
71
62struct sgttyb tmode = {
63 0, 0, CERASE, CKILL, 0
64};
65struct tchars tc = {
66 CINTR, CQUIT, CSTART,
67 CSTOP, CEOF, CBRK,
68};
69struct ltchars ltc = {
70 CSUSP, CDSUSP, CRPRNT,
71 CFLUSH, CWERASE, CLNEXT
72};
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 */
73
77
78#undef CTRL
79#define CTRL(x) (x&037)
80
81struct termios tmode, omode;
82
74int crmod, digit, lower, upper;
75
76char hostname[MAXHOSTNAMELEN];
83int crmod, digit, lower, upper;
84
85char hostname[MAXHOSTNAMELEN];
86struct utsname kerninfo;
77char name[16];
78char dev[] = _PATH_DEV;
79char ttyn[32];
87char name[16];
88char dev[] = _PATH_DEV;
89char ttyn[32];
80char *portselector();
81char *ttyname();
82
83#define OBUFSIZ 128
84#define TABBUFSIZ 512
85
86char defent[TABBUFSIZ];
90
91#define OBUFSIZ 128
92#define TABBUFSIZ 512
93
94char defent[TABBUFSIZ];
87char defstrs[TABBUFSIZ];
88char tabent[TABBUFSIZ];
95char tabent[TABBUFSIZ];
89char tabstrs[TABBUFSIZ];
90
91char *env[128];
92
93char partab[] = {
94 0001,0201,0201,0001,0201,0001,0001,0201,
95 0202,0004,0003,0205,0005,0206,0201,0001,
96 0201,0001,0001,0201,0001,0201,0201,0001,
97 0001,0201,0201,0001,0201,0001,0001,0201,

--- 6 unchanged lines hidden (view full) ---

104 0000,0200,0200,0000,0200,0000,0000,0200,
105 0200,0000,0000,0200,0000,0200,0200,0000,
106 0000,0200,0200,0000,0200,0000,0000,0200,
107 0200,0000,0000,0200,0000,0200,0200,0000,
108 0200,0000,0000,0200,0000,0200,0200,0000,
109 0000,0200,0200,0000,0200,0000,0000,0201
110};
111
96
97char *env[128];
98
99char partab[] = {
100 0001,0201,0201,0001,0201,0001,0001,0201,
101 0202,0004,0003,0205,0005,0206,0201,0001,
102 0201,0001,0001,0201,0001,0201,0201,0001,
103 0001,0201,0201,0001,0201,0001,0001,0201,

--- 6 unchanged lines hidden (view full) ---

110 0000,0200,0200,0000,0200,0000,0000,0200,
111 0200,0000,0000,0200,0000,0200,0200,0000,
112 0000,0200,0200,0000,0200,0000,0000,0200,
113 0200,0000,0000,0200,0000,0200,0200,0000,
114 0200,0000,0000,0200,0000,0200,0200,0000,
115 0000,0200,0200,0000,0200,0000,0000,0201
116};
117
112#define ERASE tmode.sg_erase
113#define KILL tmode.sg_kill
114#define EOT tc.t_eofc
118#define ERASE tmode.c_cc[VERASE]
119#define KILL tmode.c_cc[VKILL]
120#define EOT tmode.c_cc[VEOF]
115
116jmp_buf timeout;
117
121
122jmp_buf timeout;
123
124static void dingdong __P((int));
125static int getname __P((void));
126static void interrupt __P((int));
127static void oflush __P((void));
128static void prompt __P((void));
129static void putchr __P((int));
130static void putf __P((const char *));
131static void putpad __P((const char *));
132static void puts __P((const char *));
133static void timeoverrun __P((int));
134
135int main __P((int, char **));
136
118static void
137static void
119dingdong()
138dingdong(signo)
139 int signo;
120{
140{
121
122 alarm(0);
141 alarm(0);
123 signal(SIGALRM, SIG_DFL);
124 longjmp(timeout, 1);
125}
126
127jmp_buf intrupt;
128
129static void
142 longjmp(timeout, 1);
143}
144
145jmp_buf intrupt;
146
147static void
130interrupt()
148interrupt(signo)
149 int signo;
131{
150{
132
133 signal(SIGINT, interrupt);
134 longjmp(intrupt, 1);
135}
136
151 longjmp(intrupt, 1);
152}
153
154/*
155 * Action to take when getty is running too long.
156 */
157static void
158timeoverrun(signo)
159 int signo;
160{
161
162 syslog(LOG_ERR, "getty exiting due to excessive running time\n");
163 exit(1);
164}
165
166int
137main(argc, argv)
138 int argc;
139 char **argv;
140{
141 extern char **environ;
167main(argc, argv)
168 int argc;
169 char **argv;
170{
171 extern char **environ;
142 char *tname;
143 int repcnt = 0;
172 const char *tname;
173 int repcnt = 0, failopenlogged = 0;
174 struct rlimit limit;
144
145 signal(SIGINT, SIG_IGN);
146 signal(SIGQUIT, SIG_IGN);
147
175
176 signal(SIGINT, SIG_IGN);
177 signal(SIGQUIT, SIG_IGN);
178
148 openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH);
179 openlog("getty", LOG_ODELAY|LOG_CONS|LOG_PID, LOG_AUTH);
149 gethostname(hostname, sizeof(hostname));
150 if (hostname[0] == '\0')
151 strcpy(hostname, "Amnesiac");
180 gethostname(hostname, sizeof(hostname));
181 if (hostname[0] == '\0')
182 strcpy(hostname, "Amnesiac");
183
152 /*
184 /*
185 * Limit running time to deal with broken or dead lines.
186 */
187 (void)signal(SIGXCPU, timeoverrun);
188 limit.rlim_max = RLIM_INFINITY;
189 limit.rlim_cur = GETTY_TIMEOUT;
190 (void)setrlimit(RLIMIT_CPU, &limit);
191
192 /*
153 * The following is a work around for vhangup interactions
154 * which cause great problems getting window systems started.
155 * If the tty line is "-", we do the old style getty presuming
156 * that the file descriptors are already set up for us.
157 * J. Gettys - MIT Project Athena.
158 */
159 if (argc <= 2 || strcmp(argv[2], "-") == 0)
160 strcpy(ttyn, ttyname(0));
161 else {
162 int i;
163
164 strcpy(ttyn, dev);
165 strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
166 if (strcmp(argv[0], "+") != 0) {
167 chown(ttyn, 0, 0);
168 chmod(ttyn, 0600);
169 revoke(ttyn);
170 while ((i = open(ttyn, O_RDWR)) == -1) {
193 * The following is a work around for vhangup interactions
194 * which cause great problems getting window systems started.
195 * If the tty line is "-", we do the old style getty presuming
196 * that the file descriptors are already set up for us.
197 * J. Gettys - MIT Project Athena.
198 */
199 if (argc <= 2 || strcmp(argv[2], "-") == 0)
200 strcpy(ttyn, ttyname(0));
201 else {
202 int i;
203
204 strcpy(ttyn, dev);
205 strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
206 if (strcmp(argv[0], "+") != 0) {
207 chown(ttyn, 0, 0);
208 chmod(ttyn, 0600);
209 revoke(ttyn);
210 while ((i = open(ttyn, O_RDWR)) == -1) {
171 if (repcnt % 10 == 0) {
211 if ((repcnt % 10 == 0) &&
212 (errno != ENXIO || !failopenlogged)) {
172 syslog(LOG_ERR, "%s: %m", ttyn);
173 closelog();
213 syslog(LOG_ERR, "%s: %m", ttyn);
214 closelog();
215 failopenlogged = 1;
174 }
175 repcnt++;
176 sleep(60);
177 }
178 login_tty(i);
179 }
180 }
181
216 }
217 repcnt++;
218 sleep(60);
219 }
220 login_tty(i);
221 }
222 }
223
182 gettable("default", defent, defstrs);
224 /* Start with default tty settings */
225 if (tcgetattr(0, &tmode) < 0) {
226 syslog(LOG_ERR, "%s: %m", ttyn);
227 exit(1);
228 }
229 /*
230 * Don't rely on the driver too much, and initialize crucial
231 * things according to <sys/ttydefaults.h>. Avoid clobbering
232 * the c_cc[] settings however, the console drivers might wish
233 * to leave their idea of the preferred VERASE key value
234 * there.
235 */
236 tmode.c_iflag = TTYDEF_IFLAG;
237 tmode.c_oflag = TTYDEF_OFLAG;
238 tmode.c_lflag = TTYDEF_LFLAG;
239 tmode.c_cflag = TTYDEF_CFLAG;
240 omode = tmode;
241
242 gettable("default", defent);
183 gendefaults();
184 tname = "default";
185 if (argc > 1)
186 tname = argv[1];
187 for (;;) {
188 int off = 0;
243 gendefaults();
244 tname = "default";
245 if (argc > 1)
246 tname = argv[1];
247 for (;;) {
248 int off = 0;
189 int flushboth = 0;
190 struct sgttyb fake;
191
249
192 gettable(tname, tabent, tabstrs);
250 gettable(tname, tabent);
193 if (OPset || EPset || APset)
194 APset++, OPset++, EPset++;
195 setdefaults();
251 if (OPset || EPset || APset)
252 APset++, OPset++, EPset++;
253 setdefaults();
196 ioctl(0, TIOCFLUSH, &flushboth); /* clear out the crap */
254 off = 0;
255 (void)tcflush(0, TCIOFLUSH); /* clear out the crap */
197 ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */
198 ioctl(0, FIOASYNC, &off); /* ditto for async mode */
256 ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */
257 ioctl(0, FIOASYNC, &off); /* ditto for async mode */
199 ioctl(0, TIOCGETP, &fake); /* initialize kernel termios */
258
200 if (IS)
259 if (IS)
201 tmode.sg_ispeed = speed(IS);
260 cfsetispeed(&tmode, speed(IS));
202 else if (SP)
261 else if (SP)
203 tmode.sg_ispeed = speed(SP);
262 cfsetispeed(&tmode, speed(SP));
204 if (OS)
263 if (OS)
205 tmode.sg_ospeed = speed(OS);
264 cfsetospeed(&tmode, speed(OS));
206 else if (SP)
265 else if (SP)
207 tmode.sg_ospeed = speed(SP);
208 set_tmode(0);
266 cfsetospeed(&tmode, speed(SP));
267 setflags(0);
209 setchars();
268 setchars();
210 ioctl(0, TIOCSETC, &tc);
211 if (HC)
212 ioctl(0, TIOCHPCL, 0);
269 if (tcsetattr(0, TCSANOW, &tmode) < 0) {
270 syslog(LOG_ERR, "%s: %m", ttyn);
271 exit(1);
272 }
213 if (AB) {
273 if (AB) {
214 extern char *autobaud();
215
216 tname = autobaud();
217 continue;
218 }
219 if (PS) {
220 tname = portselector();
221 continue;
222 }
223 if (CL && *CL)
224 putpad(CL);
225 edithost(HE);
226 if (IM && *IM)
227 putf(IM);
228 if (setjmp(timeout)) {
274 tname = autobaud();
275 continue;
276 }
277 if (PS) {
278 tname = portselector();
279 continue;
280 }
281 if (CL && *CL)
282 putpad(CL);
283 edithost(HE);
284 if (IM && *IM)
285 putf(IM);
286 if (setjmp(timeout)) {
229 tmode.sg_ispeed = tmode.sg_ospeed = 0;
230 ioctl(0, TIOCSETP, &tmode);
287 tmode.c_ispeed = tmode.c_ospeed = 0;
288 (void)tcsetattr(0, TCSANOW, &tmode);
231 exit(1);
232 }
233 if (TO) {
234 signal(SIGALRM, dingdong);
235 alarm(TO);
236 }
237 if (getname()) {
238 register int i;
239
289 exit(1);
290 }
291 if (TO) {
292 signal(SIGALRM, dingdong);
293 alarm(TO);
294 }
295 if (getname()) {
296 register int i;
297
298 oflush();
240 alarm(0);
241 signal(SIGALRM, SIG_DFL);
299 alarm(0);
300 signal(SIGALRM, SIG_DFL);
242 oflush();
243 if (name[0] == '-') {
244 puts("user names may not start with '-'.");
245 continue;
246 }
247 if (!(upper || lower || digit))
248 continue;
301 if (name[0] == '-') {
302 puts("user names may not start with '-'.");
303 continue;
304 }
305 if (!(upper || lower || digit))
306 continue;
249 set_tmode(2);
250 ioctl(0, TIOCSLTC, &ltc);
307 setflags(2);
308 if (crmod) {
309 tmode.c_iflag |= ICRNL;
310 tmode.c_oflag |= ONLCR;
311 }
312#if REALLY_OLD_TTYS
313 if (upper || UC)
314 tmode.sg_flags |= LCASE;
315 if (lower || LC)
316 tmode.sg_flags &= ~LCASE;
317#endif
318 if (tcsetattr(0, TCSANOW, &tmode) < 0) {
319 syslog(LOG_ERR, "%s: %m", ttyn);
320 exit(1);
321 }
322 signal(SIGINT, SIG_DFL);
251 for (i = 0; environ[i] != (char *)0; i++)
252 env[i] = environ[i];
253 makeenv(&env[i]);
254
323 for (i = 0; environ[i] != (char *)0; i++)
324 env[i] = environ[i];
325 makeenv(&env[i]);
326
327 limit.rlim_max = RLIM_INFINITY;
328 limit.rlim_cur = RLIM_INFINITY;
329 (void)setrlimit(RLIMIT_CPU, &limit);
255 execle(LO, "login", "-p", name, (char *) 0, env);
256 syslog(LOG_ERR, "%s: %m", LO);
257 exit(1);
258 }
330 execle(LO, "login", "-p", name, (char *) 0, env);
331 syslog(LOG_ERR, "%s: %m", LO);
332 exit(1);
333 }
259 signal(SIGINT, SIG_IGN);
260 alarm(0);
261 signal(SIGALRM, SIG_DFL);
334 alarm(0);
335 signal(SIGALRM, SIG_DFL);
336 signal(SIGINT, SIG_IGN);
262 if (NX && *NX)
263 tname = NX;
264 }
265}
266
337 if (NX && *NX)
338 tname = NX;
339 }
340}
341
342static int
267getname()
268{
269 register int c;
270 register char *np;
271 char cs;
343getname()
344{
345 register int c;
346 register char *np;
347 char cs;
272 int flushin = 1 /*FREAD*/;
273
274 /*
275 * Interrupt may happen if we use CBREAK mode
276 */
277 if (setjmp(intrupt)) {
278 signal(SIGINT, SIG_IGN);
279 return (0);
280 }
281 signal(SIGINT, interrupt);
348
349 /*
350 * Interrupt may happen if we use CBREAK mode
351 */
352 if (setjmp(intrupt)) {
353 signal(SIGINT, SIG_IGN);
354 return (0);
355 }
356 signal(SIGINT, interrupt);
282 ioctl(0, TIOCFLUSH, &flushin); /* purge any input */
357 setflags(1);
283 prompt();
284 oflush();
285 if (PF > 0) {
286 sleep(PF);
287 PF = 0;
288 }
358 prompt();
359 oflush();
360 if (PF > 0) {
361 sleep(PF);
362 PF = 0;
363 }
289 set_tmode(1);
364 if (tcsetattr(0, TCSANOW, &tmode) < 0) {
365 syslog(LOG_ERR, "%s: %m", ttyn);
366 exit(1);
367 }
290 crmod = digit = lower = upper = 0;
291 np = name;
292 for (;;) {
293 oflush();
294 if (read(STDIN_FILENO, &cs, 1) <= 0)
295 exit(0);
296 if ((c = cs&0177) == 0)
297 return (0);
368 crmod = digit = lower = upper = 0;
369 np = name;
370 for (;;) {
371 oflush();
372 if (read(STDIN_FILENO, &cs, 1) <= 0)
373 exit(0);
374 if ((c = cs&0177) == 0)
375 return (0);
298 if (c == EOT || c == 4 /*^D*/)
376 if (c == EOT || c == CTRL('d'))
299 exit(1);
300 if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
301 putf("\r\n");
302 break;
303 }
304 if (islower(c))
305 lower = 1;
306 else if (isupper(c))
307 upper = 1;
308 else if (c == ERASE || c == '\b' || c == 0177) {
309 if (np > name) {
310 np--;
377 exit(1);
378 if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
379 putf("\r\n");
380 break;
381 }
382 if (islower(c))
383 lower = 1;
384 else if (isupper(c))
385 upper = 1;
386 else if (c == ERASE || c == '\b' || c == 0177) {
387 if (np > name) {
388 np--;
311 if (tmode.sg_ospeed >= B1200)
389 if (cfgetospeed(&tmode) >= 1200)
312 puts("\b \b");
313 else
314 putchr(cs);
315 }
316 continue;
390 puts("\b \b");
391 else
392 putchr(cs);
393 }
394 continue;
317 } else if (c == KILL || c == 025 /*^U*/) {
395 } else if (c == KILL || c == CTRL('u')) {
318 putchr('\r');
396 putchr('\r');
319 if (tmode.sg_ospeed < B1200)
397 if (cfgetospeed(&tmode) < 1200)
320 putchr('\n');
321 /* this is the way they do it down under ... */
322 else if (np > name)
323 puts(" \r");
324 prompt();
325 np = name;
326 continue;
327 } else if (isdigit(c))
328 digit++;
329 if (IG && (c <= ' ' || c > 0176))
330 continue;
331 *np++ = c;
332 putchr(cs);
333 }
334 signal(SIGINT, SIG_IGN);
335 *np = 0;
336 if (c == '\r')
337 crmod = 1;
398 putchr('\n');
399 /* this is the way they do it down under ... */
400 else if (np > name)
401 puts(" \r");
402 prompt();
403 np = name;
404 continue;
405 } else if (isdigit(c))
406 digit++;
407 if (IG && (c <= ' ' || c > 0176))
408 continue;
409 *np++ = c;
410 putchr(cs);
411 }
412 signal(SIGINT, SIG_IGN);
413 *np = 0;
414 if (c == '\r')
415 crmod = 1;
338 if (upper && !lower && !LC || UC)
416 if ((upper && !lower && !LC) || UC)
339 for (np = name; *np; np++)
340 if (isupper(*np))
341 *np = tolower(*np);
342 return (1);
343}
344
417 for (np = name; *np; np++)
418 if (isupper(*np))
419 *np = tolower(*np);
420 return (1);
421}
422
345static
346short tmspc10[] = {
347 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
348};
349
423static void
350putpad(s)
424putpad(s)
351 register char *s;
425 register const char *s;
352{
353 register pad = 0;
426{
427 register pad = 0;
354 register mspc10;
428 speed_t ospeed = cfgetospeed(&tmode);
355
356 if (isdigit(*s)) {
357 while (isdigit(*s)) {
358 pad *= 10;
359 pad += *s++ - '0';
360 }
361 pad *= 10;
362 if (*s == '.' && isdigit(s[1])) {
363 pad += s[1] - '0';
364 s += 2;
365 }
366 }
367
368 puts(s);
369 /*
370 * If no delay needed, or output speed is
371 * not comprehensible, then don't try to delay.
372 */
429
430 if (isdigit(*s)) {
431 while (isdigit(*s)) {
432 pad *= 10;
433 pad += *s++ - '0';
434 }
435 pad *= 10;
436 if (*s == '.' && isdigit(s[1])) {
437 pad += s[1] - '0';
438 s += 2;
439 }
440 }
441
442 puts(s);
443 /*
444 * If no delay needed, or output speed is
445 * not comprehensible, then don't try to delay.
446 */
373 if (pad == 0)
447 if (pad == 0 || ospeed <= 0)
374 return;
448 return;
375 if (tmode.sg_ospeed <= 0 ||
376 tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
377 return;
378
379 /*
380 * Round up by a half a character frame, and then do the delay.
381 * Too bad there are no user program accessible programmed delays.
382 * Transmitting pad characters slows many terminals down and also
383 * loads the system.
384 */
449
450 /*
451 * Round up by a half a character frame, and then do the delay.
452 * Too bad there are no user program accessible programmed delays.
453 * Transmitting pad characters slows many terminals down and also
454 * loads the system.
455 */
385 mspc10 = tmspc10[tmode.sg_ospeed];
386 pad += mspc10 / 2;
387 for (pad /= mspc10; pad > 0; pad--)
456 pad = (pad * ospeed + 50000) / 100000;
457 while (pad--)
388 putchr(*PC);
389}
390
458 putchr(*PC);
459}
460
461static void
391puts(s)
462puts(s)
392 register char *s;
463 register const char *s;
393{
394 while (*s)
395 putchr(*s++);
396}
397
398char outbuf[OBUFSIZ];
399int obufcnt = 0;
400
464{
465 while (*s)
466 putchr(*s++);
467}
468
469char outbuf[OBUFSIZ];
470int obufcnt = 0;
471
472static void
401putchr(cc)
473putchr(cc)
474 int cc;
402{
403 char c;
404
405 c = cc;
406 if (!NP) {
407 c |= partab[c&0177] & 0200;
408 if (OP)
409 c ^= 0200;
410 }
411 if (!UB) {
412 outbuf[obufcnt++] = c;
413 if (obufcnt >= OBUFSIZ)
414 oflush();
415 } else
416 write(STDOUT_FILENO, &c, 1);
417}
418
475{
476 char c;
477
478 c = cc;
479 if (!NP) {
480 c |= partab[c&0177] & 0200;
481 if (OP)
482 c ^= 0200;
483 }
484 if (!UB) {
485 outbuf[obufcnt++] = c;
486 if (obufcnt >= OBUFSIZ)
487 oflush();
488 } else
489 write(STDOUT_FILENO, &c, 1);
490}
491
492static void
419oflush()
420{
421 if (obufcnt)
422 write(STDOUT_FILENO, outbuf, obufcnt);
423 obufcnt = 0;
424}
425
493oflush()
494{
495 if (obufcnt)
496 write(STDOUT_FILENO, outbuf, obufcnt);
497 obufcnt = 0;
498}
499
500static void
426prompt()
427{
428
429 putf(LM);
430 if (CO)
431 putchr('\n');
432}
433
501prompt()
502{
503
504 putf(LM);
505 if (CO)
506 putchr('\n');
507}
508
509static void
434putf(cp)
510putf(cp)
435 register char *cp;
511 register const char *cp;
436{
437 extern char editedhost[];
438 time_t t;
439 char *slash, db[100];
440
441 while (*cp) {
442 if (*cp != '%') {
443 putchr(*cp++);
444 continue;
445 }
446 switch (*++cp) {
447
448 case 't':
512{
513 extern char editedhost[];
514 time_t t;
515 char *slash, db[100];
516
517 while (*cp) {
518 if (*cp != '%') {
519 putchr(*cp++);
520 continue;
521 }
522 switch (*++cp) {
523
524 case 't':
449 slash = rindex(ttyn, '/');
525 slash = strrchr(ttyn, '/');
450 if (slash == (char *) 0)
451 puts(ttyn);
452 else
453 puts(&slash[1]);
454 break;
455
456 case 'h':
457 puts(editedhost);
458 break;
459
460 case 'd': {
526 if (slash == (char *) 0)
527 puts(ttyn);
528 else
529 puts(&slash[1]);
530 break;
531
532 case 'h':
533 puts(editedhost);
534 break;
535
536 case 'd': {
461 static char fmt[] = "%l:% %p on %A, %d %B %Y";
462
463 fmt[4] = 'M'; /* I *hate* SCCS... */
537 t = (time_t)0;
464 (void)time(&t);
538 (void)time(&t);
465 (void)strftime(db, sizeof(db), fmt, localtime(&t));
539 if (Lo)
540 (void)setlocale(LC_TIME, Lo);
541 (void)strftime(db, sizeof(db), "%+", localtime(&t));
466 puts(db);
467 break;
542 puts(db);
543 break;
544
545 case 's':
546 puts(kerninfo.sysname);
547 break;
548
549 case 'm':
550 puts(kerninfo.machine);
551 break;
552
553 case 'r':
554 puts(kerninfo.release);
555 break;
556
557 case 'v':
558 puts(kerninfo.version);
559 break;
468 }
469
470 case '%':
471 putchr('%');
472 break;
473 }
474 cp++;
475 }
476}
560 }
561
562 case '%':
563 putchr('%');
564 break;
565 }
566 cp++;
567 }
568}
477
478/*
479 * The conversions from sgttyb to termios make LITOUT and PASS8 affect
480 * the parity. So every TIOCSETP ioctl has to be paired with a TIOCLSET
481 * ioctl (at least if LITOUT or PASS8 has changed, and PASS8 may vary
482 * with 'n').
483 */
484set_tmode(n)
485 int n;
486{
487 long allflags;
488
489 allflags = setflags(n);
490 tmode.sg_flags = allflags & 0xffff;
491 allflags >>= 16;
492 if (n == 2) {
493 if (crmod || NL)
494 tmode.sg_flags |= CRMOD;
495 if (upper || UC)
496 tmode.sg_flags |= LCASE;
497 if (lower || LC)
498 tmode.sg_flags &= ~LCASE;
499 }
500 ioctl(0, TIOCSETP, &tmode);
501 ioctl(0, TIOCLSET, &allflags);
502}