getty.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2018 K. Lange
  5. *
  6. * getty - Manage a TTY.
  7. *
  8. * Wraps a serial port (or other dumb connection) with a pty
  9. * and manages a login for it.
  10. */
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <unistd.h>
  14. #include <fcntl.h>
  15. #include <pty.h>
  16. #include <sys/wait.h>
  17. #include <sys/fswait.h>
  18. int main(int argc, char * argv[]) {
  19. int fd_master, fd_slave, fd_serial;
  20. char * file = "/dev/ttyS0";
  21. char * user = NULL;
  22. if (getuid() != 0) {
  23. fprintf(stderr, "%s: only root can do that\n", argv[0]);
  24. return 1;
  25. }
  26. int opt;
  27. while ((opt = getopt(argc, argv, "a:")) != -1) {
  28. switch (opt) {
  29. case 'a':
  30. user = optarg;
  31. break;
  32. }
  33. }
  34. if (optind < argc) {
  35. file = argv[optind];
  36. }
  37. openpty(&fd_master, &fd_slave, NULL, NULL, NULL);
  38. fd_serial = open(file, O_RDWR);
  39. pid_t child = fork();
  40. if (!child) {
  41. dup2(fd_slave, 0);
  42. dup2(fd_slave, 1);
  43. dup2(fd_slave, 2);
  44. system("ttysize -q");
  45. char * tokens[] = {"/bin/login",NULL,NULL,NULL};
  46. if (user) {
  47. tokens[1] = "-f";
  48. tokens[2] = user;
  49. }
  50. execvp(tokens[0], tokens);
  51. exit(1);
  52. } else {
  53. int fds[2] = {fd_serial, fd_master};
  54. while (1) {
  55. int index = fswait2(2,fds,200);
  56. char buf[1024];
  57. int r;
  58. switch (index) {
  59. case 0: /* fd_serial */
  60. r = read(fd_serial, buf, 1);
  61. write(fd_master, buf, 1);
  62. break;
  63. case 1: /* fd_master */
  64. r = read(fd_master, buf, 1024);
  65. write(fd_serial, buf, r);
  66. break;
  67. default: /* timeout */
  68. {
  69. int result = waitpid(child, NULL, WNOHANG);
  70. if (result > 0) {
  71. /* Child login shell has returned (session ended) */
  72. return 0;
  73. }
  74. }
  75. break;
  76. }
  77. }
  78. }
  79. return 0;
  80. }