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

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