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