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