ptty.c 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. #include <sys/wait.h>
  2. #include <errno.h>
  3. #include <inttypes.h>
  4. #include <limits.h>
  5. #include <stdarg.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <termios.h>
  10. #include <unistd.h>
  11. #include <util.h>
  12. void
  13. die(const char *fmt, ...)
  14. {
  15. va_list ap;
  16. va_start(ap, fmt);
  17. vfprintf(stderr, fmt, ap);
  18. va_end(ap);
  19. if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
  20. fputc(' ', stderr);
  21. perror(NULL);
  22. } else {
  23. fputc('\n', stderr);
  24. }
  25. exit(EXIT_FAILURE);
  26. }
  27. void
  28. usage(void)
  29. {
  30. fputs("ptty cmd\n", stderr);
  31. exit(EXIT_FAILURE);
  32. }
  33. int
  34. main(int argc, char *argv[])
  35. {
  36. struct winsize ws = {.ws_row = 25, .ws_col = 80, 0, 0};
  37. int ch;
  38. while ((ch = getopt(argc, argv, "c:r:h")) != -1) {
  39. switch (ch) {
  40. case 'c': /* cols */
  41. ws.ws_col = strtoimax(optarg, NULL, 10);
  42. if (errno != 0)
  43. die("strtoimax: %s", optarg);
  44. break;
  45. case 'r': /* lines */
  46. ws.ws_row = strtoimax(optarg, NULL, 10);
  47. if (errno != 0)
  48. die("strtoimax: %s", optarg);
  49. break;
  50. case 'h':
  51. default:
  52. usage();
  53. }
  54. }
  55. argc -= optind;
  56. argv += optind;
  57. if (argc < 1)
  58. usage();
  59. int mfd;
  60. pid_t pid = forkpty(&mfd, NULL, NULL, &ws);
  61. switch (pid) {
  62. case -1:
  63. die("forkpty");
  64. case 0: /* child */
  65. execvp(argv[0], argv);
  66. die("exec");
  67. }
  68. /* parent */
  69. FILE *fh = fdopen(mfd, "rw");
  70. if (fh == NULL)
  71. die("fdopen");
  72. char buf[BUFSIZ];
  73. while (fgets(buf, sizeof buf, fh) != NULL);
  74. int status;
  75. waitpid(pid, &status, 0);
  76. return WEXITSTATUS(status);
  77. }