2 #include <sys/resource.h>
4 //#define K8STERM_DEBUG_EXEC
7 ////////////////////////////////////////////////////////////////////////////////
10 static void dump (char c) {
13 fprintf(stderr, " %02x '%c' ", c, isprint(c)?c:'.');
14 if (++col % 10 == 0) fprintf(stderr, "\n");
24 static void execsh_free (ExecData
*ed
) {
27 for (int f
= 0; f
< ed
->argc
; ++f
) free(ed
->args
[f
]);
30 memset(ed
, 0, sizeof(*ed
));
34 static int execsh_prepare (ExecData
*ed
, const char *str
) {
36 #ifdef K8STERM_DEBUG_EXEC
37 FILE *fo
= stderr
; //fopen("/tmp/z_k8sterm_exec_debug.log", "w");
40 memset(ed
, 0, sizeof(*ed
));
44 char *envshell
= getenv("SHELL");
45 if (envshell
== NULL
) envshell
= "/bin/sh";
46 K8T_DEFAULT(envshell
, opt_shell
);
47 setenv("TERM", opt_term
, 1);
48 //args = (opt_cmd ? opt_cmd : (char *[]){envshell, "-i", NULL});
49 if (opt_cmd
&& opt_cmd_count
> 0) {
50 #ifdef K8STERM_DEBUG_EXEC
51 if (fo
) fprintf(fo
, "EXECSH: executing `opt_cmd` (%d): <%s>\n", opt_cmd_count
, opt_cmd
[0]);
53 args
= calloc(opt_cmd_count
+1, sizeof(char*));
56 for (int f
= 0; f
< opt_cmd_count
; ++f
) {
57 #ifdef K8STERM_DEBUG_EXEC
58 if (fo
) fprintf(fo
, "EXECSH: arg #%d of %d: <%s>\n", f
, opt_cmd_count
, opt_cmd
[f
]);
60 args
[f
] = strdup(opt_cmd
[f
]);
62 for (int c
= 0; c
< f
; ++c
) free(args
[c
]);
69 args
= calloc(3, sizeof(char*));
71 #ifdef K8STERM_DEBUG_EXEC
72 if (fo
) fprintf(fo
, "EXECSH: executing `opt_cmd` shell: <%s>\n", envshell
);
75 args
[0] = strdup(envshell
);
76 if (!args
[0]) { free(args
); return -1; }
77 args
[1] = strdup("-i");
78 if (!args
[1]) { free(args
[0]); free(args
); return -1; }
82 #ifdef K8STERM_DEBUG_EXEC
83 if (fo
) fprintf(fo
, "EXECSH: executing `str`: <%s>\n", str
);
86 args
= calloc(32768, sizeof(char *));
87 if (args
== NULL
) return -1;
89 if (argc
>= 32766) break;
91 while (*str
&& isspace(*str
)) ++str
;
94 while (*str
&& !isspace(*str
)) {
99 args
[argc
] = calloc(str
-b
+1, 1);
101 for (int f
= 0; f
< argc
; ++f
) free(args
[f
]);
105 memcpy(args
[argc
], b
, str
-b
);
106 #ifdef K8STERM_DEBUG_EXEC
107 if (fo
) fprintf(fo
, "EXECSH: argc=%d; argv=<%s>\n", argc
, args
[argc
]);
113 #ifdef K8STERM_DEBUG_EXEC
114 if (fo
&& fo
!= stdout
&& fo
!= stderr
) fclose(fo
);
119 if (argc
< 1) { execsh_free(ed
); return -1; }
124 static __attribute__((noreturn
)) void execsh (ExecData
*ed
) {
125 if (!ed
) exit(EXIT_FAILURE
);
126 if (ed
->argc
== 0) exit(EXIT_FAILURE
);
129 extern char **environ;
130 FILE *fo = fopen("z.log", "a");
131 for (char **e = environ; *e; ++e) {
132 fprintf(fo, "[%s]\n", *e);
140 getrlimit(RLIMIT_NOFILE
, &r
);
141 for (rlim_t f
= 3; f
< r
.rlim_cur
; ++f
) close(f
);
143 execvp(ed
->args
[0], ed
->args
);
148 static int k8t_ttyNew (K8Term
*term
) {
150 struct winsize w
= {term
->row
, term
->col
, 0, 0};
152 if (execsh_prepare(&ed
, K8T_DATA(term
)->execcmd
) != 0) {
153 fprintf(stderr
, "EXEC <%s> failed!\n", K8T_DATA(term
)->execcmd
);
156 switch (K8T_DATA(term
)->pid
= forkpty(&masterfd
, NULL
, NULL
, &w
)) {
159 fprintf(stderr
, "fork failed");
160 if (masterfd
!= -1) close(masterfd
);
163 setsid(); /* create a new process group */
166 default: /* master */
168 term
->cmdfd
= masterfd
;
177 static int k8t_ttyNew (K8Term
*term
) {
179 struct winsize w
= {term
->row
, term
->col
, 0, 0};
181 if (openpty(&m
, &s
, NULL
, NULL
, &w
) < 0) k8t_die("openpty failed: %s", strerror(errno
));
185 switch (K8T_DATA(term
)->pid
= fork()) {
187 fprintf(stderr
, "fork failed");
190 setsid(); /* create a new process group */
191 dup2(s
, STDIN_FILENO
);
192 dup2(s
, STDOUT_FILENO
);
193 dup2(s
, STDERR_FILENO
);
194 if (ioctl(s
, TIOCSCTTY
, NULL
) < 0) k8t_die("ioctl TIOCSCTTY failed: %s", strerror(errno
));
197 execsh(K8T_DATA(term
)->execcmd
);
199 default: /* master */