Bug Summary

File:src/usr.bin/mg/dired.c
Warning:line 1171, column 12
2nd function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name dired.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -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/lib/clang/13.0.0 -D REGEX -internal-isystem /usr/local/lib/clang/13.0.0/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 -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/mg/dired.c
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
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
231/* ARGSUSED */
232int
233dired(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 */
261int
262d_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 */
293int
294d_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 */
313int
314d_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 */
331int
332d_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 */
349int
350d_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 */
373int
374d_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 */
395int
396d_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 */
452int
453d_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 */
511int
512d_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 */
571void
572reaper(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 */
585int
586d_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 */
624static int
625d_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
720out:
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 */
734int
735d_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 */
751int
752d_killbuffer_cmd(int f, int n)
753{
754 return(killbuffer_cmd(FFRAND8, 0));
755}
756
757int
758d_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 */
773struct buffer *
774refreshbuffer(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
821static int
822d_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
842static int
843d_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
869static int
870d_forwpage(int f, int n)
871{
872 forwpage(f | FFRAND8, n);
873 return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
874}
875
876static int
877d_backpage (int f, int n)
878{
879 backpage(f | FFRAND8, n);
880 return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
881}
882
883static int
884d_forwline (int f, int n)
885{
886 forwline(f | FFRAND8, n);
887 return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
888}
889
890static int
891d_backline (int f, int n)
892{
893 backline(f | FFRAND8, n);
894 return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
895}
896
897int
898d_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 */
911struct buffer *
912dired_(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 */
993void
994redelete(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 */
1042int
1043createlist(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
1095int
1096dired_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
1134int
1135d_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)
1
Assuming the condition is false
2
Taking false branch
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))
3
Assuming 'fnp' is not equal to NULL
4
Taking false branch
1147 return (ABORT2);
1148 else if (fnp[0] == '\0')
5
Assuming the condition is false
6
Taking false branch
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. */
7
Assuming 'fpth' is not equal to NULL
8
Assuming the condition is false
9
Taking false branch
1153 ewprintf("No file to find"); /* Current directory given so */
1154 return (TRUE1); /* return at present location. */
1155 }
1156 return gotofile(fpth);
10
Calling 'gotofile'
1157}
1158
1159int
1160gotofile(char *fpth)
1161{
1162 struct line *lp, *nlp;
1163 char fname[NFILEN1024];
1164 char *p;
11
'p' declared without an initial value
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) {
12
Assuming 'lp' is not equal to field 'b_headp'
13
Loop condition is true. Entering loop body
1170 tmp++;
1171 if ((p = findfname(lp, p)) == NULL((void *)0)) {
14
2nd function call argument is an uninitialized value
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 */
1196char *
1197findfname(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}