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