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