[BACK]Return to dired.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

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: }