1 
2 
3 /* This version of microEmacs is based on the public domain C
4  * version written by Dave G. Conroy.
5  * The D programming language version is written by Walter Bright.
6  * http://www.digitalmars.com/d/
7  * This program is in the public domain.
8  */
9 
10 
11 /*
12  * The routines in this file are called to create a subjob running a command
13  * interpreter.
14  */
15 
16 module spawn;
17 
18 import core.stdc.stdlib;
19 import core.stdc.time;
20 
21 import std.conv;
22 import std.stdio;
23 import std.file;
24 import std.process;
25 import std..string;
26 import std.utf;
27 
28 version (Posix)
29 {
30     import core.sys.posix.unistd;
31 }
32 
33 import ed;
34 import buffer;
35 import window;
36 import display;
37 import main;
38 import file;
39 import terminal;
40 
41 
42 
43 /*
44  * Create a subjob with a copy of the command intrepreter in it. When the
45  * command interpreter exits, mark the screen as garbage so that you do a full
46  * repaint. Bound to "C-C". The message at the start in VMS puts out a newline.
47  * Under some (unknown) condition, you don't get one free when DCL starts up.
48  */
49 int spawncli(bool f, int n)
50 {
51     movecursor(term.t_nrow-1, 0);             /* Seek to last line.   */
52     version (Windows)
53     {
54         term.t_flush();
55         auto comspec = core.stdc.stdlib.getenv("COMSPEC");
56 	string[] args;
57 	args ~= to!string(comspec);
58 	args ~= "COMMAND.COM";
59         spawnProcess(args);
60     }
61     version (Posix)
62     {
63         term.t_flush();
64         term.t_close();                             /* stty to old settings */
65         auto cp = core.stdc.stdlib.getenv("SHELL");
66         if (cp && *cp != '\0')
67 	    core.stdc.stdlib.system(cp);
68         else
69 	    core.stdc.stdlib.system("exec /bin/sh");
70         sleep(2);
71         term.t_open();
72     }
73     sgarbf = TRUE;
74     return(TRUE);
75 }
76 
77 /*
78  * Run a one-liner in a subjob. When the command returns, wait for a single
79  * character to be typed, then mark the screen as garbage so a full repaint is
80  * done. Bound to "C-X !".
81  */
82 int spawn(bool f, int n)
83 {
84     int    s;
85     string line;
86     version (Windows)
87     {
88         if ((s=mlreply("MS-DOS command: ", null, line)) != TRUE)
89                 return (s);
90         core.stdc.stdlib.system(toUTF8(line).toStringz());
91         while (term.t_getchar() != '\r')     /* Pause.               */
92         {
93 	}
94         sgarbf = TRUE;
95         return (TRUE);
96     }
97     version (Posix)
98     {
99         if ((s=mlreply("! ", null, line)) != TRUE)
100                 return (s);
101         term.t_putchar('\n');                /* Already have '\r'    */
102         term.t_flush();
103         term.t_close();                              /* stty to old modes    */
104         core.stdc.stdlib.system(toUTF8(line).toStringz());
105         sleep(2);
106         term.t_open();
107         printf("[End]");                        /* Pause.               */
108         term.t_flush();
109         while ((s = term.t_getchar()) != '\r' && s != ' ')
110         {
111 	}
112         sgarbf = TRUE;
113         return (TRUE);
114     }
115 }
116 
117 /*
118  * Pipe a one line command into a window
119  * Bound to ^X @
120  */
121 int spawn_pipe(bool f, int n)
122 {
123     int    s; 	       /* return status from CLI */
124     WINDOW *wp;        /* pointer to new window */
125     BUFFER *bp;        /* pointer to buffer to zot */
126     static string bname = "[DOS]";
127 
128     static string filnam = "DOS.TMP";
129     string line; /* command line sent to shell */
130     string sline;
131 
132     /* get the command to pipe in */
133     if ((s = mlreply("DOS:", null, line)) != TRUE)
134         return s;
135 
136     /* get rid of the command output buffer if it exists */
137     if ((bp=buffer_find(bname, FALSE, BFTEMP)) != null) /* if buffer exists */
138     {   
139         /* If buffer is displayed, try to move it off screen            */
140         /* (can't remove an on-screen buffer)                           */
141         if (bp.b_nwnd)                 /* if buffer is displayed       */
142         {   if (bp == curbp)            /* if it's the current window   */
143                 window_next(FALSE,1);   /* make another window current  */
144             window_only(FALSE, 1);
145 
146             if (buffer_remove(bp) != TRUE)
147                 goto fail;
148         }
149     }
150 
151     /* split the current window to make room for the command output */
152     if (window_split(FALSE, 1) == FALSE)
153         goto fail;
154 
155     sline = toUTF8(line) ~ ">" ~ filnam;
156 
157 version (Windows)
158 {
159     movecursor(term.t_nrow - 2, 0);
160     core.stdc.stdlib.system(sline.toStringz());
161     sgarbf = TRUE;
162     if (std.file.exists(filnam) && std.file.isFile(filnam))
163 	return FALSE;
164 }
165 version (Posix)
166 {
167     term.t_putchar('\n');                /* Already have '\r'    */
168     term.t_flush();
169     term.t_close();                              /* stty to old modes    */
170     core.stdc.stdlib.system(sline.toStringz());
171     term.t_open();
172     term.t_flush();
173     sgarbf = TRUE;
174 }
175 
176     /* and read the stuff in */
177     if (file_readin(filnam) == FALSE)
178         return(FALSE);
179 
180     /* and get rid of the temporary file */
181     remove(filnam);
182     return(TRUE);
183 
184 fail:
185     return FALSE;
186 }
187 
188 /*
189  * filter a buffer through an external DOS program
190  * Bound to ^X #
191  */
192 int spawn_filter(bool f, int n)
193 {
194         int    s;      /* return status from CLI */
195         BUFFER *bp;    /* pointer to buffer to zot */
196         string line;      /* command line to send to shell */
197         string tmpnam;    /* place to store real file name */
198         string bname1 = "fltinp";
199 
200         string filnam1 = "fltinp";
201         string filnam2 = "fltout";
202 
203         if (curbp.b_flag & BFRDONLY)   /* if buffer is read-only       */
204             return FALSE;               /* fail                         */
205 
206         /* get the filter name and its args */
207         if ((s=mlreply("Filter:", null, line)) != TRUE)
208                 return(s);
209 
210         /* setup the proper file names */
211         bp = curbp;
212         tmpnam = bp.b_fname;    /* save the original name */
213         bp.b_fname = bname1;    /* set it to our new one */
214 
215         /* write it out, checking for errors */
216         if (writeout(filnam1) != TRUE) {
217                 mlwrite("[Cannot write filter file]");
218                 bp.b_fname = tmpnam;
219                 return(FALSE);
220         }
221 
222         line ~= " <fltinp >fltout";
223     version (Windows)
224     {
225         movecursor(term.t_nrow - 2, 0);
226         core.stdc.stdlib.system(toUTF8(line).toStringz());
227     }
228     version (Posix)
229     {
230         term.t_putchar('\n');                /* Already have '\r'    */
231         term.t_flush();
232         term.t_close();                              /* stty to old modes    */
233         core.stdc.stdlib.system(toUTF8(line).toStringz());
234         term.t_open();
235         term.t_flush();
236     }
237 
238         sgarbf = TRUE;
239         s = TRUE;
240 
241         /* on failure, escape gracefully */
242         if (s != TRUE || ((s = readin(filnam2)) == FALSE)) {
243                 mlwrite("[Execution failed]");
244                 bp.b_fname = tmpnam;
245                 goto ret;
246         }
247 
248         /* reset file name */
249         bp.b_fname = tmpnam;           /* restore name */
250         bp.b_flag |= BFCHG;            /* flag it as changed */
251         s = TRUE;
252 
253 ret:
254         /* and get rid of the temporary file */
255         remove(toUTF8(filnam1));
256         remove(toUTF8(filnam2));
257         return s;
258 }
259 
260