File: | src/usr.bin/mg/dired.c |
Warning: | line 1059, 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.102 2023/03/08 04:43:11 guenther 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 | int | |||
232 | dired(int f, int n) | |||
233 | { | |||
234 | char dname[NFILEN1024], *bufp, *slash; | |||
235 | struct buffer *bp; | |||
236 | ||||
237 | if (curbp->b_fname[0] != '\0') { | |||
238 | (void)strlcpy(dname, curbp->b_fname, sizeof(dname)); | |||
239 | if ((slash = strrchr(dname, '/')) != NULL((void *)0)) { | |||
240 | *(slash + 1) = '\0'; | |||
241 | } | |||
242 | } else { | |||
243 | if (getcwd(dname, sizeof(dname)) == NULL((void *)0)) | |||
244 | dname[0] = '\0'; | |||
245 | } | |||
246 | ||||
247 | if ((bufp = eread("Dired (directory): ", dname, NFILEN1024, | |||
248 | EFDEF0x0020 | EFNEW0x0008 | EFCR0x0010)) == NULL((void *)0)) | |||
249 | return (ABORT2); | |||
250 | if (bufp[0] == '\0') | |||
251 | return (FALSE0); | |||
252 | if ((bp = dired_(bufp)) == NULL((void *)0)) | |||
253 | return (FALSE0); | |||
254 | ||||
255 | curbp = bp; | |||
256 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
257 | } | |||
258 | ||||
259 | int | |||
260 | d_otherwindow(int f, int n) | |||
261 | { | |||
262 | char dname[NFILEN1024], *bufp, *slash; | |||
263 | struct buffer *bp; | |||
264 | struct mgwin *wp; | |||
265 | ||||
266 | if (curbp->b_fname[0] != '\0') { | |||
267 | (void)strlcpy(dname, curbp->b_fname, sizeof(dname)); | |||
268 | if ((slash = strrchr(dname, '/')) != NULL((void *)0)) { | |||
269 | *(slash + 1) = '\0'; | |||
270 | } | |||
271 | } else { | |||
272 | if (getcwd(dname, sizeof(dname)) == NULL((void *)0)) | |||
273 | dname[0] = '\0'; | |||
274 | } | |||
275 | ||||
276 | if ((bufp = eread("Dired other window: ", dname, NFILEN1024, | |||
277 | EFDEF0x0020 | EFNEW0x0008 | EFCR0x0010)) == NULL((void *)0)) | |||
278 | return (ABORT2); | |||
279 | else if (bufp[0] == '\0') | |||
280 | return (FALSE0); | |||
281 | if ((bp = dired_(bufp)) == NULL((void *)0)) | |||
282 | return (FALSE0); | |||
283 | if ((wp = popbuf(bp, WNONE0x00)) == NULL((void *)0)) | |||
284 | return (FALSE0); | |||
285 | curbp = bp; | |||
286 | curwp = wp; | |||
287 | return (TRUE1); | |||
288 | } | |||
289 | ||||
290 | int | |||
291 | d_del(int f, int n) | |||
292 | { | |||
293 | if (n < 0) | |||
294 | return (FALSE0); | |||
295 | while (n--) { | |||
296 | if (d_warpdot(curwp->w_dotp, &curwp->w_doto) == TRUE1) { | |||
297 | lputc(curwp->w_dotp, 0, DDELCHAR)((curwp->w_dotp)->l_text[(0)]=(DDELCHAR)); | |||
298 | curbp->b_flag |= BFDIREDDEL0x80; | |||
299 | } | |||
300 | if (lforw(curwp->w_dotp)((curwp->w_dotp)->l_fp) != curbp->b_headp) { | |||
301 | curwp->w_dotp = lforw(curwp->w_dotp)((curwp->w_dotp)->l_fp); | |||
302 | curwp->w_dotline++; | |||
303 | } | |||
304 | } | |||
305 | curwp->w_rflag |= WFEDIT0x04 | WFMOVE0x02; | |||
306 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
307 | } | |||
308 | ||||
309 | int | |||
310 | d_undel(int f, int n) | |||
311 | { | |||
312 | if (n < 0) | |||
313 | return (d_undelbak(f, -n)); | |||
314 | while (n--) { | |||
315 | if (llength(curwp->w_dotp)((curwp->w_dotp)->l_used) > 0) | |||
316 | lputc(curwp->w_dotp, 0, ' ')((curwp->w_dotp)->l_text[(0)]=(' ')); | |||
317 | if (lforw(curwp->w_dotp)((curwp->w_dotp)->l_fp) != curbp->b_headp) { | |||
318 | curwp->w_dotp = lforw(curwp->w_dotp)((curwp->w_dotp)->l_fp); | |||
319 | curwp->w_dotline++; | |||
320 | } | |||
321 | } | |||
322 | curwp->w_rflag |= WFEDIT0x04 | WFMOVE0x02; | |||
323 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
324 | } | |||
325 | ||||
326 | int | |||
327 | d_undelbak(int f, int n) | |||
328 | { | |||
329 | if (n < 0) | |||
330 | return (d_undel(f, -n)); | |||
331 | while (n--) { | |||
332 | if (lback(curwp->w_dotp)((curwp->w_dotp)->l_bp) != curbp->b_headp) { | |||
333 | curwp->w_dotp = lback(curwp->w_dotp)((curwp->w_dotp)->l_bp); | |||
334 | curwp->w_dotline--; | |||
335 | } | |||
336 | if (llength(curwp->w_dotp)((curwp->w_dotp)->l_used) > 0) | |||
337 | lputc(curwp->w_dotp, 0, ' ')((curwp->w_dotp)->l_text[(0)]=(' ')); | |||
338 | } | |||
339 | curwp->w_rflag |= WFEDIT0x04 | WFMOVE0x02; | |||
340 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
341 | } | |||
342 | ||||
343 | int | |||
344 | d_findfile(int f, int n) | |||
345 | { | |||
346 | struct buffer *bp; | |||
347 | int s; | |||
348 | char fname[NFILEN1024]; | |||
349 | ||||
350 | if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT2) | |||
351 | return (FALSE0); | |||
352 | if (s == TRUE1) | |||
353 | bp = dired_(fname); | |||
354 | else | |||
355 | bp = findbuffer(fname); | |||
356 | if (bp == NULL((void *)0)) | |||
357 | return (FALSE0); | |||
358 | curbp = bp; | |||
359 | if (showbuffer(bp, curwp, WFFULL0x08) != TRUE1) | |||
360 | return (FALSE0); | |||
361 | if (bp->b_fname[0] != 0) | |||
362 | return (TRUE1); | |||
363 | return (readin(fname)); | |||
364 | } | |||
365 | ||||
366 | int | |||
367 | d_ffotherwindow(int f, int n) | |||
368 | { | |||
369 | char fname[NFILEN1024]; | |||
370 | int s; | |||
371 | struct buffer *bp; | |||
372 | struct mgwin *wp; | |||
373 | ||||
374 | if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT2) | |||
375 | return (FALSE0); | |||
376 | if ((bp = (s ? dired_(fname) : findbuffer(fname))) == NULL((void *)0)) | |||
377 | return (FALSE0); | |||
378 | if ((wp = popbuf(bp, WNONE0x00)) == NULL((void *)0)) | |||
379 | return (FALSE0); | |||
380 | curbp = bp; | |||
381 | curwp = wp; | |||
382 | if (bp->b_fname[0] != 0) | |||
383 | return (TRUE1); /* never true for dired buffers */ | |||
384 | return (readin(fname)); | |||
385 | } | |||
386 | ||||
387 | int | |||
388 | d_expunge(int f, int n) | |||
389 | { | |||
390 | struct line *lp, *nlp; | |||
391 | char fname[NFILEN1024], sname[NFILEN1024]; | |||
392 | int tmp; | |||
393 | ||||
394 | tmp = curwp->w_dotline; | |||
395 | curwp->w_dotline = 0; | |||
396 | ||||
397 | for (lp = bfirstlp(curbp)((((curbp)->b_headp)->l_fp)); lp != curbp->b_headp; lp = nlp) { | |||
398 | curwp->w_dotline++; | |||
399 | nlp = lforw(lp)((lp)->l_fp); | |||
400 | if (llength(lp)((lp)->l_used) && lgetc(lp, 0)(((unsigned char) ((lp)->l_text[(0)]))) == 'D') { | |||
401 | switch (d_makename(lp, fname, sizeof(fname))) { | |||
402 | case ABORT2: | |||
403 | dobeep(); | |||
404 | ewprintf("Bad line in dired buffer"); | |||
405 | curwp->w_dotline = tmp; | |||
406 | return (FALSE0); | |||
407 | case FALSE0: | |||
408 | if (unlink(fname) == -1) { | |||
409 | (void)xbasename(sname, fname, NFILEN1024); | |||
410 | dobeep(); | |||
411 | ewprintf("Could not delete '%s'", sname); | |||
412 | curwp->w_dotline = tmp; | |||
413 | return (FALSE0); | |||
414 | } | |||
415 | break; | |||
416 | case TRUE1: | |||
417 | if (rmdir(fname) == -1) { | |||
418 | (void)xbasename(sname, fname, NFILEN1024); | |||
419 | dobeep(); | |||
420 | ewprintf("Could not delete directory " | |||
421 | "'%s'", sname); | |||
422 | curwp->w_dotline = tmp; | |||
423 | return (FALSE0); | |||
424 | } | |||
425 | break; | |||
426 | } | |||
427 | lfree(lp); | |||
428 | curwp->w_bufp->b_lines--; | |||
429 | if (tmp > curwp->w_dotline) | |||
430 | tmp--; | |||
431 | curwp->w_rflag |= WFFULL0x08; | |||
432 | } | |||
433 | } | |||
434 | curwp->w_dotline = tmp; | |||
435 | d_warpdot(curwp->w_dotp, &curwp->w_doto); | |||
436 | ||||
437 | /* we have deleted all items successfully, remove del flag */ | |||
438 | curbp->b_flag &= ~BFDIREDDEL0x80; | |||
439 | ||||
440 | return (TRUE1); | |||
441 | } | |||
442 | ||||
443 | int | |||
444 | d_copy(int f, int n) | |||
445 | { | |||
446 | struct stat statbuf; | |||
447 | char frname[NFILEN1024], toname[NFILEN1024], sname[NFILEN1024]; | |||
448 | char *topath, *bufp; | |||
449 | int ret; | |||
450 | size_t off; | |||
451 | struct buffer *bp; | |||
452 | ||||
453 | if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE0) { | |||
454 | dobeep(); | |||
455 | ewprintf("Not a file"); | |||
456 | return (FALSE0); | |||
457 | } | |||
458 | off = strlcpy(toname, curbp->b_fname, sizeof(toname)); | |||
459 | if (off >= sizeof(toname) - 1) { /* can't happen, really */ | |||
460 | dobeep(); | |||
461 | ewprintf("Directory name too long"); | |||
462 | return (FALSE0); | |||
463 | } | |||
464 | (void)xbasename(sname, frname, NFILEN1024); | |||
465 | bufp = eread("Copy %s to: ", toname, sizeof(toname), | |||
466 | EFDEF0x0020 | EFNEW0x0008 | EFCR0x0010, sname); | |||
467 | if (bufp == NULL((void *)0)) | |||
468 | return (ABORT2); | |||
469 | else if (bufp[0] == '\0') | |||
470 | return (FALSE0); | |||
471 | ||||
472 | topath = adjustname(toname, TRUE1); | |||
473 | if (stat(topath, &statbuf) == 0) { | |||
474 | if (S_ISDIR(statbuf.st_mode)((statbuf.st_mode & 0170000) == 0040000)) { | |||
475 | ret = snprintf(toname, sizeof(toname), "%s/%s", | |||
476 | topath, sname); | |||
477 | if (ret < 0 || ret >= sizeof(toname) - 1) { | |||
478 | dobeep(); | |||
479 | ewprintf("Directory name too long"); | |||
480 | return (FALSE0); | |||
481 | } | |||
482 | topath = adjustname(toname, TRUE1); | |||
483 | } | |||
484 | } | |||
485 | if (topath == NULL((void *)0)) | |||
486 | return (FALSE0); | |||
487 | if (strcmp(frname, topath) == 0) { | |||
488 | ewprintf("Cannot copy to same file: %s", frname); | |||
489 | return (TRUE1); | |||
490 | } | |||
491 | ret = (copy(frname, topath) >= 0) ? TRUE1 : FALSE0; | |||
492 | if (ret != TRUE1) | |||
493 | return (ret); | |||
494 | if ((bp = refreshbuffer(curbp)) == NULL((void *)0)) | |||
495 | return (FALSE0); | |||
496 | ||||
497 | ewprintf("Copy: 1 file"); | |||
498 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
499 | } | |||
500 | ||||
501 | int | |||
502 | d_rename(int f, int n) | |||
503 | { | |||
504 | struct stat statbuf; | |||
505 | char frname[NFILEN1024], toname[NFILEN1024]; | |||
506 | char *topath, *bufp; | |||
507 | int ret; | |||
508 | size_t off; | |||
509 | struct buffer *bp; | |||
510 | char sname[NFILEN1024]; | |||
511 | ||||
512 | if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE0) { | |||
513 | dobeep(); | |||
514 | ewprintf("Not a file"); | |||
515 | return (FALSE0); | |||
516 | } | |||
517 | off = strlcpy(toname, curbp->b_fname, sizeof(toname)); | |||
518 | if (off >= sizeof(toname) - 1) { /* can't happen, really */ | |||
519 | dobeep(); | |||
520 | ewprintf("Name too long"); | |||
521 | return (FALSE0); | |||
522 | } | |||
523 | (void)xbasename(sname, frname, NFILEN1024); | |||
524 | bufp = eread("Rename %s to: ", toname, | |||
525 | sizeof(toname), EFDEF0x0020 | EFNEW0x0008 | EFCR0x0010, sname); | |||
526 | if (bufp == NULL((void *)0)) | |||
527 | return (ABORT2); | |||
528 | else if (bufp[0] == '\0') | |||
529 | return (FALSE0); | |||
530 | ||||
531 | topath = adjustname(toname, TRUE1); | |||
532 | if (stat(topath, &statbuf) == 0) { | |||
533 | if (S_ISDIR(statbuf.st_mode)((statbuf.st_mode & 0170000) == 0040000)) { | |||
534 | ret = snprintf(toname, sizeof(toname), "%s/%s", | |||
535 | topath, sname); | |||
536 | if (ret < 0 || ret >= sizeof(toname) - 1) { | |||
537 | dobeep(); | |||
538 | ewprintf("Directory name too long"); | |||
539 | return (FALSE0); | |||
540 | } | |||
541 | topath = adjustname(toname, TRUE1); | |||
542 | } | |||
543 | } | |||
544 | if (topath == NULL((void *)0)) | |||
545 | return (FALSE0); | |||
546 | if (strcmp(frname, topath) == 0) { | |||
547 | ewprintf("Cannot move to same file: %s", frname); | |||
548 | return (TRUE1); | |||
549 | } | |||
550 | ret = (rename(frname, topath) >= 0) ? TRUE1 : FALSE0; | |||
551 | if (ret != TRUE1) | |||
552 | return (ret); | |||
553 | if ((bp = refreshbuffer(curbp)) == NULL((void *)0)) | |||
554 | return (FALSE0); | |||
555 | ||||
556 | ewprintf("Move: 1 file"); | |||
557 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
558 | } | |||
559 | ||||
560 | void | |||
561 | reaper(int signo __attribute__((unused))) | |||
562 | { | |||
563 | int save_errno = errno(*__errno()), status; | |||
564 | ||||
565 | while (waitpid(-1, &status, WNOHANG0x01) >= 0) | |||
566 | ; | |||
567 | errno(*__errno()) = save_errno; | |||
568 | } | |||
569 | ||||
570 | /* | |||
571 | * Pipe the currently selected file through a shell command. | |||
572 | */ | |||
573 | int | |||
574 | d_shell_command(int f, int n) | |||
575 | { | |||
576 | char command[512], fname[PATH_MAX1024], *bufp; | |||
577 | struct buffer *bp; | |||
578 | struct mgwin *wp; | |||
579 | char sname[NFILEN1024]; | |||
580 | ||||
581 | bp = bfind("*Shell Command Output*", TRUE1); | |||
582 | if (bclear(bp) != TRUE1) | |||
583 | return (ABORT2); | |||
584 | ||||
585 | if (d_makename(curwp->w_dotp, fname, sizeof(fname)) != FALSE0) { | |||
586 | dobeep(); | |||
587 | ewprintf("bad line"); | |||
588 | return (ABORT2); | |||
589 | } | |||
590 | ||||
591 | command[0] = '\0'; | |||
592 | (void)xbasename(sname, fname, NFILEN1024); | |||
593 | bufp = eread("! on %s: ", command, sizeof(command), EFNEW0x0008, sname); | |||
594 | if (bufp == NULL((void *)0)) | |||
595 | return (ABORT2); | |||
596 | ||||
597 | if (d_exec(0, bp, fname, "sh", "-c", command, NULL((void *)0)) != TRUE1) | |||
598 | return (ABORT2); | |||
599 | ||||
600 | if ((wp = popbuf(bp, WNONE0x00)) == NULL((void *)0)) | |||
601 | return (ABORT2); /* XXX - free the buffer?? */ | |||
602 | curwp = wp; | |||
603 | curbp = wp->w_bufp; | |||
604 | return (TRUE1); | |||
605 | } | |||
606 | ||||
607 | /* | |||
608 | * Pipe input file to cmd and insert the command's output in the | |||
609 | * given buffer. Each line will be prefixed with the given | |||
610 | * number of spaces. | |||
611 | */ | |||
612 | static int | |||
613 | d_exec(int space, struct buffer *bp, const char *input, const char *cmd, ...) | |||
614 | { | |||
615 | char buf[BUFSIZ1024]; | |||
616 | va_list ap; | |||
617 | struct sigaction olda, newa; | |||
618 | char **argv = NULL((void *)0), *cp; | |||
619 | FILE *fin; | |||
620 | int fds[2] = { -1, -1 }; | |||
621 | int infd = -1; | |||
622 | int ret = (ABORT2), n; | |||
623 | pid_t pid; | |||
624 | ||||
625 | if (sigaction(SIGCHLD20, NULL((void *)0), &olda) == -1) | |||
626 | return (ABORT2); | |||
627 | ||||
628 | /* Find the number of arguments. */ | |||
629 | va_start(ap, cmd)__builtin_va_start((ap), cmd); | |||
630 | for (n = 2; va_arg(ap, char *)__builtin_va_arg((ap), char *) != NULL((void *)0); n++) | |||
631 | ; | |||
632 | va_end(ap)__builtin_va_end((ap)); | |||
633 | ||||
634 | /* Allocate and build the argv. */ | |||
635 | if ((argv = calloc(n, sizeof(*argv))) == NULL((void *)0)) { | |||
636 | dobeep(); | |||
637 | ewprintf("Can't allocate argv : %s", strerror(errno(*__errno()))); | |||
638 | goto out; | |||
639 | } | |||
640 | ||||
641 | n = 1; | |||
642 | argv[0] = (char *)cmd; | |||
643 | va_start(ap, cmd)__builtin_va_start((ap), cmd); | |||
644 | while ((argv[n] = va_arg(ap, char *)__builtin_va_arg((ap), char *)) != NULL((void *)0)) | |||
645 | n++; | |||
646 | va_end(ap)__builtin_va_end((ap)); | |||
647 | ||||
648 | if (input == NULL((void *)0)) | |||
649 | input = "/dev/null"; | |||
650 | ||||
651 | if ((infd = open(input, O_RDONLY0x0000)) == -1) { | |||
652 | dobeep(); | |||
653 | ewprintf("Can't open input file : %s", strerror(errno(*__errno()))); | |||
654 | goto out; | |||
655 | } | |||
656 | ||||
657 | if (pipe(fds) == -1) { | |||
658 | dobeep(); | |||
659 | ewprintf("Can't create pipe : %s", strerror(errno(*__errno()))); | |||
660 | goto out; | |||
661 | } | |||
662 | ||||
663 | newa.sa_handler__sigaction_u.__sa_handler = reaper; | |||
664 | newa.sa_flags = 0; | |||
665 | if (sigaction(SIGCHLD20, &newa, NULL((void *)0)) == -1) | |||
666 | goto out; | |||
667 | ||||
668 | if ((pid = fork()) == -1) { | |||
669 | dobeep(); | |||
670 | ewprintf("Can't fork"); | |||
671 | goto out; | |||
672 | } | |||
673 | ||||
674 | switch (pid) { | |||
675 | case 0: /* Child */ | |||
676 | close(fds[0]); | |||
677 | dup2(infd, STDIN_FILENO0); | |||
678 | dup2(fds[1], STDOUT_FILENO1); | |||
679 | dup2(fds[1], STDERR_FILENO2); | |||
680 | if (execvp(argv[0], argv) == -1) | |||
681 | ewprintf("Can't exec %s: %s", argv[0], strerror(errno(*__errno()))); | |||
682 | exit(1); | |||
683 | break; | |||
684 | default: /* Parent */ | |||
685 | close(infd); | |||
686 | close(fds[1]); | |||
687 | infd = fds[1] = -1; | |||
688 | if ((fin = fdopen(fds[0], "r")) == NULL((void *)0)) | |||
689 | goto out; | |||
690 | while (fgets(buf, sizeof(buf), fin) != NULL((void *)0)) { | |||
691 | cp = strrchr(buf, *bp->b_nlchr); | |||
692 | if (cp == NULL((void *)0) && !feof(fin)(!__isthreaded ? (((fin)->_flags & 0x0020) != 0) : (feof )(fin))) { /* too long a line */ | |||
693 | int c; | |||
694 | addlinef(bp, "%*s%s...", space, "", buf); | |||
695 | while ((c = getc(fin)(!__isthreaded ? (--(fin)->_r < 0 ? __srget(fin) : (int )(*(fin)->_p++)) : (getc)(fin))) != EOF(-1) && | |||
696 | c != *bp->b_nlchr) | |||
697 | ; | |||
698 | continue; | |||
699 | } else if (cp) | |||
700 | *cp = '\0'; | |||
701 | addlinef(bp, "%*s%s", space, "", buf); | |||
702 | } | |||
703 | fclose(fin); | |||
704 | break; | |||
705 | } | |||
706 | ret = (TRUE1); | |||
707 | ||||
708 | out: | |||
709 | if (sigaction(SIGCHLD20, &olda, NULL((void *)0)) == -1) | |||
710 | ewprintf("Warning, couldn't reset previous signal handler"); | |||
711 | if (fds[0] != -1) | |||
712 | close(fds[0]); | |||
713 | if (fds[1] != -1) | |||
714 | close(fds[1]); | |||
715 | if (infd != -1) | |||
716 | close(infd); | |||
717 | free(argv); | |||
718 | return ret; | |||
719 | } | |||
720 | ||||
721 | int | |||
722 | d_create_directory(int f, int n) | |||
723 | { | |||
724 | int ret; | |||
725 | struct buffer *bp; | |||
726 | ||||
727 | ret = ask_makedir(); | |||
728 | if (ret != TRUE1) | |||
729 | return(ret); | |||
730 | ||||
731 | if ((bp = refreshbuffer(curbp)) == NULL((void *)0)) | |||
732 | return (FALSE0); | |||
733 | ||||
734 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
735 | } | |||
736 | ||||
737 | int | |||
738 | d_killbuffer_cmd(int f, int n) | |||
739 | { | |||
740 | return(killbuffer_cmd(FFRAND8, 0)); | |||
741 | } | |||
742 | ||||
743 | int | |||
744 | d_refreshbuffer(int f, int n) | |||
745 | { | |||
746 | struct buffer *bp; | |||
747 | ||||
748 | if ((bp = refreshbuffer(curbp)) == NULL((void *)0)) | |||
| ||||
749 | return (FALSE0); | |||
750 | ||||
751 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
752 | } | |||
753 | ||||
754 | /* | |||
755 | * Kill then re-open the requested dired buffer. | |||
756 | * If required, take a note of any files marked for deletion. Then once | |||
757 | * the buffer has been re-opened, remark the same files as deleted. | |||
758 | */ | |||
759 | struct buffer * | |||
760 | refreshbuffer(struct buffer *bp) | |||
761 | { | |||
762 | char *tmp_b_fname; | |||
763 | int i, tmp_w_dotline, ddel = 0; | |||
764 | ||||
765 | /* remember directory path to open later */ | |||
766 | tmp_b_fname = strdup(bp->b_fname); | |||
767 | if (tmp_b_fname == NULL((void *)0)) { | |||
768 | dobeep(); | |||
769 | ewprintf("Out of memory"); | |||
770 | return (NULL((void *)0)); | |||
771 | } | |||
772 | tmp_w_dotline = curwp->w_dotline; | |||
773 | ||||
774 | /* create a list of files for deletion */ | |||
775 | if (bp->b_flag & BFDIREDDEL0x80) | |||
776 | ddel = createlist(bp); | |||
777 | ||||
778 | killbuffer(bp); | |||
779 | ||||
780 | /* dired_() uses findbuffer() to create new buffer */ | |||
781 | if ((bp = dired_(tmp_b_fname)) == NULL((void *)0)) { | |||
782 | free(tmp_b_fname); | |||
783 | return (NULL((void *)0)); | |||
784 | } | |||
785 | free(tmp_b_fname); | |||
786 | ||||
787 | /* remark any previously deleted files with a 'D' */ | |||
788 | if (ddel) | |||
789 | redelete(bp); | |||
790 | ||||
791 | /* find dot line */ | |||
792 | bp->b_dotp = bfirstlp(bp)((((bp)->b_headp)->l_fp)); | |||
793 | if (tmp_w_dotline > bp->b_lines) | |||
794 | tmp_w_dotline = bp->b_lines - 1; | |||
795 | for (i = 1; i < tmp_w_dotline; i++) | |||
796 | bp->b_dotp = lforw(bp->b_dotp)((bp->b_dotp)->l_fp); | |||
797 | ||||
798 | bp->b_dotline = i; | |||
799 | bp->b_doto = 0; | |||
800 | d_warpdot(bp->b_dotp, &bp->b_doto); | |||
801 | ||||
802 | curbp = bp; | |||
803 | ||||
804 | return (bp); | |||
805 | } | |||
806 | ||||
807 | static int | |||
808 | d_makename(struct line *lp, char *fn, size_t len) | |||
809 | { | |||
810 | int start, nlen, ret; | |||
811 | char *namep; | |||
812 | ||||
813 | if (d_warpdot(lp, &start) == FALSE0) | |||
814 | return (ABORT2); | |||
815 | namep = &lp->l_text[start]; | |||
816 | nlen = llength(lp)((lp)->l_used) - start; | |||
817 | ||||
818 | ret = snprintf(fn, len, "%s%.*s", curbp->b_fname, nlen, namep); | |||
819 | if (ret < 0 || ret >= (int)len) | |||
820 | return (ABORT2); /* Name is too long. */ | |||
821 | ||||
822 | /* Return TRUE if the entry is a directory. */ | |||
823 | return ((lgetc(lp, 2)(((unsigned char) ((lp)->l_text[(2)]))) == 'd') ? TRUE1 : FALSE0); | |||
824 | } | |||
825 | ||||
826 | #define NAME_FIELD9 9 | |||
827 | ||||
828 | static int | |||
829 | d_warpdot(struct line *dotp, int *doto) | |||
830 | { | |||
831 | char *tp = dotp->l_text; | |||
832 | int off = 0, field = 0, len; | |||
833 | ||||
834 | /* | |||
835 | * Find the byte offset to the (space-delimited) filename | |||
836 | * field in formatted ls output. | |||
837 | */ | |||
838 | len = llength(dotp)((dotp)->l_used); | |||
839 | while (off < len) { | |||
840 | if (tp[off++] == ' ') { | |||
841 | if (++field == NAME_FIELD9) { | |||
842 | *doto = off; | |||
843 | return (TRUE1); | |||
844 | } | |||
845 | /* Skip the space. */ | |||
846 | while (off < len && tp[off] == ' ') | |||
847 | off++; | |||
848 | } | |||
849 | } | |||
850 | /* We didn't find the field. */ | |||
851 | *doto = 0; | |||
852 | return (FALSE0); | |||
853 | } | |||
854 | ||||
855 | static int | |||
856 | d_forwpage(int f, int n) | |||
857 | { | |||
858 | forwpage(f | FFRAND8, n); | |||
859 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
860 | } | |||
861 | ||||
862 | static int | |||
863 | d_backpage (int f, int n) | |||
864 | { | |||
865 | backpage(f | FFRAND8, n); | |||
866 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
867 | } | |||
868 | ||||
869 | static int | |||
870 | d_forwline (int f, int n) | |||
871 | { | |||
872 | forwline(f | FFRAND8, n); | |||
873 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
874 | } | |||
875 | ||||
876 | static int | |||
877 | d_backline (int f, int n) | |||
878 | { | |||
879 | backline(f | FFRAND8, n); | |||
880 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
881 | } | |||
882 | ||||
883 | int | |||
884 | d_filevisitalt (int f, int n) | |||
885 | { | |||
886 | char fname[NFILEN1024]; | |||
887 | ||||
888 | if (d_makename(curwp->w_dotp, fname, sizeof(fname)) == ABORT2) | |||
889 | return (FALSE0); | |||
890 | ||||
891 | return(do_filevisitalt(fname)); | |||
892 | } | |||
893 | ||||
894 | /* | |||
895 | * XXX dname needs to have enough place to store an additional '/'. | |||
896 | */ | |||
897 | struct buffer * | |||
898 | dired_(char *dname) | |||
899 | { | |||
900 | struct buffer *bp; | |||
901 | int i; | |||
902 | size_t len; | |||
903 | ||||
904 | if ((dname = adjustname(dname, TRUE1)) == NULL((void *)0)) { | |||
905 | dobeep(); | |||
906 | ewprintf("Bad directory name"); | |||
907 | return (NULL((void *)0)); | |||
908 | } | |||
909 | /* this should not be done, instead adjustname() should get a flag */ | |||
910 | len = strlen(dname); | |||
911 | if (dname[len - 1] != '/') { | |||
912 | dname[len++] = '/'; | |||
913 | dname[len] = '\0'; | |||
914 | } | |||
915 | if ((access(dname, R_OK0x04 | X_OK0x01)) == -1) { | |||
916 | if (errno(*__errno()) == EACCES13) { | |||
917 | dobeep(); | |||
918 | ewprintf("Permission denied: %s", dname); | |||
919 | } else { | |||
920 | dobeep(); | |||
921 | ewprintf("Error opening: %s", dname); | |||
922 | } | |||
923 | return (NULL((void *)0)); | |||
924 | } | |||
925 | for (bp = bheadp; bp != NULL((void *)0); bp = bp->b_bufpb_list.l_p.x_bp) { | |||
926 | if (strcmp(bp->b_fname, dname) == 0) { | |||
927 | if (fchecktime(bp) != TRUE1) | |||
928 | ewprintf("Directory has changed on disk;" | |||
929 | " type g to update Dired"); | |||
930 | return (bp); | |||
931 | } | |||
932 | ||||
933 | } | |||
934 | bp = bfind(dname, TRUE1); | |||
935 | bp->b_flag |= BFREADONLY0x10 | BFIGNDIRTY0x40; | |||
936 | ||||
937 | if ((d_exec(2, bp, NULL((void *)0), "ls", "-al", dname, NULL((void *)0))) != TRUE1) | |||
938 | return (NULL((void *)0)); | |||
939 | ||||
940 | /* Find the line with ".." on it. */ | |||
941 | bp->b_dotp = bfirstlp(bp)((((bp)->b_headp)->l_fp)); | |||
942 | bp->b_dotline = 1; | |||
943 | for (i = 0; i < bp->b_lines; i++) { | |||
944 | bp->b_dotp = lforw(bp->b_dotp)((bp->b_dotp)->l_fp); | |||
945 | bp->b_dotline++; | |||
946 | if (d_warpdot(bp->b_dotp, &bp->b_doto) == FALSE0) | |||
947 | continue; | |||
948 | if (strcmp(ltext(bp->b_dotp)((bp->b_dotp)->l_text) + bp->b_doto, "..") == 0) | |||
949 | break; | |||
950 | } | |||
951 | ||||
952 | /* We want dot on the entry right after "..", if possible. */ | |||
953 | if (++i < bp->b_lines - 2) { | |||
954 | bp->b_dotp = lforw(bp->b_dotp)((bp->b_dotp)->l_fp); | |||
955 | bp->b_dotline++; | |||
956 | } | |||
957 | d_warpdot(bp->b_dotp, &bp->b_doto); | |||
958 | ||||
959 | (void)strlcpy(bp->b_fname, dname, sizeof(bp->b_fname)); | |||
960 | (void)strlcpy(bp->b_cwd, dname, sizeof(bp->b_cwd)); | |||
961 | if ((bp->b_modes[1] = name_mode("dired")) == NULL((void *)0)) { | |||
962 | bp->b_modes[0] = name_mode("fundamental"); | |||
963 | dobeep(); | |||
964 | ewprintf("Could not find mode dired"); | |||
965 | return (NULL((void *)0)); | |||
966 | } | |||
967 | (void)fupdstat(bp); | |||
968 | bp->b_nmodes = 1; | |||
969 | return (bp); | |||
970 | } | |||
971 | ||||
972 | /* | |||
973 | * Iterate through the lines of the dired buffer looking for files | |||
974 | * collected in the linked list made in createlist(). If a line is found | |||
975 | * replace 'D' as first char in a line. As lines are found, remove the | |||
976 | * corresponding item from the linked list. Iterate for as long as there | |||
977 | * are items in the linked list or until end of buffer is found. | |||
978 | */ | |||
979 | void | |||
980 | redelete(struct buffer *bp) | |||
981 | { | |||
982 | struct delentry *dt, *d1 = NULL((void *)0); | |||
983 | struct line *lp, *nlp; | |||
984 | char fname[NFILEN1024]; | |||
985 | char *p = fname; | |||
986 | size_t plen, fnlen; | |||
987 | int finished = 0; | |||
988 | ||||
989 | /* reset the deleted file buffer flag until a deleted file is found */ | |||
990 | bp->b_flag &= ~BFDIREDDEL0x80; | |||
991 | ||||
992 | for (lp = bfirstlp(bp)((((bp)->b_headp)->l_fp)); lp != bp->b_headp; lp = nlp) { | |||
993 | bp->b_dotp = lp; | |||
994 | if ((p = findfname(lp, p)) == NULL((void *)0)) { | |||
995 | nlp = lforw(lp)((lp)->l_fp); | |||
996 | continue; | |||
997 | } | |||
998 | plen = strlen(p); | |||
999 | SLIST_FOREACH_SAFE(d1, &delhead, entry, dt)for ((d1) = ((&delhead)->slh_first); (d1) && ( (dt) = ((d1)->entry.sle_next), 1); (d1) = (dt)) { | |||
1000 | fnlen = strlen(d1->fn); | |||
1001 | if ((plen == fnlen) && | |||
1002 | (strncmp(p, d1->fn, plen) == 0)) { | |||
1003 | lputc(bp->b_dotp, 0, DDELCHAR)((bp->b_dotp)->l_text[(0)]=(DDELCHAR)); | |||
1004 | bp->b_flag |= BFDIREDDEL0x80; | |||
1005 | 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); | |||
1006 | if (SLIST_EMPTY(&delhead)(((&delhead)->slh_first) == ((void *)0))) { | |||
1007 | finished = 1; | |||
1008 | break; | |||
1009 | } | |||
1010 | } | |||
1011 | } | |||
1012 | if (finished) | |||
1013 | break; | |||
1014 | nlp = lforw(lp)((lp)->l_fp); | |||
1015 | } | |||
1016 | while (!SLIST_EMPTY(&delhead)(((&delhead)->slh_first) == ((void *)0))) { | |||
1017 | d1 = SLIST_FIRST(&delhead)((&delhead)->slh_first); | |||
1018 | SLIST_REMOVE_HEAD(&delhead, entry)do { (&delhead)->slh_first = (&delhead)->slh_first ->entry.sle_next; } while (0); | |||
1019 | free(d1->fn); | |||
1020 | free(d1); | |||
1021 | } | |||
1022 | return; | |||
1023 | } | |||
1024 | ||||
1025 | /* | |||
1026 | * Create a list of files marked for deletion. | |||
1027 | */ | |||
1028 | int | |||
1029 | createlist(struct buffer *bp) | |||
1030 | { | |||
1031 | struct delentry *d1 = NULL((void *)0), *d2; | |||
1032 | struct line *lp, *nlp; | |||
1033 | char fname[NFILEN1024]; | |||
1034 | char *p = fname; | |||
1035 | int ret = FALSE0; | |||
1036 | ||||
1037 | for (lp = bfirstlp(bp)((((bp)->b_headp)->l_fp)); lp != bp->b_headp; lp = nlp) { | |||
1038 | /* | |||
1039 | * Check if the line has 'D' on the first char and if a valid | |||
1040 | * filename can be extracted from it. | |||
1041 | */ | |||
1042 | if (((lp->l_text[0] != DDELCHAR)) || | |||
1043 | ((p = findfname(lp, p)) == NULL((void *)0))) { | |||
1044 | nlp = lforw(lp)((lp)->l_fp); | |||
1045 | continue; | |||
1046 | } | |||
1047 | if (SLIST_EMPTY(&delhead)(((&delhead)->slh_first) == ((void *)0))) { | |||
1048 | if ((d1 = malloc(sizeof(struct delentry))) | |||
1049 | == NULL((void *)0)) | |||
1050 | return (ABORT2); | |||
1051 | if ((d1->fn = strdup(p)) == NULL((void *)0)) { | |||
1052 | free(d1); | |||
1053 | return (ABORT2); | |||
1054 | } | |||
1055 | SLIST_INSERT_HEAD(&delhead, d1, entry)do { (d1)->entry.sle_next = (&delhead)->slh_first; ( &delhead)->slh_first = (d1); } while (0); | |||
1056 | } else { | |||
1057 | if ((d2 = malloc(sizeof(struct delentry))) | |||
1058 | == NULL((void *)0)) { | |||
1059 | free(d1->fn); | |||
| ||||
1060 | free(d1); | |||
1061 | return (ABORT2); | |||
1062 | } | |||
1063 | if ((d2->fn = strdup(p)) == NULL((void *)0)) { | |||
1064 | free(d1->fn); | |||
1065 | free(d1); | |||
1066 | free(d2); | |||
1067 | return (ABORT2); | |||
1068 | } | |||
1069 | if (!d1) | |||
1070 | SLIST_INSERT_HEAD(&delhead, d2, entry)do { (d2)->entry.sle_next = (&delhead)->slh_first; ( &delhead)->slh_first = (d2); } while (0); | |||
1071 | else | |||
1072 | SLIST_INSERT_AFTER(d1, d2, entry)do { (d2)->entry.sle_next = (d1)->entry.sle_next; (d1)-> entry.sle_next = (d2); } while (0); | |||
1073 | d1 = d2; | |||
1074 | } | |||
1075 | ret = TRUE1; | |||
1076 | nlp = lforw(lp)((lp)->l_fp); | |||
1077 | } | |||
1078 | return (ret); | |||
1079 | } | |||
1080 | ||||
1081 | int | |||
1082 | dired_jump(int f, int n) | |||
1083 | { | |||
1084 | struct buffer *bp; | |||
1085 | const char *modename; | |||
1086 | char dname[NFILEN1024], *fname; | |||
1087 | int ret, i; | |||
1088 | ||||
1089 | /* | |||
1090 | * We use fundamental mode in dired, so just check we aren't in | |||
1091 | * dired mode for this specific function. Seems like a corner | |||
1092 | * case at the moment. | |||
1093 | */ | |||
1094 | for (i = 0; i <= curbp->b_nmodes; i++) { | |||
1095 | modename = curbp->b_modes[i]->p_name; | |||
1096 | if (strncmp(modename, "dired", 5) == 0) | |||
1097 | return (dobeep_msg("In dired mode already")); | |||
1098 | } | |||
1099 | ||||
1100 | if (getbufcwd(dname, sizeof(dname)) != TRUE1) | |||
1101 | return (FALSE0); | |||
1102 | ||||
1103 | fname = curbp->b_fname; | |||
1104 | ||||
1105 | if ((bp = dired_(dname)) == NULL((void *)0)) | |||
1106 | return (FALSE0); | |||
1107 | curbp = bp; | |||
1108 | ||||
1109 | ret = showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10); | |||
1110 | if (ret != TRUE1) | |||
1111 | return ret; | |||
1112 | ||||
1113 | fname = adjustname(fname, TRUE1); | |||
1114 | if (fname != NULL((void *)0)) | |||
1115 | gotofile(fname); | |||
1116 | ||||
1117 | return (TRUE1); | |||
1118 | } | |||
1119 | ||||
1120 | int | |||
1121 | d_gotofile(int f, int n) | |||
1122 | { | |||
1123 | size_t lenfpath; | |||
1124 | char fpath[NFILEN1024]; | |||
1125 | char *fpth, *fnp = NULL((void *)0); | |||
1126 | ||||
1127 | if (getbufcwd(fpath, sizeof(fpath)) != TRUE1) | |||
1128 | fpath[0] = '\0'; | |||
1129 | lenfpath = strlen(fpath); | |||
1130 | fnp = eread("Goto file: ", fpath, NFILEN1024, | |||
1131 | EFNEW0x0008 | EFCR0x0010 | EFFILE0x0004 | EFDEF0x0020); | |||
1132 | if (fnp == NULL((void *)0)) | |||
1133 | return (ABORT2); | |||
1134 | else if (fnp[0] == '\0') | |||
1135 | return (FALSE0); | |||
1136 | ||||
1137 | fpth = adjustname(fpath, TRUE1); /* Removes last '/' if dir... */ | |||
1138 | if (fpth == NULL((void *)0) || strlen(fpth) == lenfpath - 1) { /* ...hence -1. */ | |||
1139 | ewprintf("No file to find"); /* Current directory given so */ | |||
1140 | return (TRUE1); /* return at present location. */ | |||
1141 | } | |||
1142 | return gotofile(fpth); | |||
1143 | } | |||
1144 | ||||
1145 | int | |||
1146 | gotofile(char *fpth) | |||
1147 | { | |||
1148 | struct line *lp, *nlp; | |||
1149 | char fname[NFILEN1024]; | |||
1150 | char *p; | |||
1151 | int tmp; | |||
1152 | ||||
1153 | (void)xbasename(fname, fpth, NFILEN1024); | |||
1154 | tmp = 0; | |||
1155 | for (lp = bfirstlp(curbp)((((curbp)->b_headp)->l_fp)); lp != curbp->b_headp; lp = nlp) { | |||
1156 | tmp++; | |||
1157 | if ((p = findfname(lp, p)) == NULL((void *)0)) { | |||
1158 | nlp = lforw(lp)((lp)->l_fp); | |||
1159 | continue; | |||
1160 | } | |||
1161 | if (strcmp(fname, p) == 0) { | |||
1162 | curwp->w_dotp = lp; | |||
1163 | curwp->w_dotline = tmp; | |||
1164 | (void)d_warpdot(curwp->w_dotp, &curwp->w_doto); | |||
1165 | tmp--; | |||
1166 | break; | |||
1167 | } | |||
1168 | nlp = lforw(lp)((lp)->l_fp); | |||
1169 | } | |||
1170 | if (tmp == curbp->b_lines - 1) { | |||
1171 | ewprintf("File not found %s", fname); | |||
1172 | return (FALSE0); | |||
1173 | } else { | |||
1174 | eerase(); | |||
1175 | return (TRUE1); | |||
1176 | } | |||
1177 | } | |||
1178 | ||||
1179 | /* | |||
1180 | * Look for and extract a file name on a dired buffer line. | |||
1181 | */ | |||
1182 | char * | |||
1183 | findfname(struct line *lp, char *fn) | |||
1184 | { | |||
1185 | int start; | |||
1186 | ||||
1187 | (void)d_warpdot(lp, &start); | |||
1188 | if (start < 1) | |||
1189 | return NULL((void *)0); | |||
1190 | fn = &lp->l_text[start]; | |||
1191 | return fn; | |||
1192 | } |