/MirOS/dist/jupp/joe-3.1jupp23.tgz
[alioth/jupp.git] / ushell.c
1 /* $MirOS: contrib/code/jupp/ushell.c,v 1.4 2012/12/30 18:18:07 tg Exp $ */
2 /*
3  *      Shell-window functions
4  *      Copyright
5  *              (C) 1992 Joseph H. Allen
6  *
7  *      This file is part of JOE (Joe's Own Editor)
8  */
9 #include "config.h"
10 #include "types.h"
11
12 #include <unistd.h>
13 #ifdef HAVE_SYS_TYPES_H
14 #include <sys/types.h>
15 #endif
16 #ifdef HAVE_SYS_STAT_H
17 #include <sys/stat.h>
18 #endif
19 #ifdef HAVE_SIGNAL_H
20 #include <signal.h>
21 #endif
22 #ifdef HAVE_STDLIB_H
23 #include <stdlib.h>
24 #endif
25
26 #include "b.h"
27 #include "main.h"
28 #include "pw.h"
29 #include "qw.h"
30 #include "tty.h"
31 #include "uedit.h"
32 #include "uerror.h"
33 #include "ufile.h"
34 #include "va.h"
35 #include "vs.h"
36 #include "ushell.h"
37 #include "utf8.h"
38 #include "w.h"
39
40 extern int orphan;
41
42 /* Executed when shell process terminates */
43
44 static void cdone(B *b)
45 {
46         b->pid = 0;
47         close(b->out);
48         b->out = -1;
49 }
50
51 static void cdone_parse(B *b)
52 {
53         b->pid = 0;
54         close(b->out);
55         b->out = -1;
56         parserrb(b);
57 }
58
59 /* Executed for each chunk of data we get from the shell */
60
61 static void cfollow(B *b,long byte)
62 {
63         W *w;
64          if ((w = maint->topwin) != NULL) {
65                 do {
66                         if ((w->watom->what&TYPETW) && ((BW *)w->object)->b==b && ((BW *)w->object)->cursor->byte==byte) {
67                                 BW *bw = (BW *)w->object;
68                                 p_goto_eof(bw->cursor);
69                                 bw->cursor->xcol = piscol(bw->cursor);
70                         }
71                 w = w->link.next;
72                 } while (w != maint->topwin);
73          }
74 }
75
76 static void cdata(B *b, unsigned char *dat, int siz)
77 {
78         P *q = pdup(b->eof);
79         P *r = pdup(b->eof);
80         long byte = q->byte;
81         unsigned char bf[1024];
82         int x, y;
83
84         for (x = y = 0; x != siz; ++x) {
85                 if (dat[x] == 13 || dat[x] == 0) {
86                         ;
87                 } else if (dat[x] == 8 || dat[x] == 127) {
88                         if (y) {
89                                 --y;
90                         } else {
91                                 pset(q, r);
92                                 prgetc(q);
93                                 bdel(q, r);
94                                 --byte;
95                         }
96                 } else if (dat[x] == 7) {
97                         ttputc(7);
98                 } else {
99                         bf[y++] = dat[x];
100                 }
101         }
102         if (y) {
103                 binsm(r, bf, y);
104         }
105         prm(r);
106         prm(q);
107
108         cfollow(b,byte);
109 }
110
111 static int doushell(BW *bw, unsigned char *cmd, int *notify, int build)
112 {
113 #ifdef __MSDOS__
114         if (notify) {
115                 *notify = 1;
116         }
117         varm(s);
118         msgnw(bw->parent, "Sorry, no sub-processes in DOS (yet)");
119         return -1;
120 #else
121         MPX *m;
122         unsigned char **s;
123         unsigned char *u;
124         const unsigned char *name;
125
126         name = getushell();
127         s = vamk(10);
128         u = vsncpy(NULL, 0, sz(name));
129         s = vaadd(s, u);
130         if (cmd) {
131                 u = vsncpy(NULL, 0, sc("-c"));
132                 s = vaadd(s, u);
133                 s = vaadd(s, cmd);
134         } else {
135                 u = vsncpy(NULL, 0, sc("-i"));
136                 s = vaadd(s, u);
137         }
138
139         if (notify) {
140                 *notify = 1;
141         }
142         if (bw->b->pid) {
143                 msgnw(bw->parent, US "Program already running in this window");
144                 varm(s);
145                 return -1;
146         }
147         p_goto_eof(bw->cursor);
148
149         if (!(m = mpxmk(&bw->b->out, name, s, cdata, bw->b, build ? cdone_parse : cdone, bw->b))) {
150                 varm(s);
151                 msgnw(bw->parent, US "No ptys available");
152                 return -1;
153         } else {
154                 bw->b->pid = m->pid;
155         }
156         return 0;
157 #endif
158 }
159
160 int ubknd(BW *bw)
161 {
162         if (!getenv("SHELL")) {
163                 msgnw(bw->parent, US "\"SHELL\" environment variable not defined or exported");
164         }
165         return doushell(bw, NULL, NULL, 0);
166 }
167
168 /* Run a program in a window */
169
170 static int dorun(BW *bw, unsigned char *s, void *object, int *notify)
171 {
172         return doushell(bw, s, notify, 0);
173 }
174
175 B *runhist = NULL;
176
177 int urun(BW *bw)
178 {
179         if (wmkpw(bw->parent, US "Program to run: ", &runhist, dorun, US "Run", NULL, NULL, NULL, NULL, locale_map)) {
180                 return 0;
181         } else {
182                 return -1;
183         }
184 }
185
186 static int dobuild(BW *bw, unsigned char *s, void *object, int *notify)
187 {
188         return doushell(bw, s, notify, 1);
189 }
190
191 B *buildhist = NULL;
192
193 int ubuild(BW *bw)
194 {
195         if (buildhist) {
196                 if ((bw=wmkpw(bw->parent, US "Build command: ", &buildhist, dobuild, US "Run", NULL, NULL, NULL, NULL, locale_map))) {
197                         uuparw(bw);
198                         u_goto_eol(bw);
199                         bw->cursor->xcol = piscol(bw->cursor);
200                         return 0;
201                 }
202         } else if (wmkpw(bw->parent, US "Enter build command (for example, 'make'): ", &buildhist, dobuild, US "Run", NULL, NULL, NULL, NULL, locale_map))
203                         return 0;
204                 return -1;
205 }
206
207 /* Kill program */
208
209 static int pidabort(BW *bw, int c, void *object, int *notify)
210 {
211         if (notify) {
212                 *notify = 1;
213         }
214         if (c != 'y' && c != 'Y') {
215                 return -1;
216         }
217         if (bw->b->pid) {
218                 kill(bw->b->pid, 1);
219                 return -1;
220         } else {
221                 return -1;
222         }
223 }
224
225 int ukillpid(BW *bw)
226 {
227         if (bw->b->pid) {
228                 if (mkqw(bw->parent, sc("Kill program (y,n,^C)?"), pidabort, NULL, NULL, NULL)) {
229                         return 0;
230                 } else {
231                         return -1;
232                 }
233         } else {
234                 return 0;
235         }
236 }
237
238 static const char * const getushell_envs[] = {
239         "SHELL",
240         "EXECSHELL",
241 };
242 const void *getushell(void)
243 {
244         static char *rshell;
245
246         if (!rshell) {
247                 char *eshell;
248                 struct stat sbuf;
249                 int i = 0;
250
251                 while (i < 2) {
252                         eshell = getenv(getushell_envs[i++]);
253                         if (eshell && *eshell &&
254                             !stat(eshell, &sbuf) &&
255                             S_ISREG(sbuf.st_mode) &&
256                             (sbuf.st_mode & 0111) &&
257                             /* LINTED use of access */
258                             !access(eshell, X_OK)) {
259                                 rshell = eshell;
260                                 break;
261                         }
262                 }
263         }
264         return (rshell ? rshell : "/bin/sh");
265 }