1ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley/* getty.c - A getty program to get controlling terminal.
2ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley *
3ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley * Copyright 2012 Sandeep Sharma <sandeep.jack2756@gamil.com>
4ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley * Copyright 2013 Kyungwan Han <asura321@gmail.com>
5ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley *
6ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley * No Standard.
7ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
8ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob LandleyUSE_GETTY(NEWTOY(getty, "<2t#<0H:I:l:f:iwnmLh",TOYFLAG_SBIN))
9ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
10ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landleyconfig GETTY
11ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  bool "getty"
12ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  default n
13ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  help
143297e87c2ab798696b0fb3d06904dccea076b77aRob Landley    usage: getty [OPTIONS] BAUD_RATE[,BAUD_RATE]... TTY [TERMTYPE]
15ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
16ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    -h    Enable hardware RTS/CTS flow control
17ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    -L    Set CLOCAL (ignore Carrier Detect state)
18ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    -m    Get baud rate from modem's CONNECT status message
19ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    -n    Don't prompt for login name
20ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    -w    Wait for CR or LF before sending /etc/issue
21ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    -i    Don't display /etc/issue
22ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    -f ISSUE_FILE  Display ISSUE_FILE instead of /etc/issue
23ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    -l LOGIN  Invoke LOGIN instead of /bin/login
24ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    -t SEC    Terminate after SEC if no login name is read
25ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    -I INITSTR  Send INITSTR before anything else
26ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    -H HOST    Log HOST into the utmp file as the hostname
27ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley*/
28ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#define FOR_getty
29ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#include "toys.h"
30ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#include <utmp.h>
31ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
32ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob LandleyGLOBALS(
33ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  char *issue_str;
34ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  char *login_str;
35ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  char *init_str;
36ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  char *host_str;
37ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  long timeout;
38ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
39ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  char *tty_name;
40ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  int  speeds[20];
41ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  int  sc;
42ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  struct termios termios;
43ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  char buff[128];
44ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley)
45ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
46ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#define CTL(x)        ((x) ^ 0100)
47ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#define HOSTNAME_SIZE 32
48ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
49ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landleytypedef void (*sighandler_t)(int);
50ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landleystruct speed_mapper {
51ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  long speed;
52ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  speed_t code;
53ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley};
54ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
55ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landleystruct speed_mapper speedtab[] = {
56ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  {50, B50}, {75, B75}, {110, B110}, {134, B134}, {150, B150}, {200, B200},
57ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  {300, B300}, {600, B600}, {1200, B1200}, {1800, B1800}, {2400, B2400},
58ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  {4800, B4800}, {9600, B9600},
59ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#ifdef  B19200
60ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  {19200, B19200},
61ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#endif
62ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#ifdef  B38400
63ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  {38400, B38400},
64ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#endif
65ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#ifdef  EXTA
66ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  {19200, EXTA},
67ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#endif
68ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#ifdef  EXTB
69ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  {38400, B38400},
70ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#endif
71ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#ifdef B57600
72ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  {57600, B57600},
73ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#endif
74ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#ifdef B115200
75ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  {115200, B115200},
76ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#endif
77ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#ifdef B230400
78ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  {230400, B230400},
79ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#endif
80ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  {0, 0},
81ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley};
82ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
83ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley// Find speed from mapper array
84ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landleystatic speed_t encode(char *s)
85ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley{
86ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  struct speed_mapper *sp;
87ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  long speed = atolx(s);
88ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
89ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (!speed) return 0;
90ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  for (sp = speedtab; sp->speed; sp++) if (sp->speed == speed) return sp->code;
91ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  return (speed_t) -1;
92ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley}
93ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
94ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landleystatic void get_speed(char *sp)
95ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley{
96ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  char *ptr;
97ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
98ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  TT.sc = 0;
99ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  while ((ptr = strsep(&sp, ","))) {
100ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    TT.speeds[TT.sc] = encode(ptr);
1018b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham    if (TT.speeds[TT.sc] < 0) perror_exit("bad speed");
1028b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham    if (++TT.sc > 10) perror_exit("too many speeds, max is 10");
103ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  }
104ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley}
105ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
106ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley// Parse args and set TERM env. variable
107ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landleystatic void parse_arguments(void)
108ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley{
109ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (isdigit(**toys.optargs)) {
110ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    get_speed(*toys.optargs);
1118b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham    if (*++toys.optargs) TT.tty_name = xmprintf("%s", *toys.optargs);
112ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  } else {
1138b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham    TT.tty_name = xmprintf("%s", *toys.optargs);
114ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    if (*++toys.optargs) get_speed(*toys.optargs);
115ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  }
116ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (*++toys.optargs) setenv("TERM", *toys.optargs, 1);
117ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley}
118ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
119ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley// Get controlling terminal and redirect stdio
120ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landleystatic void open_tty(void)
121ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley{
122ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (strcmp(TT.tty_name, "-")) {
1238b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham    if (*(TT.tty_name) != '/') TT.tty_name = xmprintf("/dev/%s", TT.tty_name);
124ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    // Sends SIGHUP to all foreground process if Session leader don't die,Ignore
125ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    sighandler_t sig = signal(SIGHUP, SIG_IGN);
126ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    ioctl(0, TIOCNOTTY, 0); // Giveup if there is any controlling terminal
127ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    signal(SIGHUP, sig);
1288b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham    if ((setsid() < 0) && (getpid() != getsid(0)))
1298b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham      perror_exit("setsid");
130ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    xclose(0);
131027a73a903af306449710ce12bc09e0e3550c6c9Rob Landley    xopen_stdio(TT.tty_name, O_RDWR|O_NDELAY|O_CLOEXEC);
132ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    fcntl(0, F_SETFL, fcntl(0, F_GETFL) & ~O_NONBLOCK); // Block read
133ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    dup2(0, 1);
134ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    dup2(0, 2);
135ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    if (ioctl(0, TIOCSCTTY, 1) < 0) perror_msg("ioctl(TIOCSCTTY)");
1368b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham    if (!isatty(0)) perror_exit("/dev/%s: not a tty", TT.tty_name);
137ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    chown(TT.tty_name, 0, 0); // change ownership, Hope login will change this
138ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    chmod(TT.tty_name, 0620);
139ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  } else { // We already have opened TTY
1408b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham    if (setsid() < 0) perror_msg("setsid failed");
141ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    if ((fcntl(0, F_GETFL) & (O_RDWR|O_RDONLY|O_WRONLY)) != O_RDWR)
1428b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham      perror_exit("no read/write permission");
143ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  }
144ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley}
145ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
146ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley// Intialise terminal settings
147ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landleystatic void termios_init(void)
148ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley{
149ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (tcgetattr(STDIN_FILENO, &TT.termios) < 0) perror_exit("tcgetattr");
150ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  // Flush input and output queues, important for modems!
151ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  tcflush(STDIN_FILENO, TCIOFLUSH);
152ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  TT.termios.c_cflag &= (0|CSTOPB|PARENB|PARODD);
153ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#ifdef CRTSCTS
154ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (toys.optflags & FLAG_h) TT.termios.c_cflag |= CRTSCTS;
155ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley#endif
156ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (toys.optflags & FLAG_L) TT.termios.c_cflag |= CLOCAL;
157ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  TT.termios.c_cc[VTIME] = 0;
158ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  TT.termios.c_cc[VMIN] = 1;
159ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  TT.termios.c_oflag = OPOST|ONLCR;
160ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  TT.termios.c_cflag |= CS8|CREAD|HUPCL|CBAUDEX;
161ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  // login will disable echo for passwd.
162ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  TT.termios.c_lflag |= ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOKE;
163ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  TT.termios.c_cc[VINTR] = CTL('C');
164ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  TT.termios.c_cc[VQUIT] = CTL('\\');
165ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  TT.termios.c_cc[VEOF] = CTL('D');
166ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  TT.termios.c_cc[VEOL] = '\n';
167ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  TT.termios.c_cc[VKILL] = CTL('U');
168c962e0fd295525978de0d9a0af584f47a83d9699Rob Landley  TT.termios.c_cc[VERASE] = 127; // CERASE
1698b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham  TT.termios.c_iflag = ICRNL|IXON|IXOFF;
170ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  // set non-zero baud rate. Zero baud rate left it unchanged.
171ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (TT.speeds[0] != B0) cfsetspeed(&TT.termios, TT.speeds[0]);
172ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (tcsetattr(STDIN_FILENO, TCSANOW, &TT.termios) < 0)
173ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    perror_exit("tcsetattr");
174ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley}
175ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
176ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley// Get the baud rate from modems CONNECT mesage, Its of form <junk><BAUD><Junk>
177ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landleystatic void sense_baud(void)
178ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley{
179ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  int vmin;
180ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  ssize_t size;
181ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  char *ptr;
182ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  speed_t speed;
183ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
184ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  vmin = TT.termios.c_cc[VMIN]; // Store old
185ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  TT.termios.c_cc[VMIN] = 0; // No block even queue is empty.
186ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (tcsetattr(STDIN_FILENO, TCSANOW, &TT.termios) < 0)
187ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    perror_exit("tcsetattr");
188ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  size = readall(STDIN_FILENO, TT.buff, sizeof(TT.buff)-1);
189ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (size > 0) {
190ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    for (ptr = TT.buff; ptr < TT.buff+size; ptr++) {
191ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley      if (isdigit(*ptr)) {
192ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley        speed = encode(ptr);
193ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley        if (speed > 0) cfsetspeed(&TT.termios,speed);
194ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley        break;
195ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley      }
196ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    }
197ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  }
198ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  TT.termios.c_cc[VMIN] = vmin; //restore old value
199ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (tcsetattr(STDIN_FILENO, TCSANOW, &TT.termios) < 0)
200ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    perror_exit("tcsetattr");
201ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley}
202ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
203ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley// Just prompt for login name
204ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landleyvoid print_prompt(void)
205ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley{
206ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  char *hostname;
207ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  struct utsname uts;
208ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
209ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  uname(&uts);
210ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  hostname = xstrdup(uts.nodename);
211ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  fputs(hostname, stdout);
2128b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham  fputs(" login: ", stdout);
213ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  fflush(NULL);
214ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  free(hostname);
215ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  hostname = NULL;
216ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley}
217ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
218ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley// Print /etc/isuue with taking care of each escape sequence
219ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landleyvoid write_issue(char *file)
220ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley{
221ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  char buff[20] = {0,};
222ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  struct utsname u;
223ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  uname(&u);
224ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  int size, fd = open(TT.issue_str, O_RDONLY);
225ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
226ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (fd < 0) return;
227ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  while ((size = readall(fd, buff, 1)) > 0) {
228ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    char *ch = buff;
229ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
230ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    if (*ch == '\\' || *ch == '%') {
231ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley      if (readall(fd, buff, 1) <= 0) perror_exit("readall");
232ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley      if (*ch == 's') fputs(u.sysname, stdout);
233ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley      if (*ch == 'n'|| *ch == 'h') fputs(u.nodename, stdout);
234ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley      if (*ch == 'r') fputs(u.release, stdout);
235ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley      if (*ch == 'm') fputs(u.machine, stdout);
236ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley      if (*ch == 'l') fputs(TT.tty_name, stdout);
237ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    } else xputc(*ch);
238ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  }
239ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley}
240ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
241ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley// Read login name and print prompt and Issue file.
242ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landleystatic int read_login_name(void)
243ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley{
244ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  tcflush(STDIN_FILENO, TCIFLUSH); // Flush pending speed switches
245ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  int i = 0;
246ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
247ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  while (1) { // Option -i will overide -f
248ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    if (!(toys.optflags & FLAG_i)) write_issue(TT.issue_str);
249ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    print_prompt();
250ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    TT.buff[0] = getchar();
251ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    if (!TT.buff[0] && TT.sc > 1) return 0; // Switch speed
252ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    if (TT.buff[0] == '\n') continue;
253ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    if (TT.buff[0] != '\n')
254ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley      if (!fgets(&TT.buff[1], HOSTNAME_SIZE-1, stdin)) _exit(1);
255ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    while (i < HOSTNAME_SIZE-1 && isgraph(TT.buff[i])) i++;
256ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    TT.buff[i] = 0;
257ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    break;
258ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  }
259ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  return 1;
260ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley}
261ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
262ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley// Put hostname entry in utmp file
263ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landleystatic void utmp_entry(void)
264ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley{
265ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  struct utmp entry;
266ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  struct utmp *utp_ptr;
267ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  pid_t pid = getpid();
2688b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham  char *utmperr = "can't make utmp entry, host length greater than UT_HOSTSIZE(256)";
269ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
270ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  utmpname(_PATH_UTMP);
271ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  setutent(); // Starts from start
272ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  while ((utp_ptr = getutent()))
273ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    if (utp_ptr->ut_pid == pid && utp_ptr->ut_type >= INIT_PROCESS) break;
274ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (!utp_ptr) {
275ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    entry.ut_type = LOGIN_PROCESS;
276ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    entry.ut_pid = getpid();
277ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    xstrncpy(entry.ut_line, ttyname(STDIN_FILENO) +
278ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley        strlen("/dev/"), UT_LINESIZE);
279ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    time((time_t *)&entry.ut_time);
280ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    xstrncpy(entry.ut_user, "LOGIN", UT_NAMESIZE);
281ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    if (strlen(TT.host_str) > UT_HOSTSIZE)
2828b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham      perror_msg(utmperr);
283ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    else xstrncpy(entry.ut_host, TT.host_str, UT_HOSTSIZE);
284ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    setutent();
285ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    pututline(&entry);
286ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    return;
287ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  }
288ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  xstrncpy(entry.ut_line, ttyname(STDIN_FILENO) + strlen("/dev/"), UT_LINESIZE);
289ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  xstrncpy(entry.ut_user, "LOGIN", UT_NAMESIZE);
290ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (strlen(TT.host_str) > UT_HOSTSIZE)
2918b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham    perror_msg(utmperr);
292ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  else xstrncpy(entry.ut_host, TT.host_str, UT_HOSTSIZE);
293ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  time((time_t *)&entry.ut_time);
294ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  setutent();
295ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  pututline(&entry);
296ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley}
297ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
298ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landleyvoid getty_main(void)
299ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley{
300ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  pid_t pid = getpid();
3018b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham  char *ptr[3] = {"/bin/login", NULL, NULL}; //2 NULLs so we can add username
302ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
303ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (!(toys.optflags & FLAG_f)) TT.issue_str = "/etc/issue";
304ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (toys.optflags & FLAG_l) ptr[0] = TT.login_str;
305ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  parse_arguments();
306ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  open_tty();
307ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  termios_init();
308ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  tcsetpgrp(STDIN_FILENO, pid);
309ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (toys.optflags & FLAG_H) utmp_entry();
310ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (toys.optflags & FLAG_I)
311ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    writeall(STDOUT_FILENO,TT.init_str,strlen(TT.init_str));
312ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (toys.optflags & FLAG_m) sense_baud();
313ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (toys.optflags & FLAG_t) alarm(TT.timeout);
314ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (toys.optflags & FLAG_w) {
315ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    char ch;
316ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
317ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    while (readall(STDIN_FILENO, &ch, 1) != 1)
318ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley      if (ch == '\n' || ch == '\r') break;
319ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  }
320ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  if (!(toys.optflags & FLAG_n)) {
321ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    int index = 1; // 0th we already set.
322ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
323ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    while (1) {
324ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley      int l = read_login_name();
325ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley
326ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley      if (l) break;
327ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley      index = index % TT.sc;
328ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley      cfsetspeed(&TT.termios, TT.speeds[index]); // Select from multiple speeds
329ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley      //Necessary after cfsetspeed
330ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley      if (tcsetattr(STDIN_FILENO, TCSANOW, &TT.termios) < 0)
331ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley        perror_exit("tcsetattr");
332ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley    }
3338b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham    ptr[1]=TT.buff; //put the username in the login command line
334ca51eb88831521ae4df60e88d5f3cd3c4b99d46dRob Landley  }
3358b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham  xexec(ptr);
3368b6d56c4f75efed9d4769d2d959ee7706e314152Isaac Dunham}
337