[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.20

1.20    ! kjell       1: /*     $OpenBSD: dired.c,v 1.19 2005/05/28 01:53:37 cloder 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.9       vincent    10: #include "kbd.h"
1.12      vincent    11: #include <sys/types.h>
                     12: #include <sys/stat.h>
                     13: #include <sys/wait.h>
                     14:
                     15: #include <signal.h>
                     16: #include <fcntl.h>
                     17: #include <errno.h>
                     18: #include <libgen.h>
1.1       deraadt    19:
                     20: #ifndef NO_DIRED
1.11      vincent    21:
                     22: int d_findfile(int, int);
1.1       deraadt    23:
1.12      vincent    24: static PF dired_cmds_1[] = {
                     25:        forwline,               /* space */
                     26:        d_shell_command,        /* ! */
                     27:        rescan,                 /* " */
                     28:        rescan,                 /* # */
                     29:        rescan,                 /* $ */
                     30:        rescan,                 /* % */
                     31:        rescan,                 /* & */
                     32:        rescan,                 /* ' */
                     33:        rescan,                 /* ( */
                     34:        rescan,                 /* ) */
                     35:        rescan,                 /* * */
1.15      db         36:        d_create_directory      /* + */
1.12      vincent    37: };
                     38:
                     39: static PF dired_cmds_2[] = {
1.15      db         40:        rescan,                 /* a */
                     41:        rescan,                 /* b */
                     42:        rescan,                 /* c */
                     43:        rescan,                 /* d */
                     44:        d_findfile,             /* e */
                     45:        d_findfile,             /* f */
                     46:        rescan,                 /* g */
                     47:        rescan,                 /* h */
                     48:        rescan,                 /* i */
                     49:        rescan,                 /* j */
                     50:        rescan,                 /* k */
                     51:        rescan,                 /* l */
                     52:        rescan,                 /* m */
                     53:        forwline,               /* n */
                     54:        d_ffotherwindow,        /* o */
                     55:        rescan,                 /* p */
                     56:        rescan,                 /* q */
                     57:        rescan,                 /* r */
                     58:        rescan,                 /* s */
                     59:        rescan,                 /* t */
                     60:        rescan,                 /* u */
                     61:        d_findfile,             /* v */
                     62:        rescan,                 /* w */
                     63:        d_expunge,              /* x */
                     64:        rescan,                 /* y */
                     65:        rescan                  /* z */
1.12      vincent    66: };
                     67:
                     68: static PF dired_cmds_3[] = {
1.15      db         69:        rescan,                 /* A */
                     70:        rescan,                 /* B */
                     71:        d_copy,                 /* C */
                     72:        d_del,                  /* D */
                     73:        rescan,                 /* E */
                     74:        rescan,                 /* F */
                     75:        rescan,                 /* G */
                     76:        rescan,                 /* H */
                     77:        rescan,                 /* I */
                     78:        rescan,                 /* J */
                     79:        rescan,                 /* K */
                     80:        rescan,                 /* L */
                     81:        rescan,                 /* M */
                     82:        rescan,                 /* N */
                     83:        rescan,                 /* O */
                     84:        rescan,                 /* P */
                     85:        rescan,                 /* Q */
                     86:        d_rename,               /* R */
                     87:        rescan,                 /* S */
                     88:        rescan,                 /* T */
                     89:        rescan,                 /* U */
                     90:        d_findfile,             /* V */
                     91:        rescan,                 /* W */
                     92:        d_expunge,              /* X */
                     93:        rescan,                 /* Y */
                     94:        rescan                  /* Z */
1.12      vincent    95: };
                     96:
1.9       vincent    97: static PF dired_pf[] = {
1.15      db         98:        d_findfile,             /* ^M */
                     99:        rescan,                 /* ^N */
                    100:        d_findfile              /* ^O */
1.9       vincent   101: };
1.13      deraadt   102:
1.12      vincent   103: static struct KEYMAPE (4 + IMAPEXT) diredmap = {
                    104:        4,
                    105:        4 + IMAPEXT,
1.9       vincent   106:        rescan,
                    107:        {
1.12      vincent   108:                { CCHR('M'), CCHR('O'), dired_pf, NULL },
                    109:                { ' ', '+', dired_cmds_1, NULL },
                    110:                { 'A', 'Z', dired_cmds_3, NULL },
                    111:                { 'a', 'z', dired_cmds_2, NULL }
1.9       vincent   112:        }
                    113: };
                    114:
1.12      vincent   115:
1.5       millert   116: /* ARGSUSED */
                    117: int
1.10      vincent   118: dired(int f, int n)
1.1       deraadt   119: {
1.15      db        120:        static int   inited = 0;
1.19      cloder    121:        char         dirname[NFILEN], *bufp, *slash;
1.15      db        122:        BUFFER      *bp;
1.1       deraadt   123:
1.9       vincent   124:        if (inited == 0) {
                    125:                maps_add((KEYMAP *)&diredmap, "dired");
                    126:                inited = 1;
                    127:        }
                    128:
1.19      cloder    129:        if (curbp->b_fname && curbp->b_fname[0] != '\0') {
                    130:                strlcpy(dirname, curbp->b_fname, sizeof(dirname));
                    131:                if ((slash = strrchr(dirname, '/')) != NULL) {
                    132:                        *(slash + 1) = '\0';
                    133:                }
                    134:        } else {
                    135:                if (getcwd(dirname, sizeof(dirname)) == NULL)
                    136:                        dirname[0] = '\0';
                    137:        }
                    138:
                    139:        if ((bufp = eread("Dired: ", dirname, NFILEN, EFDEF | EFNEW | EFCR)) == NULL)
1.15      db        140:                return (ABORT);
1.14      vincent   141:        if ((bp = dired_(bufp)) == NULL)
1.15      db        142:                return (FALSE);
1.9       vincent   143:        bp->b_modes[0] = name_mode("fundamental");
                    144:        bp->b_modes[1] = name_mode("dired");
                    145:        bp->b_nmodes = 1;
1.5       millert   146:        curbp = bp;
1.15      db        147:        return (showbuffer(bp, curwp, WFHARD | WFMODE));
1.1       deraadt   148: }
                    149:
1.5       millert   150: /* ARGSUSED */
                    151: int
1.10      vincent   152: d_otherwindow(int f, int n)
1.1       deraadt   153: {
1.15      db        154:        char     dirname[NFILEN], *bufp;
1.7       mickey    155:        BUFFER  *bp;
                    156:        MGWIN   *wp;
1.5       millert   157:
                    158:        dirname[0] = '\0';
1.14      vincent   159:        if ((bufp = eread("Dired other window: ", dirname, NFILEN,
                    160:            EFNEW | EFCR)) == NULL)
1.15      db        161:                return (ABORT);
1.14      vincent   162:        if ((bp = dired_(bufp)) == NULL)
1.15      db        163:                return (FALSE);
1.5       millert   164:        if ((wp = popbuf(bp)) == NULL)
1.15      db        165:                return (FALSE);
1.5       millert   166:        curbp = bp;
                    167:        curwp = wp;
1.15      db        168:        return (TRUE);
1.1       deraadt   169: }
                    170:
1.5       millert   171: /* ARGSUSED */
                    172: int
1.10      vincent   173: d_del(int f, int n)
1.1       deraadt   174: {
1.5       millert   175:        if (n < 0)
1.15      db        176:                return (FALSE);
1.5       millert   177:        while (n--) {
                    178:                if (llength(curwp->w_dotp) > 0)
                    179:                        lputc(curwp->w_dotp, 0, 'D');
                    180:                if (lforw(curwp->w_dotp) != curbp->b_linep)
                    181:                        curwp->w_dotp = lforw(curwp->w_dotp);
                    182:        }
                    183:        curwp->w_flag |= WFEDIT | WFMOVE;
                    184:        curwp->w_doto = 0;
1.15      db        185:        return (TRUE);
1.1       deraadt   186: }
                    187:
1.5       millert   188: /* ARGSUSED */
                    189: int
1.10      vincent   190: d_undel(int f, int n)
1.1       deraadt   191: {
1.5       millert   192:        if (n < 0)
1.15      db        193:                return (d_undelbak(f, -n));
1.5       millert   194:        while (n--) {
                    195:                if (llength(curwp->w_dotp) > 0)
                    196:                        lputc(curwp->w_dotp, 0, ' ');
                    197:                if (lforw(curwp->w_dotp) != curbp->b_linep)
                    198:                        curwp->w_dotp = lforw(curwp->w_dotp);
                    199:        }
                    200:        curwp->w_flag |= WFEDIT | WFMOVE;
                    201:        curwp->w_doto = 0;
1.15      db        202:        return (TRUE);
1.1       deraadt   203: }
                    204:
1.5       millert   205: /* ARGSUSED */
                    206: int
1.10      vincent   207: d_undelbak(int f, int n)
1.1       deraadt   208: {
1.5       millert   209:        if (n < 0)
1.15      db        210:                return (d_undel(f, -n));
1.5       millert   211:        while (n--) {
                    212:                if (llength(curwp->w_dotp) > 0)
                    213:                        lputc(curwp->w_dotp, 0, ' ');
                    214:                if (lback(curwp->w_dotp) != curbp->b_linep)
                    215:                        curwp->w_dotp = lback(curwp->w_dotp);
                    216:        }
                    217:        curwp->w_doto = 0;
                    218:        curwp->w_flag |= WFEDIT | WFMOVE;
1.15      db        219:        return (TRUE);
1.1       deraadt   220: }
                    221:
1.5       millert   222: /* ARGSUSED */
                    223: int
1.10      vincent   224: d_findfile(int f, int n)
1.1       deraadt   225: {
1.15      db        226:        BUFFER  *bp;
                    227:        int      s;
                    228:        char     fname[NFILEN];
1.5       millert   229:
1.15      db        230:        if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT)
                    231:                return (FALSE);
1.12      vincent   232:        if (s == TRUE)
                    233:                bp = dired_(fname);
                    234:        else
                    235:                bp = findbuffer(fname);
                    236:        if (bp == NULL)
1.15      db        237:                return (FALSE);
1.5       millert   238:        curbp = bp;
                    239:        if (showbuffer(bp, curwp, WFHARD) != TRUE)
1.15      db        240:                return (FALSE);
1.5       millert   241:        if (bp->b_fname[0] != 0)
1.15      db        242:                return (TRUE);
                    243:        return (readin(fname));
1.1       deraadt   244: }
                    245:
1.5       millert   246: /* ARGSUSED */
                    247: int
1.10      vincent   248: d_ffotherwindow(int f, int n)
1.1       deraadt   249: {
1.7       mickey    250:        char    fname[NFILEN];
                    251:        int     s;
1.5       millert   252:        BUFFER *bp;
                    253:        MGWIN  *wp;
                    254:
1.15      db        255:        if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT)
                    256:                return (FALSE);
1.5       millert   257:        if ((bp = (s ? dired_(fname) : findbuffer(fname))) == NULL)
1.15      db        258:                return (FALSE);
1.5       millert   259:        if ((wp = popbuf(bp)) == NULL)
1.15      db        260:                return (FALSE);
1.5       millert   261:        curbp = bp;
                    262:        curwp = wp;
                    263:        if (bp->b_fname[0] != 0)
1.15      db        264:                return (TRUE);  /* never true for dired buffers */
                    265:        return (readin(fname));
1.1       deraadt   266: }
                    267:
1.5       millert   268: /* ARGSUSED */
                    269: int
1.10      vincent   270: d_expunge(int f, int n)
1.1       deraadt   271: {
1.7       mickey    272:        LINE    *lp, *nlp;
1.15      db        273:        char     fname[NFILEN];
1.5       millert   274:
                    275:        for (lp = lforw(curbp->b_linep); lp != curbp->b_linep; lp = nlp) {
                    276:                nlp = lforw(lp);
                    277:                if (llength(lp) && lgetc(lp, 0) == 'D') {
1.15      db        278:                        switch (d_makename(lp, fname, sizeof(fname))) {
1.5       millert   279:                        case ABORT:
                    280:                                ewprintf("Bad line in dired buffer");
1.15      db        281:                                return (FALSE);
1.5       millert   282:                        case FALSE:
                    283:                                if (unlink(fname) < 0) {
1.12      vincent   284:                                        ewprintf("Could not delete '%s'",
                    285:                                            basename(fname));
1.15      db        286:                                        return (FALSE);
1.5       millert   287:                                }
                    288:                                break;
                    289:                        case TRUE:
                    290:                                if (rmdir(fname) < 0) {
                    291:                                        ewprintf("Could not delete directory '%s'",
1.12      vincent   292:                                            basename(fname));
1.15      db        293:                                        return (FALSE);
1.5       millert   294:                                }
                    295:                                break;
                    296:                        }
                    297:                        lfree(lp);
                    298:                        curwp->w_flag |= WFHARD;
                    299:                }
1.1       deraadt   300:        }
1.15      db        301:        return (TRUE);
1.1       deraadt   302: }
                    303:
1.5       millert   304: /* ARGSUSED */
                    305: int
1.10      vincent   306: d_copy(int f, int n)
1.1       deraadt   307: {
1.14      vincent   308:        char    frname[NFILEN], toname[NFILEN], *bufp;
                    309:        int     stat;
1.18      cloder    310:        size_t  off;
1.12      vincent   311:        BUFFER *bp;
1.1       deraadt   312:
1.15      db        313:        if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE) {
1.5       millert   314:                ewprintf("Not a file");
1.15      db        315:                return (FALSE);
1.5       millert   316:        }
1.15      db        317:        off = strlcpy(toname, curbp->b_fname, sizeof(toname));
                    318:        if (off >= sizeof(toname) - 1) {        /* can't happen, really */
1.18      cloder    319:                ewprintf("Directory name too long");
1.12      vincent   320:                return (FALSE);
                    321:        }
1.15      db        322:        if ((bufp = eread("Copy %s to: ", toname + off, sizeof(toname) - off,
1.14      vincent   323:            EFNEW | EFCR, basename(frname))) == NULL)
1.15      db        324:                return (ABORT);
1.14      vincent   325:        else if (bufp[0] == '\0')
1.17      otto      326:                return (FALSE);
1.12      vincent   327:        stat = (copy(frname, toname) >= 0) ? TRUE : FALSE;
                    328:        if (stat != TRUE)
                    329:                return (stat);
                    330:        bp = dired_(curbp->b_fname);
                    331:        return (showbuffer(bp, curwp, WFHARD | WFMODE));
1.1       deraadt   332: }
                    333:
1.5       millert   334: /* ARGSUSED */
                    335: int
1.10      vincent   336: d_rename(int f, int n)
1.1       deraadt   337: {
1.14      vincent   338:        char    frname[NFILEN], toname[NFILEN], *bufp;
1.18      cloder    339:        int     stat;
                    340:        size_t  off;
1.12      vincent   341:        BUFFER *bp;
1.1       deraadt   342:
1.15      db        343:        if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE) {
1.5       millert   344:                ewprintf("Not a file");
1.15      db        345:                return (FALSE);
1.5       millert   346:        }
1.15      db        347:        off = strlcpy(toname, curbp->b_fname, sizeof(toname));
                    348:        if (off >= sizeof(toname) - 1) {        /* can't happen, really */
1.18      cloder    349:                ewprintf("Directory name too long");
1.12      vincent   350:                return (FALSE);
                    351:        }
1.14      vincent   352:        if ((bufp = eread("Rename %s to: ", toname + off,
1.15      db        353:            sizeof(toname) - off, EFNEW | EFCR, basename(frname))) == NULL)
                    354:                return (ABORT);
1.14      vincent   355:        else if (bufp[0] == '\0')
1.15      db        356:                return (FALSE);
1.12      vincent   357:        stat = (rename(frname, toname) >= 0) ? TRUE : FALSE;
                    358:        if (stat != TRUE)
                    359:                return (stat);
                    360:        bp = dired_(curbp->b_fname);
                    361:        return (showbuffer(bp, curwp, WFHARD | WFMODE));
1.1       deraadt   362: }
                    363: #endif
1.12      vincent   364:
                    365: void
                    366: reaper(int signo __attribute__((unused)))
                    367: {
1.15      db        368:        pid_t   ret;
                    369:        int     status;
1.12      vincent   370:
                    371:        while ((ret = waitpid(-1, &status, WNOHANG)) >= 0)
                    372:                ;
                    373: }
                    374:
                    375: /*
                    376:  * Pipe the currently selected file through a shell command.
                    377:  */
                    378: int
                    379: d_shell_command(int f, int n)
                    380: {
1.15      db        381:        char     command[512], fname[MAXPATHLEN], buf[BUFSIZ], *bufp, *cp;
                    382:        int      infd, fds[2];
                    383:        pid_t    pid;
                    384:        struct   sigaction olda, newa;
                    385:        BUFFER  *bp;
                    386:        MGWIN   *wp;
                    387:        FILE    *fin;
1.12      vincent   388:
                    389:        bp = bfind("*Shell Command Output*", TRUE);
                    390:        if (bclear(bp) != TRUE)
                    391:                return (ABORT);
                    392:
1.15      db        393:        if (d_makename(curwp->w_dotp, fname, sizeof(fname)) != FALSE) {
1.12      vincent   394:                ewprintf("bad line");
                    395:                return (ABORT);
                    396:        }
                    397:
                    398:        command[0] = '\0';
1.15      db        399:        if ((bufp = eread("! on %s: ", command, sizeof(command), 0,
1.14      vincent   400:            basename(fname))) == NULL)
1.12      vincent   401:                return (ABORT);
                    402:        infd = open(fname, O_RDONLY);
                    403:        if (infd == -1) {
                    404:                ewprintf("Can't open input file : %s", strerror(errno));
                    405:                return (ABORT);
                    406:        }
                    407:        if (pipe(fds) == -1) {
                    408:                ewprintf("Can't create pipe : %s", strerror(errno));
                    409:                close(infd);
                    410:                return (ABORT);
                    411:        }
                    412:
                    413:        newa.sa_handler = reaper;
                    414:        newa.sa_flags = 0;
                    415:        if (sigaction(SIGCHLD, &newa, &olda) == -1) {
                    416:                close(infd);
                    417:                close(fds[0]);
                    418:                close(fds[1]);
                    419:                return (ABORT);
                    420:        }
                    421:        pid = fork();
                    422:        switch (pid) {
                    423:        case -1:
                    424:                ewprintf("Can't fork");
                    425:                return (ABORT);
                    426:        case 0:
                    427:                close(fds[0]);
                    428:                dup2(infd, STDIN_FILENO);
                    429:                dup2(fds[1], STDOUT_FILENO);
                    430:                dup2(fds[1], STDERR_FILENO);
1.14      vincent   431:                execl("/bin/sh", "sh", "-c", bufp, (char *)NULL);
1.12      vincent   432:                exit(1);
                    433:        default:
                    434:                close(infd);
                    435:                close(fds[1]);
                    436:                fin = fdopen(fds[0], "r");
                    437:                if (fin == NULL)        /* "r" is surely a valid mode! */
                    438:                        panic("can't happen");
1.15      db        439:                while (fgets(buf, sizeof(buf), fin) != NULL) {
1.12      vincent   440:                        cp = strrchr(buf, '\n');
                    441:                        if (cp == NULL && !feof(fin)) { /* too long a line */
                    442:                                int c;
                    443:                                addlinef(bp, "%s...", buf);
                    444:                                while ((c = getc(fin)) != EOF && c != '\n')
                    445:                                        ;
                    446:                                continue;
                    447:                        } else if (cp)
                    448:                                *cp = '\0';
                    449:                        addline(bp, buf);
                    450:                }
                    451:                fclose(fin);
                    452:                close(fds[0]);
                    453:                break;
                    454:        }
                    455:        wp = popbuf(bp);
                    456:        if (wp == NULL)
                    457:                return (ABORT); /* XXX - free the buffer?? */
                    458:        curwp = wp;
                    459:        curbp = wp->w_bufp;
                    460:        if (sigaction(SIGCHLD, &olda, NULL) == -1)
                    461:                ewprintf("Warning, couldn't reset previous signal handler");
                    462:        return (TRUE);
                    463: }
                    464:
                    465: int
                    466: d_create_directory(int f, int n)
                    467: {
1.15      db        468:        char     tocreate[MAXPATHLEN], *bufp;
1.18      cloder    469:        size_t  off;
1.15      db        470:        BUFFER  *bp;
1.12      vincent   471:
1.15      db        472:        off = strlcpy(tocreate, curbp->b_fname, sizeof(tocreate));
                    473:        if (off >= sizeof(tocreate) - 1)
1.12      vincent   474:                return (FALSE);
1.14      vincent   475:        if ((bufp = ereply("Create directory: ", tocreate + off,
1.15      db        476:            sizeof(tocreate) - off)) == NULL)
1.14      vincent   477:                return (ABORT);
                    478:        else if (bufp[0] == '\0')
1.15      db        479:                return (FALSE);
1.12      vincent   480:        if (mkdir(tocreate, 0755) == -1) {
                    481:                ewprintf("Creating directory: %s, %s", strerror(errno),
                    482:                    tocreate);
                    483:                return (ABORT);
                    484:        }
                    485:        bp = dired_(curbp->b_fname);
                    486:        return (showbuffer(bp, curwp, WFHARD | WFMODE));
                    487: }