1 /* @(#)filecmds.c 1.54 09/07/09 Copyright 1984-1986, 1989-2009 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)filecmds.c 1.54 09/07/09 Copyright 1984-1986, 1989-2009 J. Schilling";
6 #endif
7 /*
8 * Commands that deal with filenames and read/write of files
9 *
10 * Copyright (c) 1984-1986, 1989-2009 J. Schilling
11 */
12 /*
13 * The contents of this file are subject to the terms of the
14 * Common Development and Distribution License, Version 1.0 only
15 * (the "License"). You may not use this file except in compliance
16 * with the License.
17 *
18 * See the file CDDL.Schily.txt in this distribution for details.
19 * A copy of the CDDL is also available via the Internet at
20 * http://www.opensource.org/licenses/cddl1.txt
21 *
22 * When distributing Covered Code, include this CDDL HEADER in each
23 * file and include the License file CDDL.Schily.txt from this distribution.
24 */
25
26 #include "ved.h"
27 #include "buffer.h"
28 #include "terminal.h"
29 #include <schily/wait.h>
30
31 EXPORT void vread __PR((ewin_t *wp));
32 EXPORT void vwrite __PR((ewin_t *wp));
33 LOCAL BOOL shellspecial __PR((Uchar *pattern, int length));
34 LOCAL int glob __PR((ewin_t *wp, Uchar* buf));
35 EXPORT void vchange __PR((ewin_t *wp));
36 EXPORT BOOL change_file __PR((ewin_t *wp, Uchar* file));
37 EXPORT void fchange __PR((ewin_t *wp, Uchar* file));
38 EXPORT void vswrite __PR((ewin_t *wp));
39
40 /*
41 * Read a file into the current buffer
42 */
43 EXPORT void
vread(wp)44 vread(wp)
45 ewin_t *wp;
46 {
47 register epos_t savedot = wp->dot;
48 int len;
49 Uchar name[FNAMESIZE];
50
51 if (! (len = getcmdline(wp, name, sizeof (name), "Get from: ")))
52 return;
53 if (!issimple(name, len) || shellspecial(name, len))
54 if (!glob(wp, name))
55 return;
56 loadfile(wp, name, FALSE);
57 if (wp->dot == savedot) /* Did not load anything. */
58 return;
59 dispup(wp, wp->dot, savedot);
60 wp->dot = savedot;
61 modified(wp);
62 }
63
64 /*
65 * Write current buffer to a file.
66 */
67 EXPORT void
vwrite(wp)68 vwrite(wp)
69 ewin_t *wp;
70 {
71 FILE *f;
72 int len;
73 Uchar name[FNAMESIZE];
74
75 if (! (len = getcmdline(wp, name, sizeof (name), "Write to: ")))
76 return;
77 if (!issimple(name, len) || shellspecial(name, len))
78 if (!glob(wp, name))
79 return;
80 if ((f = opensyserr(wp, name, "ctwub")) == (FILE *) NULL)
81 return;
82 lockfd(fdown(f));
83 if (savefile(wp, (epos_t)0, wp->eof, f, "FILE")) {
84 wp->modflg = 0;
85 defaultinfo(wp, UC NULL);
86 }
87 fclose(f);
88 }
89
90 /*
91 * Check if the pattern contains shell special characters
92 * that (in addition to patthern matching characters) will
93 * expand filenames.
94 */
95 LOCAL BOOL
shellspecial(pattern,length)96 shellspecial(pattern, length)
97 register Uchar *pattern;
98 register int length;
99 {
100 while (length-- > 0) {
101 switch (*pattern++) {
102
103 case '~':
104 return (TRUE);
105 }
106 }
107 return (FALSE);
108 }
109
110 /*
111 * Let shell do filename globbing - pipe buffer through shell.
112 */
113 LOCAL int
glob(wp,buf)114 glob(wp, buf)
115 ewin_t *wp;
116 Uchar *buf;
117 {
118 #ifdef HAVE_FORK
119 FILE *pp[2];
120 int mypid;
121 char *sh;
122 char cmd[FNAMESIZE+5]; /* + strlen ("echo ") */
123 char tmp[FNAMESIZE];
124
125 if ((sh = getenv("SHELL")) == NULL)
126 sh = "/bin/sh";
127
128 strcatl(cmd, "echo ", buf, (char *)NULL);
129 /* cdbg("cmd: %s\n", cmd);*/
130 if (fpipe(pp) == 0) {
131 write_errno(wp, "Glob pipe failed");
132 return (0);
133 }
134 mypid = fork();
135 if (mypid < 0) {
136 write_errno(wp, "Glob fork failed");
137 return (0);
138 }
139 if (mypid == 0) {
140 FILE *null;
141
142 fclose(pp[0]);
143
144 /* We don't want to see errors */
145 null = fileopen("/dev/null", "rwb");
146
147 fexecl(sh, null, pp[1], null, "sh", "-c", cmd, (char *)NULL);
148 write_errno(wp, "Glob exec failed");
149 _exit(-1);
150 }
151 fclose(pp[1]);
152 tmp[0] = '\0';
153 fgetline(pp[0], tmp, sizeof (tmp));
154 fclose(pp[0]);
155 wait(0);
156 /* cdbg("line: '%s'\n", tmp);*/
157 if (strchr(tmp, ' ')) {
158 writeerr(wp, "Ambiguous");
159 return (0);
160 }
161 strcpy(C buf, tmp);
162 return (1);
163 #else
164 writeerr(wp, "Glob not available");
165 return (0);
166 #endif
167 }
168
169 /*
170 * Replace the current file in current buffer
171 */
172 EXPORT void
vchange(wp)173 vchange(wp)
174 ewin_t *wp;
175 {
176 int len;
177 Uchar name[FNAMESIZE];
178
179 /*
180 * Get the new filename, abort on empty input.
181 */
182 if (! (len = getcmdline(wp, name, sizeof (name), "Change to: ")))
183 return;
184 if (!issimple(name, len) || shellspecial(name, len))
185 if (!glob(wp, name))
186 return;
187
188 if (!change_file(wp, name))
189 return;
190
191 newwindow(wp);
192 }
193
194 /*
195 * Ask the user if and how the old file should be written back.
196 */
197 EXPORT BOOL
change_file(wp,file)198 change_file(wp, file)
199 ewin_t *wp;
200 Uchar *file;
201 {
202 int c;
203
204 if (wp->modflg)
205 writeerr(wp, "FILE MODIFIED!");
206 if (wp->modflg || mflag) {
207
208 switch (c = getcmdchar(wp, NULL,
209 "CHANGING TO: %s. PUT EDITS?(Y/W/N/F/!) ", file)) {
210
211 default:
212 abortmsg(wp);
213 /* FALLTHROUGH */
214 case 0:
215 return (FALSE);
216 case 'n':
217 case 'N':
218 break;
219 case 'w':
220 case 'W':
221 case '!':
222 if (!writebuf(wp, c == '!'))
223 return (FALSE);
224 break;
225 case 'y':
226 case 'Y':
227 case 'f':
228 case 'F':
229 if (!bakbuf(wp, c == 'f' || c == 'F'))
230 return (FALSE);
231 }
232 }
233 flush();
234
235 fchange(wp, file);
236 return (TRUE);
237 }
238
239 /*
240 * Replace the content of the buffer with new file and put new file on screen.
241 */
242 EXPORT void
fchange(wp,file)243 fchange(wp, file)
244 ewin_t *wp;
245 Uchar *file;
246 {
247 /*
248 * Delete the old file.
249 */
250 wp->dot = 0;
251 wp->markvalid = 0;
252 delete(wp, wp->eof);
253 bufdebug(wp);
254 /*
255 * Load the new file.
256 */
257 defaulterr(wp, UC NULL);
258 wp->curftime = gftime(C file);
259 loadfile(wp, file, TRUE);
260 wp->dot = 0;
261
262 if (autodos)
263 wp->dosmode = isdos(wp);
264
265 namemsg(file);
266 strncpy(C curfname, C file, sizeof (curfname));
267 curfname[sizeof (curfname)-1] = '\0';
268 wp->curfile = curfname;
269
270 put_vedtmp(wp, TRUE); /* save new filename */
271 newprot(wp); /* change Prot file */
272
273 wp->modflg = 0;
274
275 /*
276 * Put the new file on screen.
277 */
278 CLEAR_SCREEN(wp);
279 defaultinfo(wp, UC NULL);
280 refreshmsg(wp);
281 if (wp->dosmode)
282 writemsg(wp, "DOS MODE");
283 (void) wrtcheck(wp, FALSE);
284 writelockmsg(wp);
285 }
286
287 /*
288 * Save the content of the current selection (between cursor and mark) to file.
289 */
290 EXPORT void
vswrite(wp)291 vswrite(wp)
292 ewin_t *wp;
293 {
294 FILE *f;
295 int len;
296 Uchar name[FNAMESIZE];
297 epos_t begin = min(wp->dot, wp->mark);
298 epos_t end = max(wp->dot, wp->mark);
299
300 /*
301 * Ask the user for the filename, abort on empty input.
302 */
303 if (! (len = getcmdline(wp, name, sizeof (name), "Sel to: ")))
304 return;
305 if (!issimple(name, len) || shellspecial(name, len))
306 if (!glob(wp, name))
307 return;
308 if ((f = opensyserr(wp, name, "ctwub")) == (FILE *) NULL)
309 return;
310 lockfd(fdown(f));
311 savefile(wp, begin, end, f, "FILE");
312 fclose(f);
313 }
314