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

1.22    ! deraadt     1: /*     $OpenBSD: dired.c,v 1.21 2005/08/09 00:53:48 kjell 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') {
1.21      kjell     130:                (void)strlcpy(dirname, curbp->b_fname, sizeof(dirname));
1.19      cloder    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:
1.21      kjell     139:        if ((bufp = eread("Dired: ", dirname, NFILEN,
                    140:            EFDEF | EFNEW | EFCR)) == NULL)
1.15      db        141:                return (ABORT);
1.21      kjell     142:        if (bufp[0] == '\0')
                    143:                return (FALSE);
1.14      vincent   144:        if ((bp = dired_(bufp)) == NULL)
1.15      db        145:                return (FALSE);
1.9       vincent   146:        bp->b_modes[0] = name_mode("fundamental");
                    147:        bp->b_modes[1] = name_mode("dired");
                    148:        bp->b_nmodes = 1;
1.5       millert   149:        curbp = bp;
1.15      db        150:        return (showbuffer(bp, curwp, WFHARD | WFMODE));
1.1       deraadt   151: }
                    152:
1.5       millert   153: /* ARGSUSED */
                    154: int
1.10      vincent   155: d_otherwindow(int f, int n)
1.1       deraadt   156: {
1.15      db        157:        char     dirname[NFILEN], *bufp;
1.7       mickey    158:        BUFFER  *bp;
                    159:        MGWIN   *wp;
1.5       millert   160:
                    161:        dirname[0] = '\0';
1.14      vincent   162:        if ((bufp = eread("Dired other window: ", dirname, NFILEN,
1.21      kjell     163:            EFDEF | EFNEW | EFCR)) == NULL)
1.15      db        164:                return (ABORT);
1.21      kjell     165:        else if (bufp[0] == '\0')
                    166:                return (FALSE);
1.14      vincent   167:        if ((bp = dired_(bufp)) == NULL)
1.15      db        168:                return (FALSE);
1.5       millert   169:        if ((wp = popbuf(bp)) == NULL)
1.15      db        170:                return (FALSE);
1.5       millert   171:        curbp = bp;
                    172:        curwp = wp;
1.15      db        173:        return (TRUE);
1.1       deraadt   174: }
                    175:
1.5       millert   176: /* ARGSUSED */
                    177: int
1.10      vincent   178: d_del(int f, int n)
1.1       deraadt   179: {
1.5       millert   180:        if (n < 0)
1.15      db        181:                return (FALSE);
1.5       millert   182:        while (n--) {
                    183:                if (llength(curwp->w_dotp) > 0)
                    184:                        lputc(curwp->w_dotp, 0, 'D');
                    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_undel(int f, int n)
1.1       deraadt   196: {
1.5       millert   197:        if (n < 0)
1.15      db        198:                return (d_undelbak(f, -n));
1.5       millert   199:        while (n--) {
                    200:                if (llength(curwp->w_dotp) > 0)
                    201:                        lputc(curwp->w_dotp, 0, ' ');
                    202:                if (lforw(curwp->w_dotp) != curbp->b_linep)
                    203:                        curwp->w_dotp = lforw(curwp->w_dotp);
                    204:        }
                    205:        curwp->w_flag |= WFEDIT | WFMOVE;
                    206:        curwp->w_doto = 0;
1.15      db        207:        return (TRUE);
1.1       deraadt   208: }
                    209:
1.5       millert   210: /* ARGSUSED */
                    211: int
1.10      vincent   212: d_undelbak(int f, int n)
1.1       deraadt   213: {
1.5       millert   214:        if (n < 0)
1.15      db        215:                return (d_undel(f, -n));
1.5       millert   216:        while (n--) {
                    217:                if (llength(curwp->w_dotp) > 0)
                    218:                        lputc(curwp->w_dotp, 0, ' ');
                    219:                if (lback(curwp->w_dotp) != curbp->b_linep)
                    220:                        curwp->w_dotp = lback(curwp->w_dotp);
                    221:        }
                    222:        curwp->w_doto = 0;
                    223:        curwp->w_flag |= WFEDIT | WFMOVE;
1.15      db        224:        return (TRUE);
1.1       deraadt   225: }
                    226:
1.5       millert   227: /* ARGSUSED */
                    228: int
1.10      vincent   229: d_findfile(int f, int n)
1.1       deraadt   230: {
1.15      db        231:        BUFFER  *bp;
                    232:        int      s;
                    233:        char     fname[NFILEN];
1.5       millert   234:
1.15      db        235:        if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT)
                    236:                return (FALSE);
1.12      vincent   237:        if (s == TRUE)
                    238:                bp = dired_(fname);
                    239:        else
                    240:                bp = findbuffer(fname);
                    241:        if (bp == NULL)
1.15      db        242:                return (FALSE);
1.5       millert   243:        curbp = bp;
                    244:        if (showbuffer(bp, curwp, WFHARD) != TRUE)
1.15      db        245:                return (FALSE);
1.5       millert   246:        if (bp->b_fname[0] != 0)
1.15      db        247:                return (TRUE);
                    248:        return (readin(fname));
1.1       deraadt   249: }
                    250:
1.5       millert   251: /* ARGSUSED */
                    252: int
1.10      vincent   253: d_ffotherwindow(int f, int n)
1.1       deraadt   254: {
1.7       mickey    255:        char    fname[NFILEN];
                    256:        int     s;
1.5       millert   257:        BUFFER *bp;
                    258:        MGWIN  *wp;
                    259:
1.15      db        260:        if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT)
                    261:                return (FALSE);
1.5       millert   262:        if ((bp = (s ? dired_(fname) : findbuffer(fname))) == NULL)
1.15      db        263:                return (FALSE);
1.5       millert   264:        if ((wp = popbuf(bp)) == NULL)
1.15      db        265:                return (FALSE);
1.5       millert   266:        curbp = bp;
                    267:        curwp = wp;
                    268:        if (bp->b_fname[0] != 0)
1.15      db        269:                return (TRUE);  /* never true for dired buffers */
                    270:        return (readin(fname));
1.1       deraadt   271: }
                    272:
1.5       millert   273: /* ARGSUSED */
                    274: int
1.10      vincent   275: d_expunge(int f, int n)
1.1       deraadt   276: {
1.7       mickey    277:        LINE    *lp, *nlp;
1.15      db        278:        char     fname[NFILEN];
1.5       millert   279:
                    280:        for (lp = lforw(curbp->b_linep); lp != curbp->b_linep; lp = nlp) {
                    281:                nlp = lforw(lp);
                    282:                if (llength(lp) && lgetc(lp, 0) == 'D') {
1.15      db        283:                        switch (d_makename(lp, fname, sizeof(fname))) {
1.5       millert   284:                        case ABORT:
                    285:                                ewprintf("Bad line in dired buffer");
1.15      db        286:                                return (FALSE);
1.5       millert   287:                        case FALSE:
                    288:                                if (unlink(fname) < 0) {
1.12      vincent   289:                                        ewprintf("Could not delete '%s'",
                    290:                                            basename(fname));
1.15      db        291:                                        return (FALSE);
1.5       millert   292:                                }
                    293:                                break;
                    294:                        case TRUE:
                    295:                                if (rmdir(fname) < 0) {
                    296:                                        ewprintf("Could not delete directory '%s'",
1.12      vincent   297:                                            basename(fname));
1.15      db        298:                                        return (FALSE);
1.5       millert   299:                                }
                    300:                                break;
                    301:                        }
                    302:                        lfree(lp);
                    303:                        curwp->w_flag |= WFHARD;
                    304:                }
1.1       deraadt   305:        }
1.15      db        306:        return (TRUE);
1.1       deraadt   307: }
                    308:
1.5       millert   309: /* ARGSUSED */
                    310: int
1.10      vincent   311: d_copy(int f, int n)
1.1       deraadt   312: {
1.14      vincent   313:        char    frname[NFILEN], toname[NFILEN], *bufp;
                    314:        int     stat;
1.18      cloder    315:        size_t  off;
1.12      vincent   316:        BUFFER *bp;
1.1       deraadt   317:
1.15      db        318:        if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE) {
1.5       millert   319:                ewprintf("Not a file");
1.15      db        320:                return (FALSE);
1.5       millert   321:        }
1.15      db        322:        off = strlcpy(toname, curbp->b_fname, sizeof(toname));
                    323:        if (off >= sizeof(toname) - 1) {        /* can't happen, really */
1.18      cloder    324:                ewprintf("Directory name too long");
1.12      vincent   325:                return (FALSE);
                    326:        }
1.21      kjell     327:        if ((bufp = eread("Copy %s to: ", toname, sizeof(toname),
                    328:            EFDEF | EFNEW | EFCR, basename(frname))) == NULL)
1.15      db        329:                return (ABORT);
1.14      vincent   330:        else if (bufp[0] == '\0')
1.17      otto      331:                return (FALSE);
1.12      vincent   332:        stat = (copy(frname, toname) >= 0) ? TRUE : FALSE;
                    333:        if (stat != TRUE)
                    334:                return (stat);
                    335:        bp = dired_(curbp->b_fname);
                    336:        return (showbuffer(bp, curwp, WFHARD | WFMODE));
1.1       deraadt   337: }
                    338:
1.5       millert   339: /* ARGSUSED */
                    340: int
1.10      vincent   341: d_rename(int f, int n)
1.1       deraadt   342: {
1.14      vincent   343:        char    frname[NFILEN], toname[NFILEN], *bufp;
1.18      cloder    344:        int     stat;
                    345:        size_t  off;
1.12      vincent   346:        BUFFER *bp;
1.1       deraadt   347:
1.15      db        348:        if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE) {
1.5       millert   349:                ewprintf("Not a file");
1.15      db        350:                return (FALSE);
1.5       millert   351:        }
1.15      db        352:        off = strlcpy(toname, curbp->b_fname, sizeof(toname));
                    353:        if (off >= sizeof(toname) - 1) {        /* can't happen, really */
1.18      cloder    354:                ewprintf("Directory name too long");
1.12      vincent   355:                return (FALSE);
                    356:        }
1.21      kjell     357:        if ((bufp = eread("Rename %s to: ", toname,
                    358:            sizeof(toname), EFDEF | EFNEW | EFCR, basename(frname))) == NULL)
1.15      db        359:                return (ABORT);
1.14      vincent   360:        else if (bufp[0] == '\0')
1.15      db        361:                return (FALSE);
1.12      vincent   362:        stat = (rename(frname, toname) >= 0) ? TRUE : FALSE;
                    363:        if (stat != TRUE)
                    364:                return (stat);
                    365:        bp = dired_(curbp->b_fname);
                    366:        return (showbuffer(bp, curwp, WFHARD | WFMODE));
1.1       deraadt   367: }
                    368: #endif
1.12      vincent   369:
                    370: void
                    371: reaper(int signo __attribute__((unused)))
                    372: {
1.22    ! deraadt   373:        int     save_errno = errno, status;
1.15      db        374:        pid_t   ret;
1.12      vincent   375:
                    376:        while ((ret = waitpid(-1, &status, WNOHANG)) >= 0)
                    377:                ;
1.22    ! deraadt   378:        errno = save_errno;
1.12      vincent   379: }
                    380:
                    381: /*
                    382:  * Pipe the currently selected file through a shell command.
                    383:  */
                    384: int
                    385: d_shell_command(int f, int n)
                    386: {
1.15      db        387:        char     command[512], fname[MAXPATHLEN], buf[BUFSIZ], *bufp, *cp;
                    388:        int      infd, fds[2];
                    389:        pid_t    pid;
                    390:        struct   sigaction olda, newa;
                    391:        BUFFER  *bp;
                    392:        MGWIN   *wp;
                    393:        FILE    *fin;
1.12      vincent   394:
                    395:        bp = bfind("*Shell Command Output*", TRUE);
                    396:        if (bclear(bp) != TRUE)
                    397:                return (ABORT);
                    398:
1.15      db        399:        if (d_makename(curwp->w_dotp, fname, sizeof(fname)) != FALSE) {
1.12      vincent   400:                ewprintf("bad line");
                    401:                return (ABORT);
                    402:        }
                    403:
                    404:        command[0] = '\0';
1.21      kjell     405:        if ((bufp = eread("! on %s: ", command, sizeof(command), EFNEW,
1.14      vincent   406:            basename(fname))) == NULL)
1.12      vincent   407:                return (ABORT);
                    408:        infd = open(fname, O_RDONLY);
                    409:        if (infd == -1) {
                    410:                ewprintf("Can't open input file : %s", strerror(errno));
1.21      kjell     411:                return (FALSE);
1.12      vincent   412:        }
                    413:        if (pipe(fds) == -1) {
                    414:                ewprintf("Can't create pipe : %s", strerror(errno));
                    415:                close(infd);
1.21      kjell     416:                return (FALSE);
1.12      vincent   417:        }
                    418:
                    419:        newa.sa_handler = reaper;
                    420:        newa.sa_flags = 0;
                    421:        if (sigaction(SIGCHLD, &newa, &olda) == -1) {
                    422:                close(infd);
                    423:                close(fds[0]);
                    424:                close(fds[1]);
                    425:                return (ABORT);
                    426:        }
                    427:        pid = fork();
                    428:        switch (pid) {
                    429:        case -1:
                    430:                ewprintf("Can't fork");
                    431:                return (ABORT);
                    432:        case 0:
                    433:                close(fds[0]);
                    434:                dup2(infd, STDIN_FILENO);
                    435:                dup2(fds[1], STDOUT_FILENO);
                    436:                dup2(fds[1], STDERR_FILENO);
1.14      vincent   437:                execl("/bin/sh", "sh", "-c", bufp, (char *)NULL);
1.12      vincent   438:                exit(1);
                    439:        default:
                    440:                close(infd);
                    441:                close(fds[1]);
                    442:                fin = fdopen(fds[0], "r");
                    443:                if (fin == NULL)        /* "r" is surely a valid mode! */
                    444:                        panic("can't happen");
1.15      db        445:                while (fgets(buf, sizeof(buf), fin) != NULL) {
1.12      vincent   446:                        cp = strrchr(buf, '\n');
                    447:                        if (cp == NULL && !feof(fin)) { /* too long a line */
                    448:                                int c;
                    449:                                addlinef(bp, "%s...", buf);
                    450:                                while ((c = getc(fin)) != EOF && c != '\n')
                    451:                                        ;
                    452:                                continue;
                    453:                        } else if (cp)
                    454:                                *cp = '\0';
                    455:                        addline(bp, buf);
                    456:                }
                    457:                fclose(fin);
                    458:                close(fds[0]);
                    459:                break;
                    460:        }
                    461:        wp = popbuf(bp);
                    462:        if (wp == NULL)
                    463:                return (ABORT); /* XXX - free the buffer?? */
                    464:        curwp = wp;
                    465:        curbp = wp->w_bufp;
                    466:        if (sigaction(SIGCHLD, &olda, NULL) == -1)
                    467:                ewprintf("Warning, couldn't reset previous signal handler");
                    468:        return (TRUE);
                    469: }
                    470:
                    471: int
                    472: d_create_directory(int f, int n)
                    473: {
1.15      db        474:        char     tocreate[MAXPATHLEN], *bufp;
1.18      cloder    475:        size_t  off;
1.15      db        476:        BUFFER  *bp;
1.12      vincent   477:
1.15      db        478:        off = strlcpy(tocreate, curbp->b_fname, sizeof(tocreate));
                    479:        if (off >= sizeof(tocreate) - 1)
1.12      vincent   480:                return (FALSE);
1.21      kjell     481:        if ((bufp = eread("Create directory: ", tocreate,
                    482:            sizeof(tocreate), EFDEF | EFNEW | EFCR)) == NULL)
1.14      vincent   483:                return (ABORT);
                    484:        else if (bufp[0] == '\0')
1.15      db        485:                return (FALSE);
1.12      vincent   486:        if (mkdir(tocreate, 0755) == -1) {
                    487:                ewprintf("Creating directory: %s, %s", strerror(errno),
                    488:                    tocreate);
1.21      kjell     489:                return (FALSE);
1.12      vincent   490:        }
                    491:        bp = dired_(curbp->b_fname);
                    492:        return (showbuffer(bp, curwp, WFHARD | WFMODE));
                    493: }