Bug Summary

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')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name dired.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/mg/obj -resource-dir /usr/local/llvm16/lib/clang/16 -D REGEX -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/mg/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.bin/mg/dired.c
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
31void dired_init(void);
32static int dired(int, int);
33static int d_otherwindow(int, int);
34static int d_undel(int, int);
35static int d_undelbak(int, int);
36static int d_findfile(int, int);
37static int d_ffotherwindow(int, int);
38static int d_expunge(int, int);
39static int d_copy(int, int);
40static int d_del(int, int);
41static int d_rename(int, int);
42static int d_exec(int, struct buffer *, const char *, const char *, ...);
43static int d_shell_command(int, int);
44static int d_create_directory(int, int);
45static int d_makename(struct line *, char *, size_t);
46static int d_warpdot(struct line *, int *);
47static int d_forwpage(int, int);
48static int d_backpage(int, int);
49static int d_forwline(int, int);
50static int d_backline(int, int);
51static int d_killbuffer_cmd(int, int);
52static int d_refreshbuffer(int, int);
53static int d_filevisitalt(int, int);
54static int d_gotofile(int, int);
55static void reaper(int);
56static int gotofile(char*);
57static struct buffer *refreshbuffer(struct buffer *);
58static int createlist(struct buffer *);
59static void redelete(struct buffer *);
60static char *findfname(struct line *, char *);
61
62extern struct keymap_s helpmap, cXmap, metamap;
63
64const 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 */
70struct delentry {
71 SLIST_ENTRY(delentry)struct { struct delentry *sle_next; } entry;
72 char *fn;
73};
74SLIST_HEAD(slisthead, delentry)struct slisthead { struct delentry *slh_first; } delhead = SLIST_HEAD_INITIALIZER(delhead){ ((void *)0) };
75
76static 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
88static 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
104static 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
125static 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
138static 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
152static PF direddl[] = {
153 d_undelbak /* del */
154};
155
156static PF diredbp[] = {
157 d_backpage /* v */
158};
159
160static PF dirednull[] = {
161 NULL((void *)0)
162};
163
164static 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
175static 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
205void
206dired_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
231int
232dired(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
259int
260d_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
290int
291d_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
309int
310d_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
326int
327d_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
343int
344d_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
366int
367d_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
387int
388d_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
443int
444d_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
501int
502d_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
560void
561reaper(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 */
573int
574d_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 */
612static int
613d_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
708out:
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
721int
722d_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
737int
738d_killbuffer_cmd(int f, int n)
739{
740 return(killbuffer_cmd(FFRAND8, 0));
741}
742
743int
744d_refreshbuffer(int f, int n)
745{
746 struct buffer *bp;
747
748 if ((bp = refreshbuffer(curbp)) == NULL((void *)0))
1
Calling 'refreshbuffer'
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 */
759struct buffer *
760refreshbuffer(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)) {
2
Assuming 'tmp_b_fname' is not equal to NULL
3
Taking false branch
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)
4
Assuming the condition is true
5
Taking true branch
776 ddel = createlist(bp);
6
Calling 'createlist'
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
807static int
808d_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
828static int
829d_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
855static int
856d_forwpage(int f, int n)
857{
858 forwpage(f | FFRAND8, n);
859 return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
860}
861
862static int
863d_backpage (int f, int n)
864{
865 backpage(f | FFRAND8, n);
866 return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
867}
868
869static int
870d_forwline (int f, int n)
871{
872 forwline(f | FFRAND8, n);
873 return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
874}
875
876static int
877d_backline (int f, int n)
878{
879 backline(f | FFRAND8, n);
880 return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
881}
882
883int
884d_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 */
897struct buffer *
898dired_(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 */
979void
980redelete(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 */
1028int
1029createlist(struct buffer *bp)
1030{
1031 struct delentry *d1 = NULL((void *)0), *d2;
7
'd1' initialized to a null pointer value
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) {
8
Assuming 'lp' is not equal to field 'b_headp'
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)) ||
9
Assuming the condition is false
11
Taking false branch
1043 ((p = findfname(lp, p)) == NULL((void *)0))) {
10
Assuming the condition is false
1044 nlp = lforw(lp)((lp)->l_fp);
1045 continue;
1046 }
1047 if (SLIST_EMPTY(&delhead)(((&delhead)->slh_first) == ((void *)0))) {
12
Assuming field 'slh_first' is not equal to null
13
Taking false branch
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)))
14
Assuming the condition is true
15
Taking true branch
1058 == NULL((void *)0)) {
1059 free(d1->fn);
16
Access to field 'fn' results in a dereference of a null pointer (loaded from variable 'd1')
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
1081int
1082dired_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
1120int
1121d_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
1145int
1146gotofile(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 */
1182char *
1183findfname(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}