URI: 
       getty.c - ubase - suckless linux base utils
  HTML git clone git://git.suckless.org/ubase
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       getty.c (2823B)
       ---
            1 /* See LICENSE file for copyright and license details. */
            2 #include <sys/ioctl.h>
            3 #include <sys/stat.h>
            4 #include <sys/types.h>
            5 
            6 #include <fcntl.h>
            7 #include <limits.h>
            8 #include <signal.h>
            9 #include <stdio.h>
           10 #include <stdlib.h>
           11 #include <string.h>
           12 #include <unistd.h>
           13 #include <utmp.h>
           14 
           15 #include "config.h"
           16 #include "util.h"
           17 
           18 static char *tty = "/dev/tty1";
           19 static char *defaultterm = "linux";
           20 
           21 static void
           22 usage(void)
           23 {
           24         eprintf("usage: %s [tty] [term] [cmd] [args...]\n", argv0);
           25 }
           26 
           27 int
           28 main(int argc, char *argv[])
           29 {
           30         char term[128], logname[LOGIN_NAME_MAX], c;
           31         char hostname[HOST_NAME_MAX + 1];
           32         struct utmp usr;
           33         struct sigaction sa;
           34         FILE *fp;
           35         int fd;
           36         unsigned int i = 0;
           37         ssize_t n;
           38         long pos;
           39 
           40         ARGBEGIN {
           41         default:
           42                 usage();
           43         } ARGEND;
           44 
           45         strlcpy(term, defaultterm, sizeof(term));
           46         if (argc > 0) {
           47                 tty = argv[0];
           48                 if (argc > 1)
           49                         strlcpy(term, argv[1], sizeof(term));
           50         }
           51 
           52         sa.sa_handler = SIG_IGN;
           53         sa.sa_flags = 0;
           54         sigemptyset(&sa.sa_mask);
           55         sigaction(SIGHUP, &sa, NULL);
           56 
           57         setenv("TERM", term, 1);
           58 
           59         setsid();
           60 
           61         fd = open(tty, O_RDWR);
           62         if (fd < 0)
           63                 eprintf("open %s:", tty);
           64         if (isatty(fd) == 0)
           65                 eprintf("%s is not a tty\n", tty);
           66 
           67         /* steal the controlling terminal if necessary */
           68         if (ioctl(fd, TIOCSCTTY, (void *)1) != 0)
           69                 weprintf("TIOCSCTTY: could not set controlling tty\n");
           70         vhangup();
           71         close(fd);
           72 
           73         fd = open(tty, O_RDWR);
           74         if (fd < 0)
           75                 eprintf("open %s:", tty);
           76         dup2(fd, 0);
           77         dup2(fd, 1);
           78         dup2(fd, 2);
           79         if (fchown(fd, 0, 0) < 0)
           80                 weprintf("fchown %s:", tty);
           81         if (fchmod(fd, 0600) < 0)
           82                 weprintf("fchmod %s:", tty);
           83         if (fd > 2)
           84                 close(fd);
           85 
           86         sa.sa_handler = SIG_DFL;
           87         sa.sa_flags = 0;
           88         sigemptyset(&sa.sa_mask);
           89         sigaction(SIGHUP, &sa, NULL);
           90 
           91         /* Clear all utmp entries for this tty */
           92         fp = fopen(UTMP_PATH, "r+");
           93         if (fp) {
           94                 do {
           95                         pos = ftell(fp);
           96                         if (fread(&usr, sizeof(usr), 1, fp) != 1)
           97                                 break;
           98                         if (usr.ut_line[0] == '\0')
           99                                 continue;
          100                         if (strcmp(usr.ut_line, tty) != 0)
          101                                 continue;
          102                         memset(&usr, 0, sizeof(usr));
          103                         fseek(fp, pos, SEEK_SET);
          104                         if (fwrite(&usr, sizeof(usr), 1, fp) != 1)
          105                                 break;
          106                 } while (1);
          107                 if (ferror(fp))
          108                         weprintf("%s: I/O error:", UTMP_PATH);
          109                 fclose(fp);
          110         }
          111 
          112         if (argc > 2)
          113                 return execvp(argv[2], argv + 2);
          114 
          115         if (gethostname(hostname, sizeof(hostname)) == 0)
          116                 printf("%s ", hostname);
          117         printf("login: ");
          118         fflush(stdout);
          119 
          120         /* Flush pending input */
          121         ioctl(0, TCFLSH, (void *)0);
          122         memset(logname, 0, sizeof(logname));
          123         while (1) {
          124                 n = read(0, &c, 1);
          125                 if (n < 0)
          126                         eprintf("read:");
          127                 if (n == 0)
          128                         return 1;
          129                 if (i >= sizeof(logname) - 1)
          130                         eprintf("login name too long\n");
          131                 if (c == '\n' || c == '\r')
          132                         break;
          133                 logname[i++] = c;
          134         }
          135         if (logname[0] == '-')
          136                 eprintf("login name cannot start with '-'\n");
          137         if (logname[0] == '\0')
          138                 return 1;
          139         return execlp("/bin/login", "login", "-p", logname, NULL);
          140 }