Annotation of src/usr.bin/mg/dired.c, Revision 1.54
1.54 ! lum 1: /* $OpenBSD: dired.c,v 1.53 2013/05/27 18:24:44 lum Exp $ */
1.6 niklas 2:
1.20 kjell 3: /* This file is in the public domain. */
4:
5: /* dired module for mg 2a
6: * by Robert A. Larson
7: */
1.1 deraadt 8:
9: #include "def.h"
1.28 kjell 10: #include "funmap.h"
1.9 vincent 11: #include "kbd.h"
1.27 kjell 12:
1.12 vincent 13: #include <sys/types.h>
14: #include <sys/stat.h>
1.25 deraadt 15: #include <sys/time.h>
16: #include <sys/resource.h>
1.12 vincent 17: #include <sys/wait.h>
18:
1.24 kjell 19: #include <ctype.h>
1.12 vincent 20: #include <signal.h>
21: #include <fcntl.h>
1.54 ! lum 22: #include <err.h>
1.12 vincent 23: #include <errno.h>
24: #include <libgen.h>
1.50 lum 25: #include <stdarg.h>
1.1 deraadt 26:
1.24 kjell 27: void dired_init(void);
1.27 kjell 28: static int dired(int, int);
29: static int d_otherwindow(int, int);
30: static int d_undel(int, int);
31: static int d_undelbak(int, int);
32: static int d_findfile(int, int);
33: static int d_ffotherwindow(int, int);
34: static int d_expunge(int, int);
35: static int d_copy(int, int);
36: static int d_del(int, int);
37: static int d_rename(int, int);
1.50 lum 38: static int d_exec(int, struct buffer *, const char *, const char *, ...);
1.27 kjell 39: static int d_shell_command(int, int);
40: static int d_create_directory(int, int);
1.34 kjell 41: static int d_makename(struct line *, char *, size_t);
1.49 lum 42: static int d_warpdot(struct line *, int *);
43: static int d_forwpage(int, int);
44: static int d_backpage(int, int);
45: static int d_forwline(int, int);
46: static int d_backline(int, int);
1.47 lum 47: static void reaper(int);
1.54 ! lum 48: static struct buffer *refreshbuffer(struct buffer *);
1.1 deraadt 49:
1.23 kjell 50: extern struct keymap_s helpmap, cXmap, metamap;
51:
52: static PF dirednul[] = {
53: setmark, /* ^@ */
54: gotobol, /* ^A */
55: backchar, /* ^B */
56: rescan, /* ^C */
57: d_del, /* ^D */
58: gotoeol, /* ^E */
59: forwchar, /* ^F */
60: ctrlg, /* ^G */
61: NULL, /* ^H */
1.12 vincent 62: };
63:
1.23 kjell 64: static PF diredcl[] = {
65: reposition, /* ^L */
1.15 db 66: d_findfile, /* ^M */
1.49 lum 67: d_forwline, /* ^N */
1.23 kjell 68: rescan, /* ^O */
1.49 lum 69: d_backline, /* ^P */
1.23 kjell 70: rescan, /* ^Q */
71: backisearch, /* ^R */
72: forwisearch, /* ^S */
73: rescan, /* ^T */
74: universal_argument, /* ^U */
1.49 lum 75: d_forwpage, /* ^V */
1.23 kjell 76: rescan, /* ^W */
77: NULL /* ^X */
78: };
79:
80: static PF diredcz[] = {
81: spawncli, /* ^Z */
82: NULL, /* esc */
83: rescan, /* ^\ */
84: rescan, /* ^] */
85: rescan, /* ^^ */
86: rescan, /* ^_ */
1.49 lum 87: d_forwline, /* SP */
1.27 kjell 88: d_shell_command, /* ! */
89: rescan, /* " */
90: rescan, /* # */
91: rescan, /* $ */
92: rescan, /* % */
93: rescan, /* & */
94: rescan, /* ' */
95: rescan, /* ( */
96: rescan, /* ) */
97: rescan, /* * */
98: d_create_directory /* + */
1.23 kjell 99: };
100:
101: static PF diredc[] = {
102: d_copy, /* c */
103: d_del, /* d */
104: d_findfile, /* e */
105: d_findfile /* f */
106: };
107:
108: static PF diredn[] = {
1.49 lum 109: d_forwline, /* n */
1.23 kjell 110: d_ffotherwindow, /* o */
1.49 lum 111: d_backline, /* p */
1.23 kjell 112: rescan, /* q */
113: d_rename, /* r */
114: rescan, /* s */
115: rescan, /* t */
116: d_undel, /* u */
117: rescan, /* v */
118: rescan, /* w */
119: d_expunge /* x */
120: };
121:
122: static PF direddl[] = {
123: d_undelbak /* del */
1.9 vincent 124: };
1.13 deraadt 125:
1.49 lum 126: static PF diredbp[] = {
127: d_backpage /* v */
128: };
129:
130: static PF dirednull[] = {
131: NULL
132: };
133:
1.23 kjell 134: #ifndef DIRED_XMAPS
135: #define NDIRED_XMAPS 0 /* number of extra map sections */
136: #endif /* DIRED_XMAPS */
137:
1.49 lum 138: static struct KEYMAPE (1 + IMAPEXT) d_backpagemap = {
139: 1,
140: 1 + IMAPEXT,
141: rescan,
142: {
143: {
144: 'v', 'v', diredbp, NULL
145: }
146: }
147: };
148:
149: static struct KEYMAPE (7 + NDIRED_XMAPS + IMAPEXT) diredmap = {
150: 7 + NDIRED_XMAPS,
151: 7 + NDIRED_XMAPS + IMAPEXT,
1.9 vincent 152: rescan,
153: {
1.23 kjell 154: {
155: CCHR('@'), CCHR('H'), dirednul, (KEYMAP *) & helpmap
156: },
157: {
158: CCHR('L'), CCHR('X'), diredcl, (KEYMAP *) & cXmap
159: },
160: {
1.49 lum 161: CCHR('['), CCHR('['), dirednull, (KEYMAP *) &
162: d_backpagemap
163: },
164: {
1.27 kjell 165: CCHR('Z'), '+', diredcz, (KEYMAP *) & metamap
1.23 kjell 166: },
167: {
168: 'c', 'f', diredc, NULL
169: },
170: {
171: 'n', 'x', diredn, NULL
172: },
173: {
174: CCHR('?'), CCHR('?'), direddl, NULL
175: },
176: #ifdef DIRED_XMAPS
177: DIRED_XMAPS, /* map sections for dired mode keys */
178: #endif /* DIRED_XMAPS */
1.9 vincent 179: }
180: };
181:
1.23 kjell 182: void
183: dired_init(void)
184: {
1.27 kjell 185: funmap_add(dired, "dired");
186: funmap_add(d_undelbak, "dired-backup-unflag");
1.53 lum 187: funmap_add(d_create_directory, "dired-create-directory");
1.27 kjell 188: funmap_add(d_copy, "dired-copy-file");
189: funmap_add(d_expunge, "dired-do-deletions");
190: funmap_add(d_findfile, "dired-find-file");
191: funmap_add(d_ffotherwindow, "dired-find-file-other-window");
192: funmap_add(d_del, "dired-flag-file-deleted");
1.49 lum 193: funmap_add(d_forwline, "dired-next-line");
1.27 kjell 194: funmap_add(d_otherwindow, "dired-other-window");
1.49 lum 195: funmap_add(d_backline, "dired-previous-line");
1.27 kjell 196: funmap_add(d_rename, "dired-rename-file");
1.49 lum 197: funmap_add(d_backpage, "dired-scroll-down");
198: funmap_add(d_forwpage, "dired-scroll-up");
1.27 kjell 199: funmap_add(d_undel, "dired-unflag");
1.23 kjell 200: maps_add((KEYMAP *)&diredmap, "dired");
1.27 kjell 201: dobindkey(fundamental_map, "dired", "^Xd");
1.23 kjell 202: }
1.12 vincent 203:
1.5 millert 204: /* ARGSUSED */
205: int
1.10 vincent 206: dired(int f, int n)
1.1 deraadt 207: {
1.33 kjell 208: char dname[NFILEN], *bufp, *slash;
1.31 deraadt 209: struct buffer *bp;
1.1 deraadt 210:
1.19 cloder 211: if (curbp->b_fname && curbp->b_fname[0] != '\0') {
1.33 kjell 212: (void)strlcpy(dname, curbp->b_fname, sizeof(dname));
213: if ((slash = strrchr(dname, '/')) != NULL) {
1.19 cloder 214: *(slash + 1) = '\0';
215: }
216: } else {
1.33 kjell 217: if (getcwd(dname, sizeof(dname)) == NULL)
218: dname[0] = '\0';
1.19 cloder 219: }
220:
1.33 kjell 221: if ((bufp = eread("Dired: ", dname, NFILEN,
1.21 kjell 222: EFDEF | EFNEW | EFCR)) == NULL)
1.15 db 223: return (ABORT);
1.21 kjell 224: if (bufp[0] == '\0')
225: return (FALSE);
1.14 vincent 226: if ((bp = dired_(bufp)) == NULL)
1.15 db 227: return (FALSE);
1.23 kjell 228:
1.5 millert 229: curbp = bp;
1.37 kjell 230: return (showbuffer(bp, curwp, WFFULL | WFMODE));
1.1 deraadt 231: }
232:
1.5 millert 233: /* ARGSUSED */
234: int
1.10 vincent 235: d_otherwindow(int f, int n)
1.1 deraadt 236: {
1.33 kjell 237: char dname[NFILEN], *bufp, *slash;
1.31 deraadt 238: struct buffer *bp;
239: struct mgwin *wp;
1.5 millert 240:
1.23 kjell 241: if (curbp->b_fname && curbp->b_fname[0] != '\0') {
1.33 kjell 242: (void)strlcpy(dname, curbp->b_fname, sizeof(dname));
243: if ((slash = strrchr(dname, '/')) != NULL) {
1.23 kjell 244: *(slash + 1) = '\0';
245: }
246: } else {
1.33 kjell 247: if (getcwd(dname, sizeof(dname)) == NULL)
248: dname[0] = '\0';
1.23 kjell 249: }
250:
1.33 kjell 251: if ((bufp = eread("Dired other window: ", dname, NFILEN,
1.21 kjell 252: EFDEF | EFNEW | EFCR)) == NULL)
1.15 db 253: return (ABORT);
1.21 kjell 254: else if (bufp[0] == '\0')
255: return (FALSE);
1.14 vincent 256: if ((bp = dired_(bufp)) == NULL)
1.15 db 257: return (FALSE);
1.45 kjell 258: if ((wp = popbuf(bp, WNONE)) == NULL)
1.15 db 259: return (FALSE);
1.5 millert 260: curbp = bp;
261: curwp = wp;
1.15 db 262: return (TRUE);
1.1 deraadt 263: }
264:
1.5 millert 265: /* ARGSUSED */
266: int
1.10 vincent 267: d_del(int f, int n)
1.1 deraadt 268: {
1.5 millert 269: if (n < 0)
1.15 db 270: return (FALSE);
1.5 millert 271: while (n--) {
272: if (llength(curwp->w_dotp) > 0)
273: lputc(curwp->w_dotp, 0, 'D');
1.40 kjell 274: if (lforw(curwp->w_dotp) != curbp->b_headp)
1.5 millert 275: curwp->w_dotp = lforw(curwp->w_dotp);
276: }
1.44 kjell 277: curwp->w_rflag |= WFEDIT | WFMOVE;
1.5 millert 278: curwp->w_doto = 0;
1.15 db 279: return (TRUE);
1.1 deraadt 280: }
281:
1.5 millert 282: /* ARGSUSED */
283: int
1.10 vincent 284: d_undel(int f, int n)
1.1 deraadt 285: {
1.5 millert 286: if (n < 0)
1.15 db 287: return (d_undelbak(f, -n));
1.5 millert 288: while (n--) {
289: if (llength(curwp->w_dotp) > 0)
290: lputc(curwp->w_dotp, 0, ' ');
1.40 kjell 291: if (lforw(curwp->w_dotp) != curbp->b_headp)
1.5 millert 292: curwp->w_dotp = lforw(curwp->w_dotp);
293: }
1.44 kjell 294: curwp->w_rflag |= WFEDIT | WFMOVE;
1.5 millert 295: curwp->w_doto = 0;
1.15 db 296: return (TRUE);
1.1 deraadt 297: }
298:
1.5 millert 299: /* ARGSUSED */
300: int
1.10 vincent 301: d_undelbak(int f, int n)
1.1 deraadt 302: {
1.5 millert 303: if (n < 0)
1.15 db 304: return (d_undel(f, -n));
1.5 millert 305: while (n--) {
306: if (llength(curwp->w_dotp) > 0)
307: lputc(curwp->w_dotp, 0, ' ');
1.40 kjell 308: if (lback(curwp->w_dotp) != curbp->b_headp)
1.5 millert 309: curwp->w_dotp = lback(curwp->w_dotp);
310: }
311: curwp->w_doto = 0;
1.44 kjell 312: curwp->w_rflag |= WFEDIT | WFMOVE;
1.15 db 313: return (TRUE);
1.1 deraadt 314: }
315:
1.5 millert 316: /* ARGSUSED */
317: int
1.10 vincent 318: d_findfile(int f, int n)
1.1 deraadt 319: {
1.31 deraadt 320: struct buffer *bp;
321: int s;
322: char fname[NFILEN];
1.5 millert 323:
1.15 db 324: if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT)
325: return (FALSE);
1.12 vincent 326: if (s == TRUE)
327: bp = dired_(fname);
328: else
329: bp = findbuffer(fname);
330: if (bp == NULL)
1.15 db 331: return (FALSE);
1.5 millert 332: curbp = bp;
1.37 kjell 333: if (showbuffer(bp, curwp, WFFULL) != TRUE)
1.15 db 334: return (FALSE);
1.5 millert 335: if (bp->b_fname[0] != 0)
1.15 db 336: return (TRUE);
337: return (readin(fname));
1.1 deraadt 338: }
339:
1.5 millert 340: /* ARGSUSED */
341: int
1.10 vincent 342: d_ffotherwindow(int f, int n)
1.1 deraadt 343: {
1.31 deraadt 344: char fname[NFILEN];
345: int s;
346: struct buffer *bp;
347: struct mgwin *wp;
1.5 millert 348:
1.15 db 349: if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT)
350: return (FALSE);
1.5 millert 351: if ((bp = (s ? dired_(fname) : findbuffer(fname))) == NULL)
1.15 db 352: return (FALSE);
1.45 kjell 353: if ((wp = popbuf(bp, WNONE)) == NULL)
1.15 db 354: return (FALSE);
1.5 millert 355: curbp = bp;
356: curwp = wp;
357: if (bp->b_fname[0] != 0)
1.15 db 358: return (TRUE); /* never true for dired buffers */
359: return (readin(fname));
1.1 deraadt 360: }
361:
1.5 millert 362: /* ARGSUSED */
363: int
1.10 vincent 364: d_expunge(int f, int n)
1.1 deraadt 365: {
1.31 deraadt 366: struct line *lp, *nlp;
1.48 kjell 367: char fname[NFILEN], sname[NFILEN];
1.5 millert 368:
1.41 kjell 369: for (lp = bfirstlp(curbp); lp != curbp->b_headp; lp = nlp) {
1.5 millert 370: nlp = lforw(lp);
371: if (llength(lp) && lgetc(lp, 0) == 'D') {
1.15 db 372: switch (d_makename(lp, fname, sizeof(fname))) {
1.5 millert 373: case ABORT:
374: ewprintf("Bad line in dired buffer");
1.15 db 375: return (FALSE);
1.5 millert 376: case FALSE:
377: if (unlink(fname) < 0) {
1.48 kjell 378: (void)xbasename(sname, fname, NFILEN);
379: ewprintf("Could not delete '%s'", sname);
1.15 db 380: return (FALSE);
1.5 millert 381: }
382: break;
383: case TRUE:
384: if (rmdir(fname) < 0) {
1.48 kjell 385: (void)xbasename(sname, fname, NFILEN);
386: ewprintf("Could not delete directory "
387: "'%s'", sname);
1.15 db 388: return (FALSE);
1.5 millert 389: }
390: break;
391: }
392: lfree(lp);
1.39 kjell 393: curwp->w_bufp->b_lines--;
1.44 kjell 394: curwp->w_rflag |= WFFULL;
1.5 millert 395: }
1.1 deraadt 396: }
1.15 db 397: return (TRUE);
1.1 deraadt 398: }
399:
1.5 millert 400: /* ARGSUSED */
401: int
1.10 vincent 402: d_copy(int f, int n)
1.1 deraadt 403: {
1.48 kjell 404: char frname[NFILEN], toname[NFILEN], sname[NFILEN], *bufp;
1.33 kjell 405: int ret;
1.18 cloder 406: size_t off;
1.31 deraadt 407: struct buffer *bp;
1.1 deraadt 408:
1.15 db 409: if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE) {
1.5 millert 410: ewprintf("Not a file");
1.15 db 411: return (FALSE);
1.5 millert 412: }
1.15 db 413: off = strlcpy(toname, curbp->b_fname, sizeof(toname));
414: if (off >= sizeof(toname) - 1) { /* can't happen, really */
1.18 cloder 415: ewprintf("Directory name too long");
1.12 vincent 416: return (FALSE);
417: }
1.48 kjell 418: (void)xbasename(sname, frname, NFILEN);
419: bufp = eread("Copy %s to: ", toname, sizeof(toname),
420: EFDEF | EFNEW | EFCR, sname);
421: if (bufp == NULL)
1.15 db 422: return (ABORT);
1.14 vincent 423: else if (bufp[0] == '\0')
1.17 otto 424: return (FALSE);
1.33 kjell 425: ret = (copy(frname, toname) >= 0) ? TRUE : FALSE;
426: if (ret != TRUE)
427: return (ret);
1.54 ! lum 428: if ((bp = refreshbuffer(curbp)) == NULL)
! 429: return (FALSE);
1.37 kjell 430: return (showbuffer(bp, curwp, WFFULL | WFMODE));
1.1 deraadt 431: }
432:
1.5 millert 433: /* ARGSUSED */
434: int
1.10 vincent 435: d_rename(int f, int n)
1.1 deraadt 436: {
1.31 deraadt 437: char frname[NFILEN], toname[NFILEN], *bufp;
1.33 kjell 438: int ret;
1.31 deraadt 439: size_t off;
440: struct buffer *bp;
1.48 kjell 441: char sname[NFILEN];
1.1 deraadt 442:
1.15 db 443: if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE) {
1.5 millert 444: ewprintf("Not a file");
1.15 db 445: return (FALSE);
1.5 millert 446: }
1.15 db 447: off = strlcpy(toname, curbp->b_fname, sizeof(toname));
448: if (off >= sizeof(toname) - 1) { /* can't happen, really */
1.18 cloder 449: ewprintf("Directory name too long");
1.12 vincent 450: return (FALSE);
451: }
1.48 kjell 452: (void)xbasename(sname, frname, NFILEN);
453: bufp = eread("Rename %s to: ", toname,
454: sizeof(toname), EFDEF | EFNEW | EFCR, sname);
455: if (bufp == NULL)
1.15 db 456: return (ABORT);
1.14 vincent 457: else if (bufp[0] == '\0')
1.15 db 458: return (FALSE);
1.33 kjell 459: ret = (rename(frname, toname) >= 0) ? TRUE : FALSE;
460: if (ret != TRUE)
461: return (ret);
1.54 ! lum 462: if ((bp = refreshbuffer(curbp)) == NULL)
! 463: return (FALSE);
1.37 kjell 464: return (showbuffer(bp, curwp, WFFULL | WFMODE));
1.1 deraadt 465: }
1.12 vincent 466:
1.31 deraadt 467: /* ARGSUSED */
1.12 vincent 468: void
469: reaper(int signo __attribute__((unused)))
470: {
1.22 deraadt 471: int save_errno = errno, status;
1.12 vincent 472:
1.25 deraadt 473: while (waitpid(-1, &status, WNOHANG) >= 0)
1.12 vincent 474: ;
1.22 deraadt 475: errno = save_errno;
1.12 vincent 476: }
477:
478: /*
479: * Pipe the currently selected file through a shell command.
480: */
1.26 kjell 481: /* ARGSUSED */
1.12 vincent 482: int
483: d_shell_command(int f, int n)
484: {
1.50 lum 485: char command[512], fname[MAXPATHLEN], *bufp;
1.31 deraadt 486: struct buffer *bp;
487: struct mgwin *wp;
1.50 lum 488: char sname[NFILEN];
1.12 vincent 489:
490: bp = bfind("*Shell Command Output*", TRUE);
491: if (bclear(bp) != TRUE)
492: return (ABORT);
493:
1.15 db 494: if (d_makename(curwp->w_dotp, fname, sizeof(fname)) != FALSE) {
1.12 vincent 495: ewprintf("bad line");
496: return (ABORT);
497: }
498:
499: command[0] = '\0';
1.48 kjell 500: (void)xbasename(sname, fname, NFILEN);
501: bufp = eread("! on %s: ", command, sizeof(command), EFNEW, sname);
502: if (bufp == NULL)
1.12 vincent 503: return (ABORT);
1.50 lum 504:
505: if (d_exec(0, bp, fname, "sh", "-c", command, NULL) != TRUE)
506: return (ABORT);
507:
508: if ((wp = popbuf(bp, WNONE)) == NULL)
509: return (ABORT); /* XXX - free the buffer?? */
510: curwp = wp;
511: curbp = wp->w_bufp;
512: return (TRUE);
513: }
514:
515: /*
516: * Pipe input file to cmd and insert the command's output in the
517: * given buffer. Each line will be prefixed with the given
518: * number of spaces.
519: */
520: static int
521: d_exec(int space, struct buffer *bp, const char *input, const char *cmd, ...)
522: {
523: char buf[BUFSIZ];
524: va_list ap;
525: struct sigaction olda, newa;
526: char **argv = NULL, *cp;
527: FILE *fin;
528: int fds[2] = { -1, -1 };
529: int infd = -1;
530: int ret = (ABORT), n;
531: pid_t pid;
532:
533: if (sigaction(SIGCHLD, NULL, &olda) == -1)
534: return (ABORT);
535:
536: /* Find the number of arguments. */
537: va_start(ap, cmd);
538: for (n = 2; va_arg(ap, char *) != NULL; n++)
539: ;
540: va_end(ap);
541:
542: /* Allocate and build the argv. */
543: if ((argv = calloc(n, sizeof(*argv))) == NULL) {
544: ewprintf("Can't allocate argv : %s", strerror(errno));
545: goto out;
546: }
547:
548: n = 1;
549: argv[0] = (char *)cmd;
550: va_start(ap, cmd);
551: while ((argv[n] = va_arg(ap, char *)) != NULL)
552: n++;
553: va_end(ap);
554:
555: if (input == NULL)
556: input = "/dev/null";
557:
558: if ((infd = open(input, O_RDONLY)) == -1) {
1.12 vincent 559: ewprintf("Can't open input file : %s", strerror(errno));
1.50 lum 560: goto out;
1.12 vincent 561: }
1.50 lum 562:
1.12 vincent 563: if (pipe(fds) == -1) {
564: ewprintf("Can't create pipe : %s", strerror(errno));
1.50 lum 565: goto out;
1.12 vincent 566: }
567:
568: newa.sa_handler = reaper;
569: newa.sa_flags = 0;
1.50 lum 570: if (sigaction(SIGCHLD, &newa, NULL) == -1)
571: goto out;
572:
573: if ((pid = fork()) == -1) {
574: ewprintf("Can't fork");
575: goto out;
1.12 vincent 576: }
1.50 lum 577:
1.12 vincent 578: switch (pid) {
1.50 lum 579: case 0: /* Child */
1.12 vincent 580: close(fds[0]);
581: dup2(infd, STDIN_FILENO);
582: dup2(fds[1], STDOUT_FILENO);
583: dup2(fds[1], STDERR_FILENO);
1.50 lum 584: if (execvp(argv[0], argv) == -1)
585: ewprintf("Can't exec %s: %s", argv[0], strerror(errno));
1.12 vincent 586: exit(1);
1.29 deraadt 587: break;
1.50 lum 588: default: /* Parent */
1.12 vincent 589: close(infd);
590: close(fds[1]);
1.50 lum 591: infd = fds[1] = -1;
592: if ((fin = fdopen(fds[0], "r")) == NULL)
593: goto out;
1.15 db 594: while (fgets(buf, sizeof(buf), fin) != NULL) {
1.12 vincent 595: cp = strrchr(buf, '\n');
596: if (cp == NULL && !feof(fin)) { /* too long a line */
597: int c;
1.50 lum 598: addlinef(bp, "%*s%s...", space, "", buf);
1.12 vincent 599: while ((c = getc(fin)) != EOF && c != '\n')
600: ;
601: continue;
602: } else if (cp)
603: *cp = '\0';
1.50 lum 604: addlinef(bp, "%*s%s", space, "", buf);
1.12 vincent 605: }
606: fclose(fin);
607: break;
608: }
1.50 lum 609: ret = (TRUE);
610:
611: out:
1.12 vincent 612: if (sigaction(SIGCHLD, &olda, NULL) == -1)
613: ewprintf("Warning, couldn't reset previous signal handler");
1.50 lum 614: if (fds[0] != -1)
615: close(fds[0]);
616: if (fds[1] != -1)
617: close(fds[1]);
618: if (infd != -1)
619: close(infd);
620: if (argv != NULL)
621: free(argv);
622: return ret;
1.12 vincent 623: }
624:
1.26 kjell 625: /* ARGSUSED */
1.12 vincent 626: int
627: d_create_directory(int f, int n)
628: {
1.15 db 629: char tocreate[MAXPATHLEN], *bufp;
1.18 cloder 630: size_t off;
1.31 deraadt 631: struct buffer *bp;
1.12 vincent 632:
1.15 db 633: off = strlcpy(tocreate, curbp->b_fname, sizeof(tocreate));
634: if (off >= sizeof(tocreate) - 1)
1.12 vincent 635: return (FALSE);
1.21 kjell 636: if ((bufp = eread("Create directory: ", tocreate,
637: sizeof(tocreate), EFDEF | EFNEW | EFCR)) == NULL)
1.14 vincent 638: return (ABORT);
639: else if (bufp[0] == '\0')
1.15 db 640: return (FALSE);
1.12 vincent 641: if (mkdir(tocreate, 0755) == -1) {
642: ewprintf("Creating directory: %s, %s", strerror(errno),
643: tocreate);
1.21 kjell 644: return (FALSE);
1.12 vincent 645: }
1.54 ! lum 646: if ((bp = refreshbuffer(curbp)) == NULL)
! 647: return (FALSE);
1.37 kjell 648: return (showbuffer(bp, curwp, WFFULL | WFMODE));
1.54 ! lum 649: }
! 650:
! 651: struct buffer *
! 652: refreshbuffer(struct buffer *bp)
! 653: {
! 654: char *tmp;
! 655:
! 656: tmp = strdup(bp->b_fname);
! 657: if (tmp == NULL)
! 658: err(1, NULL);
! 659:
! 660: killbuffer(bp);
! 661:
! 662: /* dired_() uses findbuffer() to create new buffer */
! 663: if ((bp = dired_(tmp)) == NULL) {
! 664: free(tmp);
! 665: return (NULL);
! 666: }
! 667: free(tmp);
! 668: curbp = bp;
! 669:
! 670: return (bp);
1.12 vincent 671: }
1.24 kjell 672:
673: static int
1.34 kjell 674: d_makename(struct line *lp, char *fn, size_t len)
1.24 kjell 675: {
1.50 lum 676: int start, nlen;
677: char *namep;
1.24 kjell 678:
1.50 lum 679: if (d_warpdot(lp, &start) == FALSE)
1.24 kjell 680: return (ABORT);
1.50 lum 681: namep = &lp->l_text[start];
682: nlen = llength(lp) - start;
683:
684: if (snprintf(fn, len, "%s%.*s", curbp->b_fname, nlen, namep) >= len)
685: return (ABORT); /* Name is too long. */
686:
687: /* Return TRUE if the entry is a directory. */
1.24 kjell 688: return ((lgetc(lp, 2) == 'd') ? TRUE : FALSE);
689: }
690:
1.50 lum 691: #define NAME_FIELD 9
692:
1.49 lum 693: static int
694: d_warpdot(struct line *dotp, int *doto)
695: {
696: char *tp = dotp->l_text;
697: int off = 0, field = 0, len;
698:
699: /*
700: * Find the byte offset to the (space-delimited) filename
701: * field in formatted ls output.
702: */
703: len = llength(dotp);
704: while (off < len) {
705: if (tp[off++] == ' ') {
1.50 lum 706: if (++field == NAME_FIELD) {
707: *doto = off;
708: return (TRUE);
709: }
1.49 lum 710: /* Skip the space. */
711: while (off < len && tp[off] == ' ')
712: off++;
713: }
714: }
1.50 lum 715: /* We didn't find the field. */
716: *doto = 0;
717: return (FALSE);
1.49 lum 718: }
719:
720: static int
721: d_forwpage(int f, int n)
722: {
723: forwpage(f | FFRAND, n);
724: return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
725: }
726:
727: static int
728: d_backpage (int f, int n)
729: {
730: backpage(f | FFRAND, n);
731: return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
732: }
733:
734: static int
735: d_forwline (int f, int n)
736: {
737: forwline(f | FFRAND, n);
738: return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
739: }
740:
741: static int
742: d_backline (int f, int n)
743: {
744: backline(f | FFRAND, n);
745: return (d_warpdot(curwp->w_dotp, &curwp->w_doto));
746: }
747:
1.24 kjell 748: /*
1.33 kjell 749: * XXX dname needs to have enough place to store an additional '/'.
1.24 kjell 750: */
1.31 deraadt 751: struct buffer *
1.33 kjell 752: dired_(char *dname)
1.24 kjell 753: {
1.31 deraadt 754: struct buffer *bp;
1.52 haesbaer 755: int i;
756: size_t len;
1.46 kjell 757:
1.52 haesbaer 758: if ((access(dname, R_OK | X_OK)) == -1) {
1.46 kjell 759: if (errno == EACCES)
760: ewprintf("Permission denied");
761: return (NULL);
762: }
1.38 jason 763: if ((dname = adjustname(dname, FALSE)) == NULL) {
1.24 kjell 764: ewprintf("Bad directory name");
765: return (NULL);
766: }
767: /* this should not be done, instead adjustname() should get a flag */
1.33 kjell 768: len = strlen(dname);
769: if (dname[len - 1] != '/') {
770: dname[len++] = '/';
771: dname[len] = '\0';
1.24 kjell 772: }
1.33 kjell 773: if ((bp = findbuffer(dname)) == NULL) {
1.24 kjell 774: ewprintf("Could not create buffer");
775: return (NULL);
776: }
777: if (bclear(bp) != TRUE)
778: return (NULL);
779: bp->b_flag |= BFREADONLY;
1.50 lum 780:
781: if ((d_exec(2, bp, NULL, "ls", "-al", dname, NULL)) != TRUE)
1.24 kjell 782: return (NULL);
1.49 lum 783:
784: /* Find the line with ".." on it. */
1.41 kjell 785: bp->b_dotp = bfirstlp(bp);
1.49 lum 786: for (i = 0; i < bp->b_lines; i++) {
787: bp->b_dotp = lforw(bp->b_dotp);
1.50 lum 788: if (d_warpdot(bp->b_dotp, &bp->b_doto) == FALSE)
1.49 lum 789: continue;
790: if (strcmp(ltext(bp->b_dotp) + bp->b_doto, "..") == 0)
791: break;
792: }
793:
794: /* We want dot on the entry right after "..", if possible. */
795: if (++i < bp->b_lines - 2)
796: bp->b_dotp = lforw(bp->b_dotp);
797: d_warpdot(bp->b_dotp, &bp->b_doto);
798:
1.36 kjell 799: (void)strlcpy(bp->b_fname, dname, sizeof(bp->b_fname));
800: (void)strlcpy(bp->b_cwd, dname, sizeof(bp->b_cwd));
1.24 kjell 801: if ((bp->b_modes[1] = name_mode("dired")) == NULL) {
802: bp->b_modes[0] = name_mode("fundamental");
803: ewprintf("Could not find mode dired");
804: return (NULL);
805: }
806: bp->b_nmodes = 1;
807: return (bp);
808: }