Annotation of src/usr.bin/mg/dired.c, Revision 1.13
1.13 ! deraadt 1: /* $OpenBSD: dired.c,v 1.12 2003/08/15 23:23:18 vincent 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, /* * */
33: d_create_directory, /* + */
34: };
35:
36: static PF dired_cmds_2[] = {
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 */
63: };
64:
65: static PF dired_cmds_3[] = {
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 */
92: };
93:
1.9 vincent 94: static PF dired_pf[] = {
1.12 vincent 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.9 vincent 117: static int inited = 0;
1.7 mickey 118: char dirname[NFILEN];
1.5 millert 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';
127: if (eread("Dired: ", dirname, NFILEN, EFNEW | EFCR) == ABORT)
128: return ABORT;
129: if ((bp = dired_(dirname)) == NULL)
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;
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.7 mickey 142: char dirname[NFILEN];
143: BUFFER *bp;
144: MGWIN *wp;
1.5 millert 145:
146: dirname[0] = '\0';
1.12 vincent 147: if (eread("Dired other window: ", dirname, NFILEN, EFNEW | EFCR)
148: == ABORT)
1.5 millert 149: return ABORT;
150: if ((bp = dired_(dirname)) == NULL)
151: return FALSE;
152: if ((wp = popbuf(bp)) == NULL)
153: return FALSE;
154: curbp = bp;
155: curwp = wp;
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)
164: return FALSE;
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;
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)
181: return d_undelbak(f, -n);
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;
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)
198: return d_undel(f, -n);
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;
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.5 millert 214: BUFFER *bp;
1.7 mickey 215: int s;
216: char fname[NFILEN];
1.5 millert 217:
1.8 vincent 218: if ((s = d_makename(curwp->w_dotp, fname, sizeof fname)) == ABORT)
1.5 millert 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.5 millert 225: return FALSE;
226: curbp = bp;
227: if (showbuffer(bp, curwp, WFHARD) != TRUE)
228: return FALSE;
229: if (bp->b_fname[0] != 0)
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.8 vincent 243: if ((s = d_makename(curwp->w_dotp, fname, sizeof fname)) == ABORT)
1.5 millert 244: return FALSE;
245: if ((bp = (s ? dired_(fname) : findbuffer(fname))) == NULL)
246: return FALSE;
247: if ((wp = popbuf(bp)) == NULL)
248: return FALSE;
249: curbp = bp;
250: curwp = wp;
251: if (bp->b_fname[0] != 0)
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;
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.8 vincent 266: switch (d_makename(lp, fname, sizeof fname)) {
1.5 millert 267: case ABORT:
268: ewprintf("Bad line in dired buffer");
269: return FALSE;
270: case FALSE:
271: if (unlink(fname) < 0) {
1.12 vincent 272: ewprintf("Could not delete '%s'",
273: basename(fname));
1.5 millert 274: return FALSE;
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.5 millert 281: return FALSE;
282: }
283: break;
284: }
285: lfree(lp);
286: curwp->w_flag |= WFHARD;
287: }
1.1 deraadt 288: }
1.5 millert 289: return TRUE;
1.1 deraadt 290: }
291:
1.12 vincent 292:
1.5 millert 293: /* ARGSUSED */
294: int
1.10 vincent 295: d_copy(int f, int n)
1.1 deraadt 296: {
1.7 mickey 297: char frname[NFILEN], toname[NFILEN];
1.12 vincent 298: int stat, off;
299: BUFFER *bp;
1.1 deraadt 300:
1.8 vincent 301: if (d_makename(curwp->w_dotp, frname, sizeof frname) != FALSE) {
1.5 millert 302: ewprintf("Not a file");
303: return FALSE;
304: }
1.12 vincent 305: off = strlcpy(toname, curbp->b_fname, sizeof toname);
306: if (off >= sizeof toname - 1) { /* can't happen, really */
307: ewprintf("too long directory name");
308: return (FALSE);
309: }
310: if ((stat = eread("Copy %s to: ", toname + off, sizeof toname - off,
311: EFNEW | EFCR, basename(frname))) != TRUE)
312: return (stat);
313: stat = (copy(frname, toname) >= 0) ? TRUE : FALSE;
314: if (stat != TRUE)
315: return (stat);
316: bp = dired_(curbp->b_fname);
317: return (showbuffer(bp, curwp, WFHARD | WFMODE));
1.1 deraadt 318: }
319:
1.5 millert 320: /* ARGSUSED */
321: int
1.10 vincent 322: d_rename(int f, int n)
1.1 deraadt 323: {
1.5 millert 324: char frname[NFILEN], toname[NFILEN];
1.12 vincent 325: int stat, off;
326: BUFFER *bp;
1.1 deraadt 327:
1.8 vincent 328: if (d_makename(curwp->w_dotp, frname, sizeof frname) != FALSE) {
1.5 millert 329: ewprintf("Not a file");
330: return FALSE;
331: }
1.12 vincent 332: off = strlcpy(toname, curbp->b_fname, sizeof toname);
333: if (off >= sizeof toname - 1) { /* can't happen, really */
334: ewprintf("too long directory name");
335: return (FALSE);
336: }
337: if ((stat = eread("Rename %s to: ", toname + off,
338: sizeof toname - off, EFNEW | EFCR, basename(frname))) != TRUE)
1.5 millert 339: return stat;
1.12 vincent 340: stat = (rename(frname, toname) >= 0) ? TRUE : FALSE;
341: if (stat != TRUE)
342: return (stat);
343: bp = dired_(curbp->b_fname);
344: return (showbuffer(bp, curwp, WFHARD | WFMODE));
1.1 deraadt 345: }
346: #endif
1.12 vincent 347:
348: void
349: reaper(int signo __attribute__((unused)))
350: {
351: pid_t ret;
352: int status;
353:
354: while ((ret = waitpid(-1, &status, WNOHANG)) >= 0)
355: ;
356: }
357:
358: /*
359: * Pipe the currently selected file through a shell command.
360: */
361: int
362: d_shell_command(int f, int n)
363: {
364: char command[512], fname[MAXPATHLEN], buf[BUFSIZ], *cp;
365: int infd, fds[2];
366: pid_t pid;
367: struct sigaction olda, newa;
368: BUFFER *bp;
369: MGWIN *wp;
370: FILE *fin;
371:
372: bp = bfind("*Shell Command Output*", TRUE);
373: if (bclear(bp) != TRUE)
374: return (ABORT);
375:
376: if (d_makename(curwp->w_dotp, fname, sizeof fname) != FALSE) {
377: ewprintf("bad line");
378: return (ABORT);
379: }
380:
381: command[0] = '\0';
382: if (eread("! on %s: ", command, sizeof command, 0,
383: basename(fname)) == ABORT)
384: return (ABORT);
385: infd = open(fname, O_RDONLY);
386: if (infd == -1) {
387: ewprintf("Can't open input file : %s", strerror(errno));
388: return (ABORT);
389: }
390: if (pipe(fds) == -1) {
391: ewprintf("Can't create pipe : %s", strerror(errno));
392: close(infd);
393: return (ABORT);
394: }
395:
396: newa.sa_handler = reaper;
397: newa.sa_flags = 0;
398: if (sigaction(SIGCHLD, &newa, &olda) == -1) {
399: close(infd);
400: close(fds[0]);
401: close(fds[1]);
402: return (ABORT);
403: }
404: pid = fork();
405: switch (pid) {
406: case -1:
407: ewprintf("Can't fork");
408: return (ABORT);
409: case 0:
410: close(fds[0]);
411: dup2(infd, STDIN_FILENO);
412: dup2(fds[1], STDOUT_FILENO);
413: dup2(fds[1], STDERR_FILENO);
414: execl("/bin/sh", "sh", "-c", command, (char *)NULL);
415: exit(1);
416: default:
417: close(infd);
418: close(fds[1]);
419: fin = fdopen(fds[0], "r");
420: if (fin == NULL) /* "r" is surely a valid mode! */
421: panic("can't happen");
422: while (fgets(buf, sizeof buf, fin) != NULL) {
423: cp = strrchr(buf, '\n');
424: if (cp == NULL && !feof(fin)) { /* too long a line */
425: int c;
426: addlinef(bp, "%s...", buf);
427: while ((c = getc(fin)) != EOF && c != '\n')
428: ;
429: continue;
430: } else if (cp)
431: *cp = '\0';
432: addline(bp, buf);
433: }
434: fclose(fin);
435: close(fds[0]);
436: break;
437: }
438: wp = popbuf(bp);
439: if (wp == NULL)
440: return (ABORT); /* XXX - free the buffer?? */
441: curwp = wp;
442: curbp = wp->w_bufp;
443: if (sigaction(SIGCHLD, &olda, NULL) == -1)
444: ewprintf("Warning, couldn't reset previous signal handler");
445: return (TRUE);
446: }
447:
448: int
449: d_create_directory(int f, int n)
450: {
451: char tocreate[MAXPATHLEN], off;
452: int stat;
453: BUFFER *bp;
454:
455: off = strlcpy(tocreate, curbp->b_fname, sizeof tocreate);
456: if (off >= sizeof tocreate - 1)
457: return (FALSE);
458: if ((stat = ereply("Create directory: ", tocreate + off,
459: sizeof tocreate - off))
460: != TRUE)
461: return (stat);
462: if (mkdir(tocreate, 0755) == -1) {
463: ewprintf("Creating directory: %s, %s", strerror(errno),
464: tocreate);
465: return (ABORT);
466: }
467: bp = dired_(curbp->b_fname);
468: return (showbuffer(bp, curwp, WFHARD | WFMODE));
469: }