Blob


1 /*
2 * Copyright (c) 2024 Omar Polo <op@omarpolo.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
17 #include "compat.h"
19 #include <sys/wait.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stdint.h>
26 #include <string.h>
27 #include <unistd.h>
29 #include "exec.h"
30 #include "minibuffer.h"
31 #include "ui.h"
33 #define TMPFILE "/tmp/telescope.XXXXXXXXXX"
35 int
36 exec_cmd(char **argv, enum exec_mode mode)
37 {
38 char **t;
39 int s, fd, ret;
40 pid_t pid;
42 if (argv == NULL)
43 return (-1);
45 if (mode == EXEC_FOREGROUND) {
46 ui_suspend();
48 fprintf(stderr, "%s: running", getprogname());
49 for (t = argv; *t; ++t)
50 fprintf(stderr, " %s", *t);
51 fprintf(stderr, "\n");
52 fflush(NULL);
53 }
55 switch (pid = fork()) {
56 case -1:
57 message("failed to fork: %s", strerror(errno));
58 return (-1);
59 case 0:
60 if (mode == EXEC_BACKGROUND) {
61 if ((fd = open("/dev/null", O_RDWR)) == -1) {
62 warn("can't open /dev/null");
63 _exit(1);
64 }
65 (void)dup2(fd, 0);
66 (void)dup2(fd, 1);
67 (void)dup2(fd, 2);
68 if (fd > 2)
69 close(fd);
70 }
71 execvp(argv[0], argv);
72 if (mode == EXEC_FOREGROUND) {
73 warn("can't exec \"%s\"", argv[0]);
74 fprintf(stderr, "Press enter to continue");
75 fflush(stderr);
76 read(0, &s, 1);
77 }
78 _exit(1);
79 }
81 if (mode == EXEC_BACKGROUND)
82 return (0);
84 do {
85 ret = waitpid(pid, &s, 0);
86 } while (ret == -1 && errno == EINTR);
88 ui_resume();
90 if (WIFSIGNALED(s) || WEXITSTATUS(s) != 0) {
91 message("%s failed", *argv);
92 return (-1);
93 }
95 return (0);
96 }
98 FILE *
99 exec_editor(void *data, size_t len)
101 FILE *fp;
102 char *editor;
103 char sfn[sizeof(TMPFILE)];
104 char *argv[3];
105 int fd;
107 strlcpy(sfn, TMPFILE, sizeof(sfn));
108 if ((fd = mkstemp(sfn)) == -1) {
109 message("failed to create a temp file: %s", strerror(errno));
110 return (NULL);
112 (void) write(fd, data, len);
113 close(fd);
115 if ((editor = getenv("VISUAL")) == NULL &&
116 (editor = getenv("EDITOR")) == NULL)
117 editor = (char *)DEFAULT_EDITOR;
119 argv[0] = editor;
120 argv[1] = sfn;
121 argv[2] = NULL;
123 if (exec_cmd(argv, EXEC_FOREGROUND) == -1) {
124 (void) unlink(sfn);
125 return (NULL);
128 if ((fp = fopen(sfn, "r")) == NULL) {
129 message("can't open temp file!");
130 (void) unlink(sfn);
131 return (NULL);
133 (void) unlink(sfn);
135 return (fp);