File: | src/usr.bin/mg/dired.c |
Warning: | line 1073, column 10 Access to field 'fn' results in a dereference of a null pointer (loaded from variable 'd1') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: dired.c,v 1.100 2021/05/02 14:13:17 lum Exp $ */ | |||
2 | ||||
3 | /* This file is in the public domain. */ | |||
4 | ||||
5 | /* dired module for mg 2a | |||
6 | * by Robert A. Larson | |||
7 | */ | |||
8 | ||||
9 | #include <sys/queue.h> | |||
10 | #include <sys/resource.h> | |||
11 | #include <sys/stat.h> | |||
12 | #include <sys/time.h> | |||
13 | #include <sys/types.h> | |||
14 | #include <sys/wait.h> | |||
15 | #include <ctype.h> | |||
16 | #include <err.h> | |||
17 | #include <errno(*__errno()).h> | |||
18 | #include <fcntl.h> | |||
19 | #include <limits.h> | |||
20 | #include <signal.h> | |||
21 | #include <stdarg.h> | |||
22 | #include <stdio.h> | |||
23 | #include <stdlib.h> | |||
24 | #include <string.h> | |||
25 | #include <unistd.h> | |||
26 | ||||
27 | #include "def.h" | |||
28 | #include "funmap.h" | |||
29 | #include "kbd.h" | |||
30 | ||||
31 | void dired_init(void); | |||
32 | static int dired(int, int); | |||
33 | static int d_otherwindow(int, int); | |||
34 | static int d_undel(int, int); | |||
35 | static int d_undelbak(int, int); | |||
36 | static int d_findfile(int, int); | |||
37 | static int d_ffotherwindow(int, int); | |||
38 | static int d_expunge(int, int); | |||
39 | static int d_copy(int, int); | |||
40 | static int d_del(int, int); | |||
41 | static int d_rename(int, int); | |||
42 | static int d_exec(int, struct buffer *, const char *, const char *, ...); | |||
43 | static int d_shell_command(int, int); | |||
44 | static int d_create_directory(int, int); | |||
45 | static int d_makename(struct line *, char *, size_t); | |||
46 | static int d_warpdot(struct line *, int *); | |||
47 | static int d_forwpage(int, int); | |||
48 | static int d_backpage(int, int); | |||
49 | static int d_forwline(int, int); | |||
50 | static int d_backline(int, int); | |||
51 | static int d_killbuffer_cmd(int, int); | |||
52 | static int d_refreshbuffer(int, int); | |||
53 | static int d_filevisitalt(int, int); | |||
54 | static int d_gotofile(int, int); | |||
55 | static void reaper(int); | |||
56 | static int gotofile(char*); | |||
57 | static struct buffer *refreshbuffer(struct buffer *); | |||
58 | static int createlist(struct buffer *); | |||
59 | static void redelete(struct buffer *); | |||
60 | static char *findfname(struct line *, char *); | |||
61 | ||||
62 | extern struct keymap_s helpmap, cXmap, metamap; | |||
63 | ||||
64 | const char DDELCHAR = 'D'; | |||
65 | ||||
66 | /* | |||
67 | * Structure which holds a linked list of file names marked for | |||
68 | * deletion. Used to maintain dired buffer 'state' between refreshes. | |||
69 | */ | |||
70 | struct delentry { | |||
71 | SLIST_ENTRY(delentry)struct { struct delentry *sle_next; } entry; | |||
72 | char *fn; | |||
73 | }; | |||
74 | SLIST_HEAD(slisthead, delentry)struct slisthead { struct delentry *slh_first; } delhead = SLIST_HEAD_INITIALIZER(delhead){ ((void *)0) }; | |||
75 | ||||
76 | static PF dirednul[] = { | |||
77 | setmark, /* ^@ */ | |||
78 | gotobol, /* ^A */ | |||
79 | backchar, /* ^B */ | |||
80 | rescan, /* ^C */ | |||
81 | d_del, /* ^D */ | |||
82 | gotoeol, /* ^E */ | |||
83 | forwchar, /* ^F */ | |||
84 | ctrlg, /* ^G */ | |||
85 | NULL((void *)0), /* ^H */ | |||
86 | }; | |||
87 | ||||
88 | static PF diredcl[] = { | |||
89 | reposition, /* ^L */ | |||
90 | d_findfile, /* ^M */ | |||
91 | d_forwline, /* ^N */ | |||
92 | rescan, /* ^O */ | |||
93 | d_backline, /* ^P */ | |||
94 | rescan, /* ^Q */ | |||
95 | backisearch, /* ^R */ | |||
96 | forwisearch, /* ^S */ | |||
97 | rescan, /* ^T */ | |||
98 | universal_argument, /* ^U */ | |||
99 | d_forwpage, /* ^V */ | |||
100 | rescan, /* ^W */ | |||
101 | NULL((void *)0) /* ^X */ | |||
102 | }; | |||
103 | ||||
104 | static PF diredcz[] = { | |||
105 | spawncli, /* ^Z */ | |||
106 | NULL((void *)0), /* esc */ | |||
107 | rescan, /* ^\ */ | |||
108 | rescan, /* ^] */ | |||
109 | rescan, /* ^^ */ | |||
110 | rescan, /* ^_ */ | |||
111 | d_forwline, /* SP */ | |||
112 | d_shell_command, /* ! */ | |||
113 | rescan, /* " */ | |||
114 | rescan, /* # */ | |||
115 | rescan, /* $ */ | |||
116 | rescan, /* % */ | |||
117 | rescan, /* & */ | |||
118 | rescan, /* ' */ | |||
119 | rescan, /* ( */ | |||
120 | rescan, /* ) */ | |||
121 | rescan, /* * */ | |||
122 | d_create_directory /* + */ | |||
123 | }; | |||
124 | ||||
125 | static PF direda[] = { | |||
126 | d_filevisitalt, /* a */ | |||
127 | rescan, /* b */ | |||
128 | d_copy, /* c */ | |||
129 | d_del, /* d */ | |||
130 | d_findfile, /* e */ | |||
131 | d_findfile, /* f */ | |||
132 | d_refreshbuffer, /* g */ | |||
133 | rescan, /* h */ | |||
134 | rescan, /* i */ | |||
135 | d_gotofile /* j */ | |||
136 | }; | |||
137 | ||||
138 | static PF diredn[] = { | |||
139 | d_forwline, /* n */ | |||
140 | d_ffotherwindow, /* o */ | |||
141 | d_backline, /* p */ | |||
142 | d_killbuffer_cmd, /* q */ | |||
143 | d_rename, /* r */ | |||
144 | rescan, /* s */ | |||
145 | rescan, /* t */ | |||
146 | d_undel, /* u */ | |||
147 | rescan, /* v */ | |||
148 | rescan, /* w */ | |||
149 | d_expunge /* x */ | |||
150 | }; | |||
151 | ||||
152 | static PF direddl[] = { | |||
153 | d_undelbak /* del */ | |||
154 | }; | |||
155 | ||||
156 | static PF diredbp[] = { | |||
157 | d_backpage /* v */ | |||
158 | }; | |||
159 | ||||
160 | static PF dirednull[] = { | |||
161 | NULL((void *)0) | |||
162 | }; | |||
163 | ||||
164 | static struct KEYMAPE (1){ short map_num; short map_max; PF map_default; struct map_element map_element[1]; } d_backpagemap = { | |||
165 | 1, | |||
166 | 1, | |||
167 | rescan, | |||
168 | { | |||
169 | { | |||
170 | 'v', 'v', diredbp, NULL((void *)0) | |||
171 | } | |||
172 | } | |||
173 | }; | |||
174 | ||||
175 | static struct KEYMAPE (7){ short map_num; short map_max; PF map_default; struct map_element map_element[7]; } diredmap = { | |||
176 | 7, | |||
177 | 7, | |||
178 | rescan, | |||
179 | { | |||
180 | { | |||
181 | CCHR('@')(('@') ^ 0x40), CCHR('H')(('H') ^ 0x40), dirednul, (KEYMAP *) & helpmap | |||
182 | }, | |||
183 | { | |||
184 | CCHR('L')(('L') ^ 0x40), CCHR('X')(('X') ^ 0x40), diredcl, (KEYMAP *) & cXmap | |||
185 | }, | |||
186 | { | |||
187 | CCHR('[')(('[') ^ 0x40), CCHR('[')(('[') ^ 0x40), dirednull, (KEYMAP *) & | |||
188 | d_backpagemap | |||
189 | }, | |||
190 | { | |||
191 | CCHR('Z')(('Z') ^ 0x40), '+', diredcz, (KEYMAP *) & metamap | |||
192 | }, | |||
193 | { | |||
194 | 'a', 'j', direda, NULL((void *)0) | |||
195 | }, | |||
196 | { | |||
197 | 'n', 'x', diredn, NULL((void *)0) | |||
198 | }, | |||
199 | { | |||
200 | CCHR('?')(('?') ^ 0x40), CCHR('?')(('?') ^ 0x40), direddl, NULL((void *)0) | |||
201 | }, | |||
202 | } | |||
203 | }; | |||
204 | ||||
205 | void | |||
206 | dired_init(void) | |||
207 | { | |||
208 | funmap_add(dired, "dired", 1); | |||
209 | funmap_add(d_create_directory, "dired-create-directory", 1); | |||
210 | funmap_add(d_copy, "dired-do-copy", 1); | |||
211 | funmap_add(d_expunge, "dired-do-flagged-delete", 0); | |||
212 | funmap_add(d_rename, "dired-do-rename", 1); | |||
213 | funmap_add(d_findfile, "dired-find-file", 1); | |||
214 | funmap_add(d_ffotherwindow, "dired-find-file-other-window", 1); | |||
215 | funmap_add(d_del, "dired-flag-file-deletion", 0); | |||
216 | funmap_add(d_gotofile, "dired-goto-file", 1); | |||
217 | funmap_add(d_forwline, "dired-next-line", 0); | |||
218 | funmap_add(d_otherwindow, "dired-other-window", 0); | |||
219 | funmap_add(d_backline, "dired-previous-line", 0); | |||
220 | funmap_add(d_refreshbuffer, "dired-revert", 0); | |||
221 | funmap_add(d_backpage, "dired-scroll-down", 0); | |||
222 | funmap_add(d_forwpage, "dired-scroll-up", 0); | |||
223 | funmap_add(d_shell_command, "dired-shell-command", 1); | |||
224 | funmap_add(d_undel, "dired-unmark", 0); | |||
225 | funmap_add(d_undelbak, "dired-unmark-backward", 0); | |||
226 | funmap_add(d_killbuffer_cmd, "quit-window", 0); | |||
227 | maps_add((KEYMAP *)&diredmap, "dired"); | |||
228 | dobindkey(fundamental_map(fundamental_mode.p_map), "dired", "^Xd"); | |||
229 | } | |||
230 | ||||
231 | /* ARGSUSED */ | |||
232 | int | |||
233 | dired(int f, int n) | |||
234 | { | |||
235 | char dname[NFILEN1024], *bufp, *slash; | |||
236 | struct buffer *bp; | |||
237 | ||||
238 | if (curbp->b_fname[0] != '\0') { | |||
239 | (void)strlcpy(dname, curbp->b_fname, sizeof(dname)); | |||
240 | if ((slash = strrchr(dname, '/')) != NULL((void *)0)) { | |||
241 | *(slash + 1) = '\0'; | |||
242 | } | |||
243 | } else { | |||
244 | if (getcwd(dname, sizeof(dname)) == NULL((void *)0)) | |||
245 | dname[0] = '\0'; | |||
246 | } | |||
247 | ||||
248 | if ((bufp = eread("Dired (directory): ", dname, NFILEN1024, | |||
249 | EFDEF0x0020 | EFNEW0x0008 | EFCR0x0010)) == NULL((void *)0)) | |||
250 | return (ABORT2); | |||
251 | if (bufp[0] == '\0') | |||
252 | return (FALSE0); | |||
253 | if ((bp = dired_(bufp)) == NULL((void *)0)) | |||
254 | return (FALSE0); | |||
255 | ||||
256 | curbp = bp; | |||
257 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
258 | } | |||
259 | ||||
260 | /* ARGSUSED */ | |||
261 | int | |||
262 | d_otherwindow(int f, int n) | |||
263 | { | |||
264 | char dname[NFILEN1024], *bufp, *slash; | |||
265 | struct buffer *bp; | |||
266 | struct mgwin *wp; | |||
267 | ||||
268 | if (curbp->b_fname[0] != '\0') { | |||
269 | (void)strlcpy(dname, curbp->b_fname, sizeof(dname)); | |||
270 | if ((slash = strrchr(dname, '/')) != NULL((void *)0)) { | |||
271 | *(slash + 1) = '\0'; | |||
272 | } | |||
273 | } else { | |||
274 | if (getcwd(dname, sizeof(dname)) == NULL((void *)0)) | |||
275 | dname[0] = '\0'; | |||
276 | } | |||
277 | ||||
278 | if ((bufp = eread("Dired other window: ", dname, NFILEN1024, | |||
279 | EFDEF0x0020 | EFNEW0x0008 | EFCR0x0010)) == NULL((void *)0)) | |||
280 | return (ABORT2); | |||
281 | else if (bufp[0] == '\0') | |||
282 | return (FALSE0); | |||
283 | if ((bp = dired_(bufp)) == NULL((void *)0)) | |||
284 | return (FALSE0); | |||
285 | if ((wp = popbuf(bp, WNONE0x00)) == NULL((void *)0)) | |||
286 | return (FALSE0); | |||
287 | curbp = bp; | |||
288 | curwp = wp; | |||
289 | return (TRUE1); | |||
290 | } | |||
291 | ||||
292 | /* ARGSUSED */ | |||
293 | int | |||
294 | d_del(int f, int n) | |||
295 | { | |||
296 | if (n < 0) | |||
297 | return (FALSE0); | |||
298 | while (n--) { | |||
299 | if (d_warpdot(curwp->w_dotp, &curwp->w_doto) == TRUE1) { | |||
300 | lputc(curwp->w_dotp, 0, DDELCHAR)((curwp->w_dotp)->l_text[(0)]=(DDELCHAR)); | |||
301 | curbp->b_flag |= BFDIREDDEL0x80; | |||
302 | } | |||
303 | if (lforw(curwp->w_dotp)((curwp->w_dotp)->l_fp) != curbp->b_headp) { | |||
304 | curwp->w_dotp = lforw(curwp->w_dotp)((curwp->w_dotp)->l_fp); | |||
305 | curwp->w_dotline++; | |||
306 | } | |||
307 | } | |||
308 | curwp->w_rflag |= WFEDIT0x04 | WFMOVE0x02; | |||
309 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
310 | } | |||
311 | ||||
312 | /* ARGSUSED */ | |||
313 | int | |||
314 | d_undel(int f, int n) | |||
315 | { | |||
316 | if (n < 0) | |||
317 | return (d_undelbak(f, -n)); | |||
318 | while (n--) { | |||
319 | if (llength(curwp->w_dotp)((curwp->w_dotp)->l_used) > 0) | |||
320 | lputc(curwp->w_dotp, 0, ' ')((curwp->w_dotp)->l_text[(0)]=(' ')); | |||
321 | if (lforw(curwp->w_dotp)((curwp->w_dotp)->l_fp) != curbp->b_headp) { | |||
322 | curwp->w_dotp = lforw(curwp->w_dotp)((curwp->w_dotp)->l_fp); | |||
323 | curwp->w_dotline++; | |||
324 | } | |||
325 | } | |||
326 | curwp->w_rflag |= WFEDIT0x04 | WFMOVE0x02; | |||
327 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
328 | } | |||
329 | ||||
330 | /* ARGSUSED */ | |||
331 | int | |||
332 | d_undelbak(int f, int n) | |||
333 | { | |||
334 | if (n < 0) | |||
335 | return (d_undel(f, -n)); | |||
336 | while (n--) { | |||
337 | if (lback(curwp->w_dotp)((curwp->w_dotp)->l_bp) != curbp->b_headp) { | |||
338 | curwp->w_dotp = lback(curwp->w_dotp)((curwp->w_dotp)->l_bp); | |||
339 | curwp->w_dotline--; | |||
340 | } | |||
341 | if (llength(curwp->w_dotp)((curwp->w_dotp)->l_used) > 0) | |||
342 | lputc(curwp->w_dotp, 0, ' ')((curwp->w_dotp)->l_text[(0)]=(' ')); | |||
343 | } | |||
344 | curwp->w_rflag |= WFEDIT0x04 | WFMOVE0x02; | |||
345 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
346 | } | |||
347 | ||||
348 | /* ARGSUSED */ | |||
349 | int | |||
350 | d_findfile(int f, int n) | |||
351 | { | |||
352 | struct buffer *bp; | |||
353 | int s; | |||
354 | char fname[NFILEN1024]; | |||
355 | ||||
356 | if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT2) | |||
357 | return (FALSE0); | |||
358 | if (s == TRUE1) | |||
359 | bp = dired_(fname); | |||
360 | else | |||
361 | bp = findbuffer(fname); | |||
362 | if (bp == NULL((void *)0)) | |||
363 | return (FALSE0); | |||
364 | curbp = bp; | |||
365 | if (showbuffer(bp, curwp, WFFULL0x08) != TRUE1) | |||
366 | return (FALSE0); | |||
367 | if (bp->b_fname[0] != 0) | |||
368 | return (TRUE1); | |||
369 | return (readin(fname)); | |||
370 | } | |||
371 | ||||
372 | /* ARGSUSED */ | |||
373 | int | |||
374 | d_ffotherwindow(int f, int n) | |||
375 | { | |||
376 | char fname[NFILEN1024]; | |||
377 | int s; | |||
378 | struct buffer *bp; | |||
379 | struct mgwin *wp; | |||
380 | ||||
381 | if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT2) | |||
382 | return (FALSE0); | |||
383 | if ((bp = (s ? dired_(fname) : findbuffer(fname))) == NULL((void *)0)) | |||
384 | return (FALSE0); | |||
385 | if ((wp = popbuf(bp, WNONE0x00)) == NULL((void *)0)) | |||
386 | return (FALSE0); | |||
387 | curbp = bp; | |||
388 | curwp = wp; | |||
389 | if (bp->b_fname[0] != 0) | |||
390 | return (TRUE1); /* never true for dired buffers */ | |||
391 | return (readin(fname)); | |||
392 | } | |||
393 | ||||
394 | /* ARGSUSED */ | |||
395 | int | |||
396 | d_expunge(int f, int n) | |||
397 | { | |||
398 | struct line *lp, *nlp; | |||
399 | char fname[NFILEN1024], sname[NFILEN1024]; | |||
400 | int tmp; | |||
401 | ||||
402 | tmp = curwp->w_dotline; | |||
403 | curwp->w_dotline = 0; | |||
404 | ||||
405 | for (lp = bfirstlp(curbp)((((curbp)->b_headp)->l_fp)); lp != curbp->b_headp; lp = nlp) { | |||
406 | curwp->w_dotline++; | |||
407 | nlp = lforw(lp)((lp)->l_fp); | |||
408 | if (llength(lp)((lp)->l_used) && lgetc(lp, 0)(((unsigned char) ((lp)->l_text[(0)]))) == 'D') { | |||
409 | switch (d_makename(lp, fname, sizeof(fname))) { | |||
410 | case ABORT2: | |||
411 | dobeep(); | |||
412 | ewprintf("Bad line in dired buffer"); | |||
413 | curwp->w_dotline = tmp; | |||
414 | return (FALSE0); | |||
415 | case FALSE0: | |||
416 | if (unlink(fname) == -1) { | |||
417 | (void)xbasename(sname, fname, NFILEN1024); | |||
418 | dobeep(); | |||
419 | ewprintf("Could not delete '%s'", sname); | |||
420 | curwp->w_dotline = tmp; | |||
421 | return (FALSE0); | |||
422 | } | |||
423 | break; | |||
424 | case TRUE1: | |||
425 | if (rmdir(fname) == -1) { | |||
426 | (void)xbasename(sname, fname, NFILEN1024); | |||
427 | dobeep(); | |||
428 | ewprintf("Could not delete directory " | |||
429 | "'%s'", sname); | |||
430 | curwp->w_dotline = tmp; | |||
431 | return (FALSE0); | |||
432 | } | |||
433 | break; | |||
434 | } | |||
435 | lfree(lp); | |||
436 | curwp->w_bufp->b_lines--; | |||
437 | if (tmp > curwp->w_dotline) | |||
438 | tmp--; | |||
439 | curwp->w_rflag |= WFFULL0x08; | |||
440 | } | |||
441 | } | |||
442 | curwp->w_dotline = tmp; | |||
443 | d_warpdot(curwp->w_dotp, &curwp->w_doto); | |||
444 | ||||
445 | /* we have deleted all items successfully, remove del flag */ | |||
446 | curbp->b_flag &= ~BFDIREDDEL0x80; | |||
447 | ||||
448 | return (TRUE1); | |||
449 | } | |||
450 | ||||
451 | /* ARGSUSED */ | |||
452 | int | |||
453 | d_copy(int f, int n) | |||
454 | { | |||
455 | struct stat statbuf; | |||
456 | char frname[NFILEN1024], toname[NFILEN1024], sname[NFILEN1024]; | |||
457 | char *topath, *bufp; | |||
458 | int ret; | |||
459 | size_t off; | |||
460 | struct buffer *bp; | |||
461 | ||||
462 | if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE0) { | |||
463 | dobeep(); | |||
464 | ewprintf("Not a file"); | |||
465 | return (FALSE0); | |||
466 | } | |||
467 | off = strlcpy(toname, curbp->b_fname, sizeof(toname)); | |||
468 | if (off >= sizeof(toname) - 1) { /* can't happen, really */ | |||
469 | dobeep(); | |||
470 | ewprintf("Directory name too long"); | |||
471 | return (FALSE0); | |||
472 | } | |||
473 | (void)xbasename(sname, frname, NFILEN1024); | |||
474 | bufp = eread("Copy %s to: ", toname, sizeof(toname), | |||
475 | EFDEF0x0020 | EFNEW0x0008 | EFCR0x0010, sname); | |||
476 | if (bufp == NULL((void *)0)) | |||
477 | return (ABORT2); | |||
478 | else if (bufp[0] == '\0') | |||
479 | return (FALSE0); | |||
480 | ||||
481 | topath = adjustname(toname, TRUE1); | |||
482 | if (stat(topath, &statbuf) == 0) { | |||
483 | if (S_ISDIR(statbuf.st_mode)((statbuf.st_mode & 0170000) == 0040000)) { | |||
484 | ret = snprintf(toname, sizeof(toname), "%s/%s", | |||
485 | topath, sname); | |||
486 | if (ret < 0 || ret >= sizeof(toname) - 1) { | |||
487 | dobeep(); | |||
488 | ewprintf("Directory name too long"); | |||
489 | return (FALSE0); | |||
490 | } | |||
491 | topath = adjustname(toname, TRUE1); | |||
492 | } | |||
493 | } | |||
494 | if (topath == NULL((void *)0)) | |||
495 | return (FALSE0); | |||
496 | if (strcmp(frname, topath) == 0) { | |||
497 | ewprintf("Cannot copy to same file: %s", frname); | |||
498 | return (TRUE1); | |||
499 | } | |||
500 | ret = (copy(frname, topath) >= 0) ? TRUE1 : FALSE0; | |||
501 | if (ret != TRUE1) | |||
502 | return (ret); | |||
503 | if ((bp = refreshbuffer(curbp)) == NULL((void *)0)) | |||
504 | return (FALSE0); | |||
505 | ||||
506 | ewprintf("Copy: 1 file"); | |||
507 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
508 | } | |||
509 | ||||
510 | /* ARGSUSED */ | |||
511 | int | |||
512 | d_rename(int f, int n) | |||
513 | { | |||
514 | struct stat statbuf; | |||
515 | char frname[NFILEN1024], toname[NFILEN1024]; | |||
516 | char *topath, *bufp; | |||
517 | int ret; | |||
518 | size_t off; | |||
519 | struct buffer *bp; | |||
520 | char sname[NFILEN1024]; | |||
521 | ||||
522 | if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE0) { | |||
523 | dobeep(); | |||
524 | ewprintf("Not a file"); | |||
525 | return (FALSE0); | |||
526 | } | |||
527 | off = strlcpy(toname, curbp->b_fname, sizeof(toname)); | |||
528 | if (off >= sizeof(toname) - 1) { /* can't happen, really */ | |||
529 | dobeep(); | |||
530 | ewprintf("Name too long"); | |||
531 | return (FALSE0); | |||
532 | } | |||
533 | (void)xbasename(sname, frname, NFILEN1024); | |||
534 | bufp = eread("Rename %s to: ", toname, | |||
535 | sizeof(toname), EFDEF0x0020 | EFNEW0x0008 | EFCR0x0010, sname); | |||
536 | if (bufp == NULL((void *)0)) | |||
537 | return (ABORT2); | |||
538 | else if (bufp[0] == '\0') | |||
539 | return (FALSE0); | |||
540 | ||||
541 | topath = adjustname(toname, TRUE1); | |||
542 | if (stat(topath, &statbuf) == 0) { | |||
543 | if (S_ISDIR(statbuf.st_mode)((statbuf.st_mode & 0170000) == 0040000)) { | |||
544 | ret = snprintf(toname, sizeof(toname), "%s/%s", | |||
545 | topath, sname); | |||
546 | if (ret < 0 || ret >= sizeof(toname) - 1) { | |||
547 | dobeep(); | |||
548 | ewprintf("Directory name too long"); | |||
549 | return (FALSE0); | |||
550 | } | |||
551 | topath = adjustname(toname, TRUE1); | |||
552 | } | |||
553 | } | |||
554 | if (topath == NULL((void *)0)) | |||
555 | return (FALSE0); | |||
556 | if (strcmp(frname, topath) == 0) { | |||
557 | ewprintf("Cannot move to same file: %s", frname); | |||
558 | return (TRUE1); | |||
559 | } | |||
560 | ret = (rename(frname, topath) >= 0) ? TRUE1 : FALSE0; | |||
561 | if (ret != TRUE1) | |||
562 | return (ret); | |||
563 | if ((bp = refreshbuffer(curbp)) == NULL((void *)0)) | |||
564 | return (FALSE0); | |||
565 | ||||
566 | ewprintf("Move: 1 file"); | |||
567 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
568 | } | |||
569 | ||||
570 | /* ARGSUSED */ | |||
571 | void | |||
572 | reaper(int signo __attribute__((unused))) | |||
573 | { | |||
574 | int save_errno = errno(*__errno()), status; | |||
575 | ||||
576 | while (waitpid(-1, &status, WNOHANG1) >= 0) | |||
577 | ; | |||
578 | errno(*__errno()) = save_errno; | |||
579 | } | |||
580 | ||||
581 | /* | |||
582 | * Pipe the currently selected file through a shell command. | |||
583 | */ | |||
584 | /* ARGSUSED */ | |||
585 | int | |||
586 | d_shell_command(int f, int n) | |||
587 | { | |||
588 | char command[512], fname[PATH_MAX1024], *bufp; | |||
589 | struct buffer *bp; | |||
590 | struct mgwin *wp; | |||
591 | char sname[NFILEN1024]; | |||
592 | ||||
593 | bp = bfind("*Shell Command Output*", TRUE1); | |||
594 | if (bclear(bp) != TRUE1) | |||
595 | return (ABORT2); | |||
596 | ||||
597 | if (d_makename(curwp->w_dotp, fname, sizeof(fname)) != FALSE0) { | |||
598 | dobeep(); | |||
599 | ewprintf("bad line"); | |||
600 | return (ABORT2); | |||
601 | } | |||
602 | ||||
603 | command[0] = '\0'; | |||
604 | (void)xbasename(sname, fname, NFILEN1024); | |||
605 | bufp = eread("! on %s: ", command, sizeof(command), EFNEW0x0008, sname); | |||
606 | if (bufp == NULL((void *)0)) | |||
607 | return (ABORT2); | |||
608 | ||||
609 | if (d_exec(0, bp, fname, "sh", "-c", command, NULL((void *)0)) != TRUE1) | |||
610 | return (ABORT2); | |||
611 | ||||
612 | if ((wp = popbuf(bp, WNONE0x00)) == NULL((void *)0)) | |||
613 | return (ABORT2); /* XXX - free the buffer?? */ | |||
614 | curwp = wp; | |||
615 | curbp = wp->w_bufp; | |||
616 | return (TRUE1); | |||
617 | } | |||
618 | ||||
619 | /* | |||
620 | * Pipe input file to cmd and insert the command's output in the | |||
621 | * given buffer. Each line will be prefixed with the given | |||
622 | * number of spaces. | |||
623 | */ | |||
624 | static int | |||
625 | d_exec(int space, struct buffer *bp, const char *input, const char *cmd, ...) | |||
626 | { | |||
627 | char buf[BUFSIZ1024]; | |||
628 | va_list ap; | |||
629 | struct sigaction olda, newa; | |||
630 | char **argv = NULL((void *)0), *cp; | |||
631 | FILE *fin; | |||
632 | int fds[2] = { -1, -1 }; | |||
633 | int infd = -1; | |||
634 | int ret = (ABORT2), n; | |||
635 | pid_t pid; | |||
636 | ||||
637 | if (sigaction(SIGCHLD20, NULL((void *)0), &olda) == -1) | |||
638 | return (ABORT2); | |||
639 | ||||
640 | /* Find the number of arguments. */ | |||
641 | va_start(ap, cmd)__builtin_va_start(ap, cmd); | |||
642 | for (n = 2; va_arg(ap, char *)__builtin_va_arg(ap, char *) != NULL((void *)0); n++) | |||
643 | ; | |||
644 | va_end(ap)__builtin_va_end(ap); | |||
645 | ||||
646 | /* Allocate and build the argv. */ | |||
647 | if ((argv = calloc(n, sizeof(*argv))) == NULL((void *)0)) { | |||
648 | dobeep(); | |||
649 | ewprintf("Can't allocate argv : %s", strerror(errno(*__errno()))); | |||
650 | goto out; | |||
651 | } | |||
652 | ||||
653 | n = 1; | |||
654 | argv[0] = (char *)cmd; | |||
655 | va_start(ap, cmd)__builtin_va_start(ap, cmd); | |||
656 | while ((argv[n] = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void *)0)) | |||
657 | n++; | |||
658 | va_end(ap)__builtin_va_end(ap); | |||
659 | ||||
660 | if (input == NULL((void *)0)) | |||
661 | input = "/dev/null"; | |||
662 | ||||
663 | if ((infd = open(input, O_RDONLY0x0000)) == -1) { | |||
664 | dobeep(); | |||
665 | ewprintf("Can't open input file : %s", strerror(errno(*__errno()))); | |||
666 | goto out; | |||
667 | } | |||
668 | ||||
669 | if (pipe(fds) == -1) { | |||
670 | dobeep(); | |||
671 | ewprintf("Can't create pipe : %s", strerror(errno(*__errno()))); | |||
672 | goto out; | |||
673 | } | |||
674 | ||||
675 | newa.sa_handler__sigaction_u.__sa_handler = reaper; | |||
676 | newa.sa_flags = 0; | |||
677 | if (sigaction(SIGCHLD20, &newa, NULL((void *)0)) == -1) | |||
678 | goto out; | |||
679 | ||||
680 | if ((pid = fork()) == -1) { | |||
681 | dobeep(); | |||
682 | ewprintf("Can't fork"); | |||
683 | goto out; | |||
684 | } | |||
685 | ||||
686 | switch (pid) { | |||
687 | case 0: /* Child */ | |||
688 | close(fds[0]); | |||
689 | dup2(infd, STDIN_FILENO0); | |||
690 | dup2(fds[1], STDOUT_FILENO1); | |||
691 | dup2(fds[1], STDERR_FILENO2); | |||
692 | if (execvp(argv[0], argv) == -1) | |||
693 | ewprintf("Can't exec %s: %s", argv[0], strerror(errno(*__errno()))); | |||
694 | exit(1); | |||
695 | break; | |||
696 | default: /* Parent */ | |||
697 | close(infd); | |||
698 | close(fds[1]); | |||
699 | infd = fds[1] = -1; | |||
700 | if ((fin = fdopen(fds[0], "r")) == NULL((void *)0)) | |||
701 | goto out; | |||
702 | while (fgets(buf, sizeof(buf), fin) != NULL((void *)0)) { | |||
703 | cp = strrchr(buf, *bp->b_nlchr); | |||
704 | if (cp == NULL((void *)0) && !feof(fin)(!__isthreaded ? (((fin)->_flags & 0x0020) != 0) : (feof )(fin))) { /* too long a line */ | |||
705 | int c; | |||
706 | addlinef(bp, "%*s%s...", space, "", buf); | |||
707 | while ((c = getc(fin)(!__isthreaded ? (--(fin)->_r < 0 ? __srget(fin) : (int )(*(fin)->_p++)) : (getc)(fin))) != EOF(-1) && | |||
708 | c != *bp->b_nlchr) | |||
709 | ; | |||
710 | continue; | |||
711 | } else if (cp) | |||
712 | *cp = '\0'; | |||
713 | addlinef(bp, "%*s%s", space, "", buf); | |||
714 | } | |||
715 | fclose(fin); | |||
716 | break; | |||
717 | } | |||
718 | ret = (TRUE1); | |||
719 | ||||
720 | out: | |||
721 | if (sigaction(SIGCHLD20, &olda, NULL((void *)0)) == -1) | |||
722 | ewprintf("Warning, couldn't reset previous signal handler"); | |||
723 | if (fds[0] != -1) | |||
724 | close(fds[0]); | |||
725 | if (fds[1] != -1) | |||
726 | close(fds[1]); | |||
727 | if (infd != -1) | |||
728 | close(infd); | |||
729 | free(argv); | |||
730 | return ret; | |||
731 | } | |||
732 | ||||
733 | /* ARGSUSED */ | |||
734 | int | |||
735 | d_create_directory(int f, int n) | |||
736 | { | |||
737 | int ret; | |||
738 | struct buffer *bp; | |||
739 | ||||
740 | ret = ask_makedir(); | |||
741 | if (ret != TRUE1) | |||
742 | return(ret); | |||
743 | ||||
744 | if ((bp = refreshbuffer(curbp)) == NULL((void *)0)) | |||
745 | return (FALSE0); | |||
746 | ||||
747 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
748 | } | |||
749 | ||||
750 | /* ARGSUSED */ | |||
751 | int | |||
752 | d_killbuffer_cmd(int f, int n) | |||
753 | { | |||
754 | return(killbuffer_cmd(FFRAND8, 0)); | |||
755 | } | |||
756 | ||||
757 | int | |||
758 | d_refreshbuffer(int f, int n) | |||
759 | { | |||
760 | struct buffer *bp; | |||
761 | ||||
762 | if ((bp = refreshbuffer(curbp)) == NULL((void *)0)) | |||
| ||||
763 | return (FALSE0); | |||
764 | ||||
765 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
766 | } | |||
767 | ||||
768 | /* | |||
769 | * Kill then re-open the requested dired buffer. | |||
770 | * If required, take a note of any files marked for deletion. Then once | |||
771 | * the buffer has been re-opened, remark the same files as deleted. | |||
772 | */ | |||
773 | struct buffer * | |||
774 | refreshbuffer(struct buffer *bp) | |||
775 | { | |||
776 | char *tmp_b_fname; | |||
777 | int i, tmp_w_dotline, ddel = 0; | |||
778 | ||||
779 | /* remember directory path to open later */ | |||
780 | tmp_b_fname = strdup(bp->b_fname); | |||
781 | if (tmp_b_fname == NULL((void *)0)) { | |||
782 | dobeep(); | |||
783 | ewprintf("Out of memory"); | |||
784 | return (NULL((void *)0)); | |||
785 | } | |||
786 | tmp_w_dotline = curwp->w_dotline; | |||
787 | ||||
788 | /* create a list of files for deletion */ | |||
789 | if (bp->b_flag & BFDIREDDEL0x80) | |||
790 | ddel = createlist(bp); | |||
791 | ||||
792 | killbuffer(bp); | |||
793 | ||||
794 | /* dired_() uses findbuffer() to create new buffer */ | |||
795 | if ((bp = dired_(tmp_b_fname)) == NULL((void *)0)) { | |||
796 | free(tmp_b_fname); | |||
797 | return (NULL((void *)0)); | |||
798 | } | |||
799 | free(tmp_b_fname); | |||
800 | ||||
801 | /* remark any previously deleted files with a 'D' */ | |||
802 | if (ddel) | |||
803 | redelete(bp); | |||
804 | ||||
805 | /* find dot line */ | |||
806 | bp->b_dotp = bfirstlp(bp)((((bp)->b_headp)->l_fp)); | |||
807 | if (tmp_w_dotline > bp->b_lines) | |||
808 | tmp_w_dotline = bp->b_lines - 1; | |||
809 | for (i = 1; i < tmp_w_dotline; i++) | |||
810 | bp->b_dotp = lforw(bp->b_dotp)((bp->b_dotp)->l_fp); | |||
811 | ||||
812 | bp->b_dotline = i; | |||
813 | bp->b_doto = 0; | |||
814 | d_warpdot(bp->b_dotp, &bp->b_doto); | |||
815 | ||||
816 | curbp = bp; | |||
817 | ||||
818 | return (bp); | |||
819 | } | |||
820 | ||||
821 | static int | |||
822 | d_makename(struct line *lp, char *fn, size_t len) | |||
823 | { | |||
824 | int start, nlen, ret; | |||
825 | char *namep; | |||
826 | ||||
827 | if (d_warpdot(lp, &start) == FALSE0) | |||
828 | return (ABORT2); | |||
829 | namep = &lp->l_text[start]; | |||
830 | nlen = llength(lp)((lp)->l_used) - start; | |||
831 | ||||
832 | ret = snprintf(fn, len, "%s%.*s", curbp->b_fname, nlen, namep); | |||
833 | if (ret < 0 || ret >= (int)len) | |||
834 | return (ABORT2); /* Name is too long. */ | |||
835 | ||||
836 | /* Return TRUE if the entry is a directory. */ | |||
837 | return ((lgetc(lp, 2)(((unsigned char) ((lp)->l_text[(2)]))) == 'd') ? TRUE1 : FALSE0); | |||
838 | } | |||
839 | ||||
840 | #define NAME_FIELD9 9 | |||
841 | ||||
842 | static int | |||
843 | d_warpdot(struct line *dotp, int *doto) | |||
844 | { | |||
845 | char *tp = dotp->l_text; | |||
846 | int off = 0, field = 0, len; | |||
847 | ||||
848 | /* | |||
849 | * Find the byte offset to the (space-delimited) filename | |||
850 | * field in formatted ls output. | |||
851 | */ | |||
852 | len = llength(dotp)((dotp)->l_used); | |||
853 | while (off < len) { | |||
854 | if (tp[off++] == ' ') { | |||
855 | if (++field == NAME_FIELD9) { | |||
856 | *doto = off; | |||
857 | return (TRUE1); | |||
858 | } | |||
859 | /* Skip the space. */ | |||
860 | while (off < len && tp[off] == ' ') | |||
861 | off++; | |||
862 | } | |||
863 | } | |||
864 | /* We didn't find the field. */ | |||
865 | *doto = 0; | |||
866 | return (FALSE0); | |||
867 | } | |||
868 | ||||
869 | static int | |||
870 | d_forwpage(int f, int n) | |||
871 | { | |||
872 | forwpage(f | FFRAND8, n); | |||
873 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
874 | } | |||
875 | ||||
876 | static int | |||
877 | d_backpage (int f, int n) | |||
878 | { | |||
879 | backpage(f | FFRAND8, n); | |||
880 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
881 | } | |||
882 | ||||
883 | static int | |||
884 | d_forwline (int f, int n) | |||
885 | { | |||
886 | forwline(f | FFRAND8, n); | |||
887 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
888 | } | |||
889 | ||||
890 | static int | |||
891 | d_backline (int f, int n) | |||
892 | { | |||
893 | backline(f | FFRAND8, n); | |||
894 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
895 | } | |||
896 | ||||
897 | int | |||
898 | d_filevisitalt (int f, int n) | |||
899 | { | |||
900 | char fname[NFILEN1024]; | |||
901 | ||||
902 | if (d_makename(curwp->w_dotp, fname, sizeof(fname)) == ABORT2) | |||
903 | return (FALSE0); | |||
904 | ||||
905 | return(do_filevisitalt(fname)); | |||
906 | } | |||
907 | ||||
908 | /* | |||
909 | * XXX dname needs to have enough place to store an additional '/'. | |||
910 | */ | |||
911 | struct buffer * | |||
912 | dired_(char *dname) | |||
913 | { | |||
914 | struct buffer *bp; | |||
915 | int i; | |||
916 | size_t len; | |||
917 | ||||
918 | if ((dname = adjustname(dname, TRUE1)) == NULL((void *)0)) { | |||
919 | dobeep(); | |||
920 | ewprintf("Bad directory name"); | |||
921 | return (NULL((void *)0)); | |||
922 | } | |||
923 | /* this should not be done, instead adjustname() should get a flag */ | |||
924 | len = strlen(dname); | |||
925 | if (dname[len - 1] != '/') { | |||
926 | dname[len++] = '/'; | |||
927 | dname[len] = '\0'; | |||
928 | } | |||
929 | if ((access(dname, R_OK0x04 | X_OK0x01)) == -1) { | |||
930 | if (errno(*__errno()) == EACCES13) { | |||
931 | dobeep(); | |||
932 | ewprintf("Permission denied: %s", dname); | |||
933 | } else { | |||
934 | dobeep(); | |||
935 | ewprintf("Error opening: %s", dname); | |||
936 | } | |||
937 | return (NULL((void *)0)); | |||
938 | } | |||
939 | for (bp = bheadp; bp != NULL((void *)0); bp = bp->b_bufpb_list.l_p.x_bp) { | |||
940 | if (strcmp(bp->b_fname, dname) == 0) { | |||
941 | if (fchecktime(bp) != TRUE1) | |||
942 | ewprintf("Directory has changed on disk;" | |||
943 | " type g to update Dired"); | |||
944 | return (bp); | |||
945 | } | |||
946 | ||||
947 | } | |||
948 | bp = bfind(dname, TRUE1); | |||
949 | bp->b_flag |= BFREADONLY0x10 | BFIGNDIRTY0x40; | |||
950 | ||||
951 | if ((d_exec(2, bp, NULL((void *)0), "ls", "-al", dname, NULL((void *)0))) != TRUE1) | |||
952 | return (NULL((void *)0)); | |||
953 | ||||
954 | /* Find the line with ".." on it. */ | |||
955 | bp->b_dotp = bfirstlp(bp)((((bp)->b_headp)->l_fp)); | |||
956 | bp->b_dotline = 1; | |||
957 | for (i = 0; i < bp->b_lines; i++) { | |||
958 | bp->b_dotp = lforw(bp->b_dotp)((bp->b_dotp)->l_fp); | |||
959 | bp->b_dotline++; | |||
960 | if (d_warpdot(bp->b_dotp, &bp->b_doto) == FALSE0) | |||
961 | continue; | |||
962 | if (strcmp(ltext(bp->b_dotp)((bp->b_dotp)->l_text) + bp->b_doto, "..") == 0) | |||
963 | break; | |||
964 | } | |||
965 | ||||
966 | /* We want dot on the entry right after "..", if possible. */ | |||
967 | if (++i < bp->b_lines - 2) { | |||
968 | bp->b_dotp = lforw(bp->b_dotp)((bp->b_dotp)->l_fp); | |||
969 | bp->b_dotline++; | |||
970 | } | |||
971 | d_warpdot(bp->b_dotp, &bp->b_doto); | |||
972 | ||||
973 | (void)strlcpy(bp->b_fname, dname, sizeof(bp->b_fname)); | |||
974 | (void)strlcpy(bp->b_cwd, dname, sizeof(bp->b_cwd)); | |||
975 | if ((bp->b_modes[1] = name_mode("dired")) == NULL((void *)0)) { | |||
976 | bp->b_modes[0] = name_mode("fundamental"); | |||
977 | dobeep(); | |||
978 | ewprintf("Could not find mode dired"); | |||
979 | return (NULL((void *)0)); | |||
980 | } | |||
981 | (void)fupdstat(bp); | |||
982 | bp->b_nmodes = 1; | |||
983 | return (bp); | |||
984 | } | |||
985 | ||||
986 | /* | |||
987 | * Iterate through the lines of the dired buffer looking for files | |||
988 | * collected in the linked list made in createlist(). If a line is found | |||
989 | * replace 'D' as first char in a line. As lines are found, remove the | |||
990 | * corresponding item from the linked list. Iterate for as long as there | |||
991 | * are items in the linked list or until end of buffer is found. | |||
992 | */ | |||
993 | void | |||
994 | redelete(struct buffer *bp) | |||
995 | { | |||
996 | struct delentry *dt, *d1 = NULL((void *)0); | |||
997 | struct line *lp, *nlp; | |||
998 | char fname[NFILEN1024]; | |||
999 | char *p = fname; | |||
1000 | size_t plen, fnlen; | |||
1001 | int finished = 0; | |||
1002 | ||||
1003 | /* reset the deleted file buffer flag until a deleted file is found */ | |||
1004 | bp->b_flag &= ~BFDIREDDEL0x80; | |||
1005 | ||||
1006 | for (lp = bfirstlp(bp)((((bp)->b_headp)->l_fp)); lp != bp->b_headp; lp = nlp) { | |||
1007 | bp->b_dotp = lp; | |||
1008 | if ((p = findfname(lp, p)) == NULL((void *)0)) { | |||
1009 | nlp = lforw(lp)((lp)->l_fp); | |||
1010 | continue; | |||
1011 | } | |||
1012 | plen = strlen(p); | |||
1013 | SLIST_FOREACH_SAFE(d1, &delhead, entry, dt)for ((d1) = ((&delhead)->slh_first); (d1) && ( (dt) = ((d1)->entry.sle_next), 1); (d1) = (dt)) { | |||
1014 | fnlen = strlen(d1->fn); | |||
1015 | if ((plen == fnlen) && | |||
1016 | (strncmp(p, d1->fn, plen) == 0)) { | |||
1017 | lputc(bp->b_dotp, 0, DDELCHAR)((bp->b_dotp)->l_text[(0)]=(DDELCHAR)); | |||
1018 | bp->b_flag |= BFDIREDDEL0x80; | |||
1019 | SLIST_REMOVE(&delhead, d1, delentry, entry)do { if ((&delhead)->slh_first == (d1)) { do { ((& delhead))->slh_first = ((&delhead))->slh_first-> entry.sle_next; } while (0); } else { struct delentry *curelm = (&delhead)->slh_first; while (curelm->entry.sle_next != (d1)) curelm = curelm->entry.sle_next; curelm->entry .sle_next = curelm->entry.sle_next->entry.sle_next; } ; } while (0); | |||
1020 | if (SLIST_EMPTY(&delhead)(((&delhead)->slh_first) == ((void *)0))) { | |||
1021 | finished = 1; | |||
1022 | break; | |||
1023 | } | |||
1024 | } | |||
1025 | } | |||
1026 | if (finished) | |||
1027 | break; | |||
1028 | nlp = lforw(lp)((lp)->l_fp); | |||
1029 | } | |||
1030 | while (!SLIST_EMPTY(&delhead)(((&delhead)->slh_first) == ((void *)0))) { | |||
1031 | d1 = SLIST_FIRST(&delhead)((&delhead)->slh_first); | |||
1032 | SLIST_REMOVE_HEAD(&delhead, entry)do { (&delhead)->slh_first = (&delhead)->slh_first ->entry.sle_next; } while (0); | |||
1033 | free(d1->fn); | |||
1034 | free(d1); | |||
1035 | } | |||
1036 | return; | |||
1037 | } | |||
1038 | ||||
1039 | /* | |||
1040 | * Create a list of files marked for deletion. | |||
1041 | */ | |||
1042 | int | |||
1043 | createlist(struct buffer *bp) | |||
1044 | { | |||
1045 | struct delentry *d1 = NULL((void *)0), *d2; | |||
1046 | struct line *lp, *nlp; | |||
1047 | char fname[NFILEN1024]; | |||
1048 | char *p = fname; | |||
1049 | int ret = FALSE0; | |||
1050 | ||||
1051 | for (lp = bfirstlp(bp)((((bp)->b_headp)->l_fp)); lp != bp->b_headp; lp = nlp) { | |||
1052 | /* | |||
1053 | * Check if the line has 'D' on the first char and if a valid | |||
1054 | * filename can be extracted from it. | |||
1055 | */ | |||
1056 | if (((lp->l_text[0] != DDELCHAR)) || | |||
1057 | ((p = findfname(lp, p)) == NULL((void *)0))) { | |||
1058 | nlp = lforw(lp)((lp)->l_fp); | |||
1059 | continue; | |||
1060 | } | |||
1061 | if (SLIST_EMPTY(&delhead)(((&delhead)->slh_first) == ((void *)0))) { | |||
1062 | if ((d1 = malloc(sizeof(struct delentry))) | |||
1063 | == NULL((void *)0)) | |||
1064 | return (ABORT2); | |||
1065 | if ((d1->fn = strdup(p)) == NULL((void *)0)) { | |||
1066 | free(d1); | |||
1067 | return (ABORT2); | |||
1068 | } | |||
1069 | SLIST_INSERT_HEAD(&delhead, d1, entry)do { (d1)->entry.sle_next = (&delhead)->slh_first; ( &delhead)->slh_first = (d1); } while (0); | |||
1070 | } else { | |||
1071 | if ((d2 = malloc(sizeof(struct delentry))) | |||
1072 | == NULL((void *)0)) { | |||
1073 | free(d1->fn); | |||
| ||||
1074 | free(d1); | |||
1075 | return (ABORT2); | |||
1076 | } | |||
1077 | if ((d2->fn = strdup(p)) == NULL((void *)0)) { | |||
1078 | free(d1->fn); | |||
1079 | free(d1); | |||
1080 | free(d2); | |||
1081 | return (ABORT2); | |||
1082 | } | |||
1083 | if (!d1) | |||
1084 | SLIST_INSERT_HEAD(&delhead, d2, entry)do { (d2)->entry.sle_next = (&delhead)->slh_first; ( &delhead)->slh_first = (d2); } while (0); | |||
1085 | else | |||
1086 | SLIST_INSERT_AFTER(d1, d2, entry)do { (d2)->entry.sle_next = (d1)->entry.sle_next; (d1)-> entry.sle_next = (d2); } while (0); | |||
1087 | d1 = d2; | |||
1088 | } | |||
1089 | ret = TRUE1; | |||
1090 | nlp = lforw(lp)((lp)->l_fp); | |||
1091 | } | |||
1092 | return (ret); | |||
1093 | } | |||
1094 | ||||
1095 | int | |||
1096 | dired_jump(int f, int n) | |||
1097 | { | |||
1098 | struct buffer *bp; | |||
1099 | const char *modename; | |||
1100 | char dname[NFILEN1024], *fname; | |||
1101 | int ret, i; | |||
1102 | ||||
1103 | /* | |||
1104 | * We use fundamental mode in dired, so just check we aren't in | |||
1105 | * dired mode for this specific function. Seems like a corner | |||
1106 | * case at the moment. | |||
1107 | */ | |||
1108 | for (i = 0; i <= curbp->b_nmodes; i++) { | |||
1109 | modename = curbp->b_modes[i]->p_name; | |||
1110 | if (strncmp(modename, "dired", 5) == 0) | |||
1111 | return (dobeep_msg("In dired mode already")); | |||
1112 | } | |||
1113 | ||||
1114 | if (getbufcwd(dname, sizeof(dname)) != TRUE1) | |||
1115 | return (FALSE0); | |||
1116 | ||||
1117 | fname = curbp->b_fname; | |||
1118 | ||||
1119 | if ((bp = dired_(dname)) == NULL((void *)0)) | |||
1120 | return (FALSE0); | |||
1121 | curbp = bp; | |||
1122 | ||||
1123 | ret = showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10); | |||
1124 | if (ret != TRUE1) | |||
1125 | return ret; | |||
1126 | ||||
1127 | fname = adjustname(fname, TRUE1); | |||
1128 | if (fname != NULL((void *)0)) | |||
1129 | gotofile(fname); | |||
1130 | ||||
1131 | return (TRUE1); | |||
1132 | } | |||
1133 | ||||
1134 | int | |||
1135 | d_gotofile(int f, int n) | |||
1136 | { | |||
1137 | size_t lenfpath; | |||
1138 | char fpath[NFILEN1024]; | |||
1139 | char *fpth, *fnp = NULL((void *)0); | |||
1140 | ||||
1141 | if (getbufcwd(fpath, sizeof(fpath)) != TRUE1) | |||
1142 | fpath[0] = '\0'; | |||
1143 | lenfpath = strlen(fpath); | |||
1144 | fnp = eread("Goto file: ", fpath, NFILEN1024, | |||
1145 | EFNEW0x0008 | EFCR0x0010 | EFFILE0x0004 | EFDEF0x0020); | |||
1146 | if (fnp == NULL((void *)0)) | |||
1147 | return (ABORT2); | |||
1148 | else if (fnp[0] == '\0') | |||
1149 | return (FALSE0); | |||
1150 | ||||
1151 | fpth = adjustname(fpath, TRUE1); /* Removes last '/' if dir... */ | |||
1152 | if (fpth == NULL((void *)0) || strlen(fpth) == lenfpath - 1) { /* ...hence -1. */ | |||
1153 | ewprintf("No file to find"); /* Current directory given so */ | |||
1154 | return (TRUE1); /* return at present location. */ | |||
1155 | } | |||
1156 | return gotofile(fpth); | |||
1157 | } | |||
1158 | ||||
1159 | int | |||
1160 | gotofile(char *fpth) | |||
1161 | { | |||
1162 | struct line *lp, *nlp; | |||
1163 | char fname[NFILEN1024]; | |||
1164 | char *p; | |||
1165 | int tmp; | |||
1166 | ||||
1167 | (void)xbasename(fname, fpth, NFILEN1024); | |||
1168 | tmp = 0; | |||
1169 | for (lp = bfirstlp(curbp)((((curbp)->b_headp)->l_fp)); lp != curbp->b_headp; lp = nlp) { | |||
1170 | tmp++; | |||
1171 | if ((p = findfname(lp, p)) == NULL((void *)0)) { | |||
1172 | nlp = lforw(lp)((lp)->l_fp); | |||
1173 | continue; | |||
1174 | } | |||
1175 | if (strcmp(fname, p) == 0) { | |||
1176 | curwp->w_dotp = lp; | |||
1177 | curwp->w_dotline = tmp; | |||
1178 | (void)d_warpdot(curwp->w_dotp, &curwp->w_doto); | |||
1179 | tmp--; | |||
1180 | break; | |||
1181 | } | |||
1182 | nlp = lforw(lp)((lp)->l_fp); | |||
1183 | } | |||
1184 | if (tmp == curbp->b_lines - 1) { | |||
1185 | ewprintf("File not found %s", fname); | |||
1186 | return (FALSE0); | |||
1187 | } else { | |||
1188 | ewprintf(""); | |||
1189 | return (TRUE1); | |||
1190 | } | |||
1191 | } | |||
1192 | ||||
1193 | /* | |||
1194 | * Look for and extract a file name on a dired buffer line. | |||
1195 | */ | |||
1196 | char * | |||
1197 | findfname(struct line *lp, char *fn) | |||
1198 | { | |||
1199 | int start; | |||
1200 | ||||
1201 | (void)d_warpdot(lp, &start); | |||
1202 | if (start < 1) | |||
1203 | return NULL((void *)0); | |||
1204 | fn = &lp->l_text[start]; | |||
1205 | return fn; | |||
1206 | } |