| File: | src/usr.bin/mg/dired.c |
| Warning: | line 1171, column 12 2nd function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: dired.c,v 1.100 2021/05/02 14:13:17 lum Exp $ */ | |||
| 2 | ||||
| 3 | /* This file is in the public domain. */ | |||
| 4 | ||||
| 5 | /* dired module for mg 2a | |||
| 6 | * by Robert A. Larson | |||
| 7 | */ | |||
| 8 | ||||
| 9 | #include <sys/queue.h> | |||
| 10 | #include <sys/resource.h> | |||
| 11 | #include <sys/stat.h> | |||
| 12 | #include <sys/time.h> | |||
| 13 | #include <sys/types.h> | |||
| 14 | #include <sys/wait.h> | |||
| 15 | #include <ctype.h> | |||
| 16 | #include <err.h> | |||
| 17 | #include <errno(*__errno()).h> | |||
| 18 | #include <fcntl.h> | |||
| 19 | #include <limits.h> | |||
| 20 | #include <signal.h> | |||
| 21 | #include <stdarg.h> | |||
| 22 | #include <stdio.h> | |||
| 23 | #include <stdlib.h> | |||
| 24 | #include <string.h> | |||
| 25 | #include <unistd.h> | |||
| 26 | ||||
| 27 | #include "def.h" | |||
| 28 | #include "funmap.h" | |||
| 29 | #include "kbd.h" | |||
| 30 | ||||
| 31 | void dired_init(void); | |||
| 32 | static int dired(int, int); | |||
| 33 | static int d_otherwindow(int, int); | |||
| 34 | static int d_undel(int, int); | |||
| 35 | static int d_undelbak(int, int); | |||
| 36 | static int d_findfile(int, int); | |||
| 37 | static int d_ffotherwindow(int, int); | |||
| 38 | static int d_expunge(int, int); | |||
| 39 | static int d_copy(int, int); | |||
| 40 | static int d_del(int, int); | |||
| 41 | static int d_rename(int, int); | |||
| 42 | static int d_exec(int, struct buffer *, const char *, const char *, ...); | |||
| 43 | static int d_shell_command(int, int); | |||
| 44 | static int d_create_directory(int, int); | |||
| 45 | static int d_makename(struct line *, char *, size_t); | |||
| 46 | static int d_warpdot(struct line *, int *); | |||
| 47 | static int d_forwpage(int, int); | |||
| 48 | static int d_backpage(int, int); | |||
| 49 | static int d_forwline(int, int); | |||
| 50 | static int d_backline(int, int); | |||
| 51 | static int d_killbuffer_cmd(int, int); | |||
| 52 | static int d_refreshbuffer(int, int); | |||
| 53 | static int d_filevisitalt(int, int); | |||
| 54 | static int d_gotofile(int, int); | |||
| 55 | static void reaper(int); | |||
| 56 | static int gotofile(char*); | |||
| 57 | static struct buffer *refreshbuffer(struct buffer *); | |||
| 58 | static int createlist(struct buffer *); | |||
| 59 | static void redelete(struct buffer *); | |||
| 60 | static char *findfname(struct line *, char *); | |||
| 61 | ||||
| 62 | extern struct keymap_s helpmap, cXmap, metamap; | |||
| 63 | ||||
| 64 | const char DDELCHAR = 'D'; | |||
| 65 | ||||
| 66 | /* | |||
| 67 | * Structure which holds a linked list of file names marked for | |||
| 68 | * deletion. Used to maintain dired buffer 'state' between refreshes. | |||
| 69 | */ | |||
| 70 | struct delentry { | |||
| 71 | SLIST_ENTRY(delentry)struct { struct delentry *sle_next; } entry; | |||
| 72 | char *fn; | |||
| 73 | }; | |||
| 74 | SLIST_HEAD(slisthead, delentry)struct slisthead { struct delentry *slh_first; } delhead = SLIST_HEAD_INITIALIZER(delhead){ ((void *)0) }; | |||
| 75 | ||||
| 76 | static PF dirednul[] = { | |||
| 77 | setmark, /* ^@ */ | |||
| 78 | gotobol, /* ^A */ | |||
| 79 | backchar, /* ^B */ | |||
| 80 | rescan, /* ^C */ | |||
| 81 | d_del, /* ^D */ | |||
| 82 | gotoeol, /* ^E */ | |||
| 83 | forwchar, /* ^F */ | |||
| 84 | ctrlg, /* ^G */ | |||
| 85 | NULL((void *)0), /* ^H */ | |||
| 86 | }; | |||
| 87 | ||||
| 88 | static PF diredcl[] = { | |||
| 89 | reposition, /* ^L */ | |||
| 90 | d_findfile, /* ^M */ | |||
| 91 | d_forwline, /* ^N */ | |||
| 92 | rescan, /* ^O */ | |||
| 93 | d_backline, /* ^P */ | |||
| 94 | rescan, /* ^Q */ | |||
| 95 | backisearch, /* ^R */ | |||
| 96 | forwisearch, /* ^S */ | |||
| 97 | rescan, /* ^T */ | |||
| 98 | universal_argument, /* ^U */ | |||
| 99 | d_forwpage, /* ^V */ | |||
| 100 | rescan, /* ^W */ | |||
| 101 | NULL((void *)0) /* ^X */ | |||
| 102 | }; | |||
| 103 | ||||
| 104 | static PF diredcz[] = { | |||
| 105 | spawncli, /* ^Z */ | |||
| 106 | NULL((void *)0), /* esc */ | |||
| 107 | rescan, /* ^\ */ | |||
| 108 | rescan, /* ^] */ | |||
| 109 | rescan, /* ^^ */ | |||
| 110 | rescan, /* ^_ */ | |||
| 111 | d_forwline, /* SP */ | |||
| 112 | d_shell_command, /* ! */ | |||
| 113 | rescan, /* " */ | |||
| 114 | rescan, /* # */ | |||
| 115 | rescan, /* $ */ | |||
| 116 | rescan, /* % */ | |||
| 117 | rescan, /* & */ | |||
| 118 | rescan, /* ' */ | |||
| 119 | rescan, /* ( */ | |||
| 120 | rescan, /* ) */ | |||
| 121 | rescan, /* * */ | |||
| 122 | d_create_directory /* + */ | |||
| 123 | }; | |||
| 124 | ||||
| 125 | static PF direda[] = { | |||
| 126 | d_filevisitalt, /* a */ | |||
| 127 | rescan, /* b */ | |||
| 128 | d_copy, /* c */ | |||
| 129 | d_del, /* d */ | |||
| 130 | d_findfile, /* e */ | |||
| 131 | d_findfile, /* f */ | |||
| 132 | d_refreshbuffer, /* g */ | |||
| 133 | rescan, /* h */ | |||
| 134 | rescan, /* i */ | |||
| 135 | d_gotofile /* j */ | |||
| 136 | }; | |||
| 137 | ||||
| 138 | static PF diredn[] = { | |||
| 139 | d_forwline, /* n */ | |||
| 140 | d_ffotherwindow, /* o */ | |||
| 141 | d_backline, /* p */ | |||
| 142 | d_killbuffer_cmd, /* q */ | |||
| 143 | d_rename, /* r */ | |||
| 144 | rescan, /* s */ | |||
| 145 | rescan, /* t */ | |||
| 146 | d_undel, /* u */ | |||
| 147 | rescan, /* v */ | |||
| 148 | rescan, /* w */ | |||
| 149 | d_expunge /* x */ | |||
| 150 | }; | |||
| 151 | ||||
| 152 | static PF direddl[] = { | |||
| 153 | d_undelbak /* del */ | |||
| 154 | }; | |||
| 155 | ||||
| 156 | static PF diredbp[] = { | |||
| 157 | d_backpage /* v */ | |||
| 158 | }; | |||
| 159 | ||||
| 160 | static PF dirednull[] = { | |||
| 161 | NULL((void *)0) | |||
| 162 | }; | |||
| 163 | ||||
| 164 | static struct KEYMAPE (1){ short map_num; short map_max; PF map_default; struct map_element map_element[1]; } d_backpagemap = { | |||
| 165 | 1, | |||
| 166 | 1, | |||
| 167 | rescan, | |||
| 168 | { | |||
| 169 | { | |||
| 170 | 'v', 'v', diredbp, NULL((void *)0) | |||
| 171 | } | |||
| 172 | } | |||
| 173 | }; | |||
| 174 | ||||
| 175 | static struct KEYMAPE (7){ short map_num; short map_max; PF map_default; struct map_element map_element[7]; } diredmap = { | |||
| 176 | 7, | |||
| 177 | 7, | |||
| 178 | rescan, | |||
| 179 | { | |||
| 180 | { | |||
| 181 | CCHR('@')(('@') ^ 0x40), CCHR('H')(('H') ^ 0x40), dirednul, (KEYMAP *) & helpmap | |||
| 182 | }, | |||
| 183 | { | |||
| 184 | CCHR('L')(('L') ^ 0x40), CCHR('X')(('X') ^ 0x40), diredcl, (KEYMAP *) & cXmap | |||
| 185 | }, | |||
| 186 | { | |||
| 187 | CCHR('[')(('[') ^ 0x40), CCHR('[')(('[') ^ 0x40), dirednull, (KEYMAP *) & | |||
| 188 | d_backpagemap | |||
| 189 | }, | |||
| 190 | { | |||
| 191 | CCHR('Z')(('Z') ^ 0x40), '+', diredcz, (KEYMAP *) & metamap | |||
| 192 | }, | |||
| 193 | { | |||
| 194 | 'a', 'j', direda, NULL((void *)0) | |||
| 195 | }, | |||
| 196 | { | |||
| 197 | 'n', 'x', diredn, NULL((void *)0) | |||
| 198 | }, | |||
| 199 | { | |||
| 200 | CCHR('?')(('?') ^ 0x40), CCHR('?')(('?') ^ 0x40), direddl, NULL((void *)0) | |||
| 201 | }, | |||
| 202 | } | |||
| 203 | }; | |||
| 204 | ||||
| 205 | void | |||
| 206 | dired_init(void) | |||
| 207 | { | |||
| 208 | funmap_add(dired, "dired", 1); | |||
| 209 | funmap_add(d_create_directory, "dired-create-directory", 1); | |||
| 210 | funmap_add(d_copy, "dired-do-copy", 1); | |||
| 211 | funmap_add(d_expunge, "dired-do-flagged-delete", 0); | |||
| 212 | funmap_add(d_rename, "dired-do-rename", 1); | |||
| 213 | funmap_add(d_findfile, "dired-find-file", 1); | |||
| 214 | funmap_add(d_ffotherwindow, "dired-find-file-other-window", 1); | |||
| 215 | funmap_add(d_del, "dired-flag-file-deletion", 0); | |||
| 216 | funmap_add(d_gotofile, "dired-goto-file", 1); | |||
| 217 | funmap_add(d_forwline, "dired-next-line", 0); | |||
| 218 | funmap_add(d_otherwindow, "dired-other-window", 0); | |||
| 219 | funmap_add(d_backline, "dired-previous-line", 0); | |||
| 220 | funmap_add(d_refreshbuffer, "dired-revert", 0); | |||
| 221 | funmap_add(d_backpage, "dired-scroll-down", 0); | |||
| 222 | funmap_add(d_forwpage, "dired-scroll-up", 0); | |||
| 223 | funmap_add(d_shell_command, "dired-shell-command", 1); | |||
| 224 | funmap_add(d_undel, "dired-unmark", 0); | |||
| 225 | funmap_add(d_undelbak, "dired-unmark-backward", 0); | |||
| 226 | funmap_add(d_killbuffer_cmd, "quit-window", 0); | |||
| 227 | maps_add((KEYMAP *)&diredmap, "dired"); | |||
| 228 | dobindkey(fundamental_map(fundamental_mode.p_map), "dired", "^Xd"); | |||
| 229 | } | |||
| 230 | ||||
| 231 | /* ARGSUSED */ | |||
| 232 | int | |||
| 233 | dired(int f, int n) | |||
| 234 | { | |||
| 235 | char dname[NFILEN1024], *bufp, *slash; | |||
| 236 | struct buffer *bp; | |||
| 237 | ||||
| 238 | if (curbp->b_fname[0] != '\0') { | |||
| 239 | (void)strlcpy(dname, curbp->b_fname, sizeof(dname)); | |||
| 240 | if ((slash = strrchr(dname, '/')) != NULL((void *)0)) { | |||
| 241 | *(slash + 1) = '\0'; | |||
| 242 | } | |||
| 243 | } else { | |||
| 244 | if (getcwd(dname, sizeof(dname)) == NULL((void *)0)) | |||
| 245 | dname[0] = '\0'; | |||
| 246 | } | |||
| 247 | ||||
| 248 | if ((bufp = eread("Dired (directory): ", dname, NFILEN1024, | |||
| 249 | EFDEF0x0020 | EFNEW0x0008 | EFCR0x0010)) == NULL((void *)0)) | |||
| 250 | return (ABORT2); | |||
| 251 | if (bufp[0] == '\0') | |||
| 252 | return (FALSE0); | |||
| 253 | if ((bp = dired_(bufp)) == NULL((void *)0)) | |||
| 254 | return (FALSE0); | |||
| 255 | ||||
| 256 | curbp = bp; | |||
| 257 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
| 258 | } | |||
| 259 | ||||
| 260 | /* ARGSUSED */ | |||
| 261 | int | |||
| 262 | d_otherwindow(int f, int n) | |||
| 263 | { | |||
| 264 | char dname[NFILEN1024], *bufp, *slash; | |||
| 265 | struct buffer *bp; | |||
| 266 | struct mgwin *wp; | |||
| 267 | ||||
| 268 | if (curbp->b_fname[0] != '\0') { | |||
| 269 | (void)strlcpy(dname, curbp->b_fname, sizeof(dname)); | |||
| 270 | if ((slash = strrchr(dname, '/')) != NULL((void *)0)) { | |||
| 271 | *(slash + 1) = '\0'; | |||
| 272 | } | |||
| 273 | } else { | |||
| 274 | if (getcwd(dname, sizeof(dname)) == NULL((void *)0)) | |||
| 275 | dname[0] = '\0'; | |||
| 276 | } | |||
| 277 | ||||
| 278 | if ((bufp = eread("Dired other window: ", dname, NFILEN1024, | |||
| 279 | EFDEF0x0020 | EFNEW0x0008 | EFCR0x0010)) == NULL((void *)0)) | |||
| 280 | return (ABORT2); | |||
| 281 | else if (bufp[0] == '\0') | |||
| 282 | return (FALSE0); | |||
| 283 | if ((bp = dired_(bufp)) == NULL((void *)0)) | |||
| 284 | return (FALSE0); | |||
| 285 | if ((wp = popbuf(bp, WNONE0x00)) == NULL((void *)0)) | |||
| 286 | return (FALSE0); | |||
| 287 | curbp = bp; | |||
| 288 | curwp = wp; | |||
| 289 | return (TRUE1); | |||
| 290 | } | |||
| 291 | ||||
| 292 | /* ARGSUSED */ | |||
| 293 | int | |||
| 294 | d_del(int f, int n) | |||
| 295 | { | |||
| 296 | if (n < 0) | |||
| 297 | return (FALSE0); | |||
| 298 | while (n--) { | |||
| 299 | if (d_warpdot(curwp->w_dotp, &curwp->w_doto) == TRUE1) { | |||
| 300 | lputc(curwp->w_dotp, 0, DDELCHAR)((curwp->w_dotp)->l_text[(0)]=(DDELCHAR)); | |||
| 301 | curbp->b_flag |= BFDIREDDEL0x80; | |||
| 302 | } | |||
| 303 | if (lforw(curwp->w_dotp)((curwp->w_dotp)->l_fp) != curbp->b_headp) { | |||
| 304 | curwp->w_dotp = lforw(curwp->w_dotp)((curwp->w_dotp)->l_fp); | |||
| 305 | curwp->w_dotline++; | |||
| 306 | } | |||
| 307 | } | |||
| 308 | curwp->w_rflag |= WFEDIT0x04 | WFMOVE0x02; | |||
| 309 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
| 310 | } | |||
| 311 | ||||
| 312 | /* ARGSUSED */ | |||
| 313 | int | |||
| 314 | d_undel(int f, int n) | |||
| 315 | { | |||
| 316 | if (n < 0) | |||
| 317 | return (d_undelbak(f, -n)); | |||
| 318 | while (n--) { | |||
| 319 | if (llength(curwp->w_dotp)((curwp->w_dotp)->l_used) > 0) | |||
| 320 | lputc(curwp->w_dotp, 0, ' ')((curwp->w_dotp)->l_text[(0)]=(' ')); | |||
| 321 | if (lforw(curwp->w_dotp)((curwp->w_dotp)->l_fp) != curbp->b_headp) { | |||
| 322 | curwp->w_dotp = lforw(curwp->w_dotp)((curwp->w_dotp)->l_fp); | |||
| 323 | curwp->w_dotline++; | |||
| 324 | } | |||
| 325 | } | |||
| 326 | curwp->w_rflag |= WFEDIT0x04 | WFMOVE0x02; | |||
| 327 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
| 328 | } | |||
| 329 | ||||
| 330 | /* ARGSUSED */ | |||
| 331 | int | |||
| 332 | d_undelbak(int f, int n) | |||
| 333 | { | |||
| 334 | if (n < 0) | |||
| 335 | return (d_undel(f, -n)); | |||
| 336 | while (n--) { | |||
| 337 | if (lback(curwp->w_dotp)((curwp->w_dotp)->l_bp) != curbp->b_headp) { | |||
| 338 | curwp->w_dotp = lback(curwp->w_dotp)((curwp->w_dotp)->l_bp); | |||
| 339 | curwp->w_dotline--; | |||
| 340 | } | |||
| 341 | if (llength(curwp->w_dotp)((curwp->w_dotp)->l_used) > 0) | |||
| 342 | lputc(curwp->w_dotp, 0, ' ')((curwp->w_dotp)->l_text[(0)]=(' ')); | |||
| 343 | } | |||
| 344 | curwp->w_rflag |= WFEDIT0x04 | WFMOVE0x02; | |||
| 345 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
| 346 | } | |||
| 347 | ||||
| 348 | /* ARGSUSED */ | |||
| 349 | int | |||
| 350 | d_findfile(int f, int n) | |||
| 351 | { | |||
| 352 | struct buffer *bp; | |||
| 353 | int s; | |||
| 354 | char fname[NFILEN1024]; | |||
| 355 | ||||
| 356 | if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT2) | |||
| 357 | return (FALSE0); | |||
| 358 | if (s == TRUE1) | |||
| 359 | bp = dired_(fname); | |||
| 360 | else | |||
| 361 | bp = findbuffer(fname); | |||
| 362 | if (bp == NULL((void *)0)) | |||
| 363 | return (FALSE0); | |||
| 364 | curbp = bp; | |||
| 365 | if (showbuffer(bp, curwp, WFFULL0x08) != TRUE1) | |||
| 366 | return (FALSE0); | |||
| 367 | if (bp->b_fname[0] != 0) | |||
| 368 | return (TRUE1); | |||
| 369 | return (readin(fname)); | |||
| 370 | } | |||
| 371 | ||||
| 372 | /* ARGSUSED */ | |||
| 373 | int | |||
| 374 | d_ffotherwindow(int f, int n) | |||
| 375 | { | |||
| 376 | char fname[NFILEN1024]; | |||
| 377 | int s; | |||
| 378 | struct buffer *bp; | |||
| 379 | struct mgwin *wp; | |||
| 380 | ||||
| 381 | if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT2) | |||
| 382 | return (FALSE0); | |||
| 383 | if ((bp = (s ? dired_(fname) : findbuffer(fname))) == NULL((void *)0)) | |||
| 384 | return (FALSE0); | |||
| 385 | if ((wp = popbuf(bp, WNONE0x00)) == NULL((void *)0)) | |||
| 386 | return (FALSE0); | |||
| 387 | curbp = bp; | |||
| 388 | curwp = wp; | |||
| 389 | if (bp->b_fname[0] != 0) | |||
| 390 | return (TRUE1); /* never true for dired buffers */ | |||
| 391 | return (readin(fname)); | |||
| 392 | } | |||
| 393 | ||||
| 394 | /* ARGSUSED */ | |||
| 395 | int | |||
| 396 | d_expunge(int f, int n) | |||
| 397 | { | |||
| 398 | struct line *lp, *nlp; | |||
| 399 | char fname[NFILEN1024], sname[NFILEN1024]; | |||
| 400 | int tmp; | |||
| 401 | ||||
| 402 | tmp = curwp->w_dotline; | |||
| 403 | curwp->w_dotline = 0; | |||
| 404 | ||||
| 405 | for (lp = bfirstlp(curbp)((((curbp)->b_headp)->l_fp)); lp != curbp->b_headp; lp = nlp) { | |||
| 406 | curwp->w_dotline++; | |||
| 407 | nlp = lforw(lp)((lp)->l_fp); | |||
| 408 | if (llength(lp)((lp)->l_used) && lgetc(lp, 0)(((unsigned char) ((lp)->l_text[(0)]))) == 'D') { | |||
| 409 | switch (d_makename(lp, fname, sizeof(fname))) { | |||
| 410 | case ABORT2: | |||
| 411 | dobeep(); | |||
| 412 | ewprintf("Bad line in dired buffer"); | |||
| 413 | curwp->w_dotline = tmp; | |||
| 414 | return (FALSE0); | |||
| 415 | case FALSE0: | |||
| 416 | if (unlink(fname) == -1) { | |||
| 417 | (void)xbasename(sname, fname, NFILEN1024); | |||
| 418 | dobeep(); | |||
| 419 | ewprintf("Could not delete '%s'", sname); | |||
| 420 | curwp->w_dotline = tmp; | |||
| 421 | return (FALSE0); | |||
| 422 | } | |||
| 423 | break; | |||
| 424 | case TRUE1: | |||
| 425 | if (rmdir(fname) == -1) { | |||
| 426 | (void)xbasename(sname, fname, NFILEN1024); | |||
| 427 | dobeep(); | |||
| 428 | ewprintf("Could not delete directory " | |||
| 429 | "'%s'", sname); | |||
| 430 | curwp->w_dotline = tmp; | |||
| 431 | return (FALSE0); | |||
| 432 | } | |||
| 433 | break; | |||
| 434 | } | |||
| 435 | lfree(lp); | |||
| 436 | curwp->w_bufp->b_lines--; | |||
| 437 | if (tmp > curwp->w_dotline) | |||
| 438 | tmp--; | |||
| 439 | curwp->w_rflag |= WFFULL0x08; | |||
| 440 | } | |||
| 441 | } | |||
| 442 | curwp->w_dotline = tmp; | |||
| 443 | d_warpdot(curwp->w_dotp, &curwp->w_doto); | |||
| 444 | ||||
| 445 | /* we have deleted all items successfully, remove del flag */ | |||
| 446 | curbp->b_flag &= ~BFDIREDDEL0x80; | |||
| 447 | ||||
| 448 | return (TRUE1); | |||
| 449 | } | |||
| 450 | ||||
| 451 | /* ARGSUSED */ | |||
| 452 | int | |||
| 453 | d_copy(int f, int n) | |||
| 454 | { | |||
| 455 | struct stat statbuf; | |||
| 456 | char frname[NFILEN1024], toname[NFILEN1024], sname[NFILEN1024]; | |||
| 457 | char *topath, *bufp; | |||
| 458 | int ret; | |||
| 459 | size_t off; | |||
| 460 | struct buffer *bp; | |||
| 461 | ||||
| 462 | if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE0) { | |||
| 463 | dobeep(); | |||
| 464 | ewprintf("Not a file"); | |||
| 465 | return (FALSE0); | |||
| 466 | } | |||
| 467 | off = strlcpy(toname, curbp->b_fname, sizeof(toname)); | |||
| 468 | if (off >= sizeof(toname) - 1) { /* can't happen, really */ | |||
| 469 | dobeep(); | |||
| 470 | ewprintf("Directory name too long"); | |||
| 471 | return (FALSE0); | |||
| 472 | } | |||
| 473 | (void)xbasename(sname, frname, NFILEN1024); | |||
| 474 | bufp = eread("Copy %s to: ", toname, sizeof(toname), | |||
| 475 | EFDEF0x0020 | EFNEW0x0008 | EFCR0x0010, sname); | |||
| 476 | if (bufp == NULL((void *)0)) | |||
| 477 | return (ABORT2); | |||
| 478 | else if (bufp[0] == '\0') | |||
| 479 | return (FALSE0); | |||
| 480 | ||||
| 481 | topath = adjustname(toname, TRUE1); | |||
| 482 | if (stat(topath, &statbuf) == 0) { | |||
| 483 | if (S_ISDIR(statbuf.st_mode)((statbuf.st_mode & 0170000) == 0040000)) { | |||
| 484 | ret = snprintf(toname, sizeof(toname), "%s/%s", | |||
| 485 | topath, sname); | |||
| 486 | if (ret < 0 || ret >= sizeof(toname) - 1) { | |||
| 487 | dobeep(); | |||
| 488 | ewprintf("Directory name too long"); | |||
| 489 | return (FALSE0); | |||
| 490 | } | |||
| 491 | topath = adjustname(toname, TRUE1); | |||
| 492 | } | |||
| 493 | } | |||
| 494 | if (topath == NULL((void *)0)) | |||
| 495 | return (FALSE0); | |||
| 496 | if (strcmp(frname, topath) == 0) { | |||
| 497 | ewprintf("Cannot copy to same file: %s", frname); | |||
| 498 | return (TRUE1); | |||
| 499 | } | |||
| 500 | ret = (copy(frname, topath) >= 0) ? TRUE1 : FALSE0; | |||
| 501 | if (ret != TRUE1) | |||
| 502 | return (ret); | |||
| 503 | if ((bp = refreshbuffer(curbp)) == NULL((void *)0)) | |||
| 504 | return (FALSE0); | |||
| 505 | ||||
| 506 | ewprintf("Copy: 1 file"); | |||
| 507 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
| 508 | } | |||
| 509 | ||||
| 510 | /* ARGSUSED */ | |||
| 511 | int | |||
| 512 | d_rename(int f, int n) | |||
| 513 | { | |||
| 514 | struct stat statbuf; | |||
| 515 | char frname[NFILEN1024], toname[NFILEN1024]; | |||
| 516 | char *topath, *bufp; | |||
| 517 | int ret; | |||
| 518 | size_t off; | |||
| 519 | struct buffer *bp; | |||
| 520 | char sname[NFILEN1024]; | |||
| 521 | ||||
| 522 | if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE0) { | |||
| 523 | dobeep(); | |||
| 524 | ewprintf("Not a file"); | |||
| 525 | return (FALSE0); | |||
| 526 | } | |||
| 527 | off = strlcpy(toname, curbp->b_fname, sizeof(toname)); | |||
| 528 | if (off >= sizeof(toname) - 1) { /* can't happen, really */ | |||
| 529 | dobeep(); | |||
| 530 | ewprintf("Name too long"); | |||
| 531 | return (FALSE0); | |||
| 532 | } | |||
| 533 | (void)xbasename(sname, frname, NFILEN1024); | |||
| 534 | bufp = eread("Rename %s to: ", toname, | |||
| 535 | sizeof(toname), EFDEF0x0020 | EFNEW0x0008 | EFCR0x0010, sname); | |||
| 536 | if (bufp == NULL((void *)0)) | |||
| 537 | return (ABORT2); | |||
| 538 | else if (bufp[0] == '\0') | |||
| 539 | return (FALSE0); | |||
| 540 | ||||
| 541 | topath = adjustname(toname, TRUE1); | |||
| 542 | if (stat(topath, &statbuf) == 0) { | |||
| 543 | if (S_ISDIR(statbuf.st_mode)((statbuf.st_mode & 0170000) == 0040000)) { | |||
| 544 | ret = snprintf(toname, sizeof(toname), "%s/%s", | |||
| 545 | topath, sname); | |||
| 546 | if (ret < 0 || ret >= sizeof(toname) - 1) { | |||
| 547 | dobeep(); | |||
| 548 | ewprintf("Directory name too long"); | |||
| 549 | return (FALSE0); | |||
| 550 | } | |||
| 551 | topath = adjustname(toname, TRUE1); | |||
| 552 | } | |||
| 553 | } | |||
| 554 | if (topath == NULL((void *)0)) | |||
| 555 | return (FALSE0); | |||
| 556 | if (strcmp(frname, topath) == 0) { | |||
| 557 | ewprintf("Cannot move to same file: %s", frname); | |||
| 558 | return (TRUE1); | |||
| 559 | } | |||
| 560 | ret = (rename(frname, topath) >= 0) ? TRUE1 : FALSE0; | |||
| 561 | if (ret != TRUE1) | |||
| 562 | return (ret); | |||
| 563 | if ((bp = refreshbuffer(curbp)) == NULL((void *)0)) | |||
| 564 | return (FALSE0); | |||
| 565 | ||||
| 566 | ewprintf("Move: 1 file"); | |||
| 567 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
| 568 | } | |||
| 569 | ||||
| 570 | /* ARGSUSED */ | |||
| 571 | void | |||
| 572 | reaper(int signo __attribute__((unused))) | |||
| 573 | { | |||
| 574 | int save_errno = errno(*__errno()), status; | |||
| 575 | ||||
| 576 | while (waitpid(-1, &status, WNOHANG1) >= 0) | |||
| 577 | ; | |||
| 578 | errno(*__errno()) = save_errno; | |||
| 579 | } | |||
| 580 | ||||
| 581 | /* | |||
| 582 | * Pipe the currently selected file through a shell command. | |||
| 583 | */ | |||
| 584 | /* ARGSUSED */ | |||
| 585 | int | |||
| 586 | d_shell_command(int f, int n) | |||
| 587 | { | |||
| 588 | char command[512], fname[PATH_MAX1024], *bufp; | |||
| 589 | struct buffer *bp; | |||
| 590 | struct mgwin *wp; | |||
| 591 | char sname[NFILEN1024]; | |||
| 592 | ||||
| 593 | bp = bfind("*Shell Command Output*", TRUE1); | |||
| 594 | if (bclear(bp) != TRUE1) | |||
| 595 | return (ABORT2); | |||
| 596 | ||||
| 597 | if (d_makename(curwp->w_dotp, fname, sizeof(fname)) != FALSE0) { | |||
| 598 | dobeep(); | |||
| 599 | ewprintf("bad line"); | |||
| 600 | return (ABORT2); | |||
| 601 | } | |||
| 602 | ||||
| 603 | command[0] = '\0'; | |||
| 604 | (void)xbasename(sname, fname, NFILEN1024); | |||
| 605 | bufp = eread("! on %s: ", command, sizeof(command), EFNEW0x0008, sname); | |||
| 606 | if (bufp == NULL((void *)0)) | |||
| 607 | return (ABORT2); | |||
| 608 | ||||
| 609 | if (d_exec(0, bp, fname, "sh", "-c", command, NULL((void *)0)) != TRUE1) | |||
| 610 | return (ABORT2); | |||
| 611 | ||||
| 612 | if ((wp = popbuf(bp, WNONE0x00)) == NULL((void *)0)) | |||
| 613 | return (ABORT2); /* XXX - free the buffer?? */ | |||
| 614 | curwp = wp; | |||
| 615 | curbp = wp->w_bufp; | |||
| 616 | return (TRUE1); | |||
| 617 | } | |||
| 618 | ||||
| 619 | /* | |||
| 620 | * Pipe input file to cmd and insert the command's output in the | |||
| 621 | * given buffer. Each line will be prefixed with the given | |||
| 622 | * number of spaces. | |||
| 623 | */ | |||
| 624 | static int | |||
| 625 | d_exec(int space, struct buffer *bp, const char *input, const char *cmd, ...) | |||
| 626 | { | |||
| 627 | char buf[BUFSIZ1024]; | |||
| 628 | va_list ap; | |||
| 629 | struct sigaction olda, newa; | |||
| 630 | char **argv = NULL((void *)0), *cp; | |||
| 631 | FILE *fin; | |||
| 632 | int fds[2] = { -1, -1 }; | |||
| 633 | int infd = -1; | |||
| 634 | int ret = (ABORT2), n; | |||
| 635 | pid_t pid; | |||
| 636 | ||||
| 637 | if (sigaction(SIGCHLD20, NULL((void *)0), &olda) == -1) | |||
| 638 | return (ABORT2); | |||
| 639 | ||||
| 640 | /* Find the number of arguments. */ | |||
| 641 | va_start(ap, cmd)__builtin_va_start(ap, cmd); | |||
| 642 | for (n = 2; va_arg(ap, char *)__builtin_va_arg(ap, char *) != NULL((void *)0); n++) | |||
| 643 | ; | |||
| 644 | va_end(ap)__builtin_va_end(ap); | |||
| 645 | ||||
| 646 | /* Allocate and build the argv. */ | |||
| 647 | if ((argv = calloc(n, sizeof(*argv))) == NULL((void *)0)) { | |||
| 648 | dobeep(); | |||
| 649 | ewprintf("Can't allocate argv : %s", strerror(errno(*__errno()))); | |||
| 650 | goto out; | |||
| 651 | } | |||
| 652 | ||||
| 653 | n = 1; | |||
| 654 | argv[0] = (char *)cmd; | |||
| 655 | va_start(ap, cmd)__builtin_va_start(ap, cmd); | |||
| 656 | while ((argv[n] = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void *)0)) | |||
| 657 | n++; | |||
| 658 | va_end(ap)__builtin_va_end(ap); | |||
| 659 | ||||
| 660 | if (input == NULL((void *)0)) | |||
| 661 | input = "/dev/null"; | |||
| 662 | ||||
| 663 | if ((infd = open(input, O_RDONLY0x0000)) == -1) { | |||
| 664 | dobeep(); | |||
| 665 | ewprintf("Can't open input file : %s", strerror(errno(*__errno()))); | |||
| 666 | goto out; | |||
| 667 | } | |||
| 668 | ||||
| 669 | if (pipe(fds) == -1) { | |||
| 670 | dobeep(); | |||
| 671 | ewprintf("Can't create pipe : %s", strerror(errno(*__errno()))); | |||
| 672 | goto out; | |||
| 673 | } | |||
| 674 | ||||
| 675 | newa.sa_handler__sigaction_u.__sa_handler = reaper; | |||
| 676 | newa.sa_flags = 0; | |||
| 677 | if (sigaction(SIGCHLD20, &newa, NULL((void *)0)) == -1) | |||
| 678 | goto out; | |||
| 679 | ||||
| 680 | if ((pid = fork()) == -1) { | |||
| 681 | dobeep(); | |||
| 682 | ewprintf("Can't fork"); | |||
| 683 | goto out; | |||
| 684 | } | |||
| 685 | ||||
| 686 | switch (pid) { | |||
| 687 | case 0: /* Child */ | |||
| 688 | close(fds[0]); | |||
| 689 | dup2(infd, STDIN_FILENO0); | |||
| 690 | dup2(fds[1], STDOUT_FILENO1); | |||
| 691 | dup2(fds[1], STDERR_FILENO2); | |||
| 692 | if (execvp(argv[0], argv) == -1) | |||
| 693 | ewprintf("Can't exec %s: %s", argv[0], strerror(errno(*__errno()))); | |||
| 694 | exit(1); | |||
| 695 | break; | |||
| 696 | default: /* Parent */ | |||
| 697 | close(infd); | |||
| 698 | close(fds[1]); | |||
| 699 | infd = fds[1] = -1; | |||
| 700 | if ((fin = fdopen(fds[0], "r")) == NULL((void *)0)) | |||
| 701 | goto out; | |||
| 702 | while (fgets(buf, sizeof(buf), fin) != NULL((void *)0)) { | |||
| 703 | cp = strrchr(buf, *bp->b_nlchr); | |||
| 704 | if (cp == NULL((void *)0) && !feof(fin)(!__isthreaded ? (((fin)->_flags & 0x0020) != 0) : (feof )(fin))) { /* too long a line */ | |||
| 705 | int c; | |||
| 706 | addlinef(bp, "%*s%s...", space, "", buf); | |||
| 707 | while ((c = getc(fin)(!__isthreaded ? (--(fin)->_r < 0 ? __srget(fin) : (int )(*(fin)->_p++)) : (getc)(fin))) != EOF(-1) && | |||
| 708 | c != *bp->b_nlchr) | |||
| 709 | ; | |||
| 710 | continue; | |||
| 711 | } else if (cp) | |||
| 712 | *cp = '\0'; | |||
| 713 | addlinef(bp, "%*s%s", space, "", buf); | |||
| 714 | } | |||
| 715 | fclose(fin); | |||
| 716 | break; | |||
| 717 | } | |||
| 718 | ret = (TRUE1); | |||
| 719 | ||||
| 720 | out: | |||
| 721 | if (sigaction(SIGCHLD20, &olda, NULL((void *)0)) == -1) | |||
| 722 | ewprintf("Warning, couldn't reset previous signal handler"); | |||
| 723 | if (fds[0] != -1) | |||
| 724 | close(fds[0]); | |||
| 725 | if (fds[1] != -1) | |||
| 726 | close(fds[1]); | |||
| 727 | if (infd != -1) | |||
| 728 | close(infd); | |||
| 729 | free(argv); | |||
| 730 | return ret; | |||
| 731 | } | |||
| 732 | ||||
| 733 | /* ARGSUSED */ | |||
| 734 | int | |||
| 735 | d_create_directory(int f, int n) | |||
| 736 | { | |||
| 737 | int ret; | |||
| 738 | struct buffer *bp; | |||
| 739 | ||||
| 740 | ret = ask_makedir(); | |||
| 741 | if (ret != TRUE1) | |||
| 742 | return(ret); | |||
| 743 | ||||
| 744 | if ((bp = refreshbuffer(curbp)) == NULL((void *)0)) | |||
| 745 | return (FALSE0); | |||
| 746 | ||||
| 747 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
| 748 | } | |||
| 749 | ||||
| 750 | /* ARGSUSED */ | |||
| 751 | int | |||
| 752 | d_killbuffer_cmd(int f, int n) | |||
| 753 | { | |||
| 754 | return(killbuffer_cmd(FFRAND8, 0)); | |||
| 755 | } | |||
| 756 | ||||
| 757 | int | |||
| 758 | d_refreshbuffer(int f, int n) | |||
| 759 | { | |||
| 760 | struct buffer *bp; | |||
| 761 | ||||
| 762 | if ((bp = refreshbuffer(curbp)) == NULL((void *)0)) | |||
| 763 | return (FALSE0); | |||
| 764 | ||||
| 765 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
| 766 | } | |||
| 767 | ||||
| 768 | /* | |||
| 769 | * Kill then re-open the requested dired buffer. | |||
| 770 | * If required, take a note of any files marked for deletion. Then once | |||
| 771 | * the buffer has been re-opened, remark the same files as deleted. | |||
| 772 | */ | |||
| 773 | struct buffer * | |||
| 774 | refreshbuffer(struct buffer *bp) | |||
| 775 | { | |||
| 776 | char *tmp_b_fname; | |||
| 777 | int i, tmp_w_dotline, ddel = 0; | |||
| 778 | ||||
| 779 | /* remember directory path to open later */ | |||
| 780 | tmp_b_fname = strdup(bp->b_fname); | |||
| 781 | if (tmp_b_fname == NULL((void *)0)) { | |||
| 782 | dobeep(); | |||
| 783 | ewprintf("Out of memory"); | |||
| 784 | return (NULL((void *)0)); | |||
| 785 | } | |||
| 786 | tmp_w_dotline = curwp->w_dotline; | |||
| 787 | ||||
| 788 | /* create a list of files for deletion */ | |||
| 789 | if (bp->b_flag & BFDIREDDEL0x80) | |||
| 790 | ddel = createlist(bp); | |||
| 791 | ||||
| 792 | killbuffer(bp); | |||
| 793 | ||||
| 794 | /* dired_() uses findbuffer() to create new buffer */ | |||
| 795 | if ((bp = dired_(tmp_b_fname)) == NULL((void *)0)) { | |||
| 796 | free(tmp_b_fname); | |||
| 797 | return (NULL((void *)0)); | |||
| 798 | } | |||
| 799 | free(tmp_b_fname); | |||
| 800 | ||||
| 801 | /* remark any previously deleted files with a 'D' */ | |||
| 802 | if (ddel) | |||
| 803 | redelete(bp); | |||
| 804 | ||||
| 805 | /* find dot line */ | |||
| 806 | bp->b_dotp = bfirstlp(bp)((((bp)->b_headp)->l_fp)); | |||
| 807 | if (tmp_w_dotline > bp->b_lines) | |||
| 808 | tmp_w_dotline = bp->b_lines - 1; | |||
| 809 | for (i = 1; i < tmp_w_dotline; i++) | |||
| 810 | bp->b_dotp = lforw(bp->b_dotp)((bp->b_dotp)->l_fp); | |||
| 811 | ||||
| 812 | bp->b_dotline = i; | |||
| 813 | bp->b_doto = 0; | |||
| 814 | d_warpdot(bp->b_dotp, &bp->b_doto); | |||
| 815 | ||||
| 816 | curbp = bp; | |||
| 817 | ||||
| 818 | return (bp); | |||
| 819 | } | |||
| 820 | ||||
| 821 | static int | |||
| 822 | d_makename(struct line *lp, char *fn, size_t len) | |||
| 823 | { | |||
| 824 | int start, nlen, ret; | |||
| 825 | char *namep; | |||
| 826 | ||||
| 827 | if (d_warpdot(lp, &start) == FALSE0) | |||
| 828 | return (ABORT2); | |||
| 829 | namep = &lp->l_text[start]; | |||
| 830 | nlen = llength(lp)((lp)->l_used) - start; | |||
| 831 | ||||
| 832 | ret = snprintf(fn, len, "%s%.*s", curbp->b_fname, nlen, namep); | |||
| 833 | if (ret < 0 || ret >= (int)len) | |||
| 834 | return (ABORT2); /* Name is too long. */ | |||
| 835 | ||||
| 836 | /* Return TRUE if the entry is a directory. */ | |||
| 837 | return ((lgetc(lp, 2)(((unsigned char) ((lp)->l_text[(2)]))) == 'd') ? TRUE1 : FALSE0); | |||
| 838 | } | |||
| 839 | ||||
| 840 | #define NAME_FIELD9 9 | |||
| 841 | ||||
| 842 | static int | |||
| 843 | d_warpdot(struct line *dotp, int *doto) | |||
| 844 | { | |||
| 845 | char *tp = dotp->l_text; | |||
| 846 | int off = 0, field = 0, len; | |||
| 847 | ||||
| 848 | /* | |||
| 849 | * Find the byte offset to the (space-delimited) filename | |||
| 850 | * field in formatted ls output. | |||
| 851 | */ | |||
| 852 | len = llength(dotp)((dotp)->l_used); | |||
| 853 | while (off < len) { | |||
| 854 | if (tp[off++] == ' ') { | |||
| 855 | if (++field == NAME_FIELD9) { | |||
| 856 | *doto = off; | |||
| 857 | return (TRUE1); | |||
| 858 | } | |||
| 859 | /* Skip the space. */ | |||
| 860 | while (off < len && tp[off] == ' ') | |||
| 861 | off++; | |||
| 862 | } | |||
| 863 | } | |||
| 864 | /* We didn't find the field. */ | |||
| 865 | *doto = 0; | |||
| 866 | return (FALSE0); | |||
| 867 | } | |||
| 868 | ||||
| 869 | static int | |||
| 870 | d_forwpage(int f, int n) | |||
| 871 | { | |||
| 872 | forwpage(f | FFRAND8, n); | |||
| 873 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
| 874 | } | |||
| 875 | ||||
| 876 | static int | |||
| 877 | d_backpage (int f, int n) | |||
| 878 | { | |||
| 879 | backpage(f | FFRAND8, n); | |||
| 880 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
| 881 | } | |||
| 882 | ||||
| 883 | static int | |||
| 884 | d_forwline (int f, int n) | |||
| 885 | { | |||
| 886 | forwline(f | FFRAND8, n); | |||
| 887 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
| 888 | } | |||
| 889 | ||||
| 890 | static int | |||
| 891 | d_backline (int f, int n) | |||
| 892 | { | |||
| 893 | backline(f | FFRAND8, n); | |||
| 894 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
| 895 | } | |||
| 896 | ||||
| 897 | int | |||
| 898 | d_filevisitalt (int f, int n) | |||
| 899 | { | |||
| 900 | char fname[NFILEN1024]; | |||
| 901 | ||||
| 902 | if (d_makename(curwp->w_dotp, fname, sizeof(fname)) == ABORT2) | |||
| 903 | return (FALSE0); | |||
| 904 | ||||
| 905 | return(do_filevisitalt(fname)); | |||
| 906 | } | |||
| 907 | ||||
| 908 | /* | |||
| 909 | * XXX dname needs to have enough place to store an additional '/'. | |||
| 910 | */ | |||
| 911 | struct buffer * | |||
| 912 | dired_(char *dname) | |||
| 913 | { | |||
| 914 | struct buffer *bp; | |||
| 915 | int i; | |||
| 916 | size_t len; | |||
| 917 | ||||
| 918 | if ((dname = adjustname(dname, TRUE1)) == NULL((void *)0)) { | |||
| 919 | dobeep(); | |||
| 920 | ewprintf("Bad directory name"); | |||
| 921 | return (NULL((void *)0)); | |||
| 922 | } | |||
| 923 | /* this should not be done, instead adjustname() should get a flag */ | |||
| 924 | len = strlen(dname); | |||
| 925 | if (dname[len - 1] != '/') { | |||
| 926 | dname[len++] = '/'; | |||
| 927 | dname[len] = '\0'; | |||
| 928 | } | |||
| 929 | if ((access(dname, R_OK0x04 | X_OK0x01)) == -1) { | |||
| 930 | if (errno(*__errno()) == EACCES13) { | |||
| 931 | dobeep(); | |||
| 932 | ewprintf("Permission denied: %s", dname); | |||
| 933 | } else { | |||
| 934 | dobeep(); | |||
| 935 | ewprintf("Error opening: %s", dname); | |||
| 936 | } | |||
| 937 | return (NULL((void *)0)); | |||
| 938 | } | |||
| 939 | for (bp = bheadp; bp != NULL((void *)0); bp = bp->b_bufpb_list.l_p.x_bp) { | |||
| 940 | if (strcmp(bp->b_fname, dname) == 0) { | |||
| 941 | if (fchecktime(bp) != TRUE1) | |||
| 942 | ewprintf("Directory has changed on disk;" | |||
| 943 | " type g to update Dired"); | |||
| 944 | return (bp); | |||
| 945 | } | |||
| 946 | ||||
| 947 | } | |||
| 948 | bp = bfind(dname, TRUE1); | |||
| 949 | bp->b_flag |= BFREADONLY0x10 | BFIGNDIRTY0x40; | |||
| 950 | ||||
| 951 | if ((d_exec(2, bp, NULL((void *)0), "ls", "-al", dname, NULL((void *)0))) != TRUE1) | |||
| 952 | return (NULL((void *)0)); | |||
| 953 | ||||
| 954 | /* Find the line with ".." on it. */ | |||
| 955 | bp->b_dotp = bfirstlp(bp)((((bp)->b_headp)->l_fp)); | |||
| 956 | bp->b_dotline = 1; | |||
| 957 | for (i = 0; i < bp->b_lines; i++) { | |||
| 958 | bp->b_dotp = lforw(bp->b_dotp)((bp->b_dotp)->l_fp); | |||
| 959 | bp->b_dotline++; | |||
| 960 | if (d_warpdot(bp->b_dotp, &bp->b_doto) == FALSE0) | |||
| 961 | continue; | |||
| 962 | if (strcmp(ltext(bp->b_dotp)((bp->b_dotp)->l_text) + bp->b_doto, "..") == 0) | |||
| 963 | break; | |||
| 964 | } | |||
| 965 | ||||
| 966 | /* We want dot on the entry right after "..", if possible. */ | |||
| 967 | if (++i < bp->b_lines - 2) { | |||
| 968 | bp->b_dotp = lforw(bp->b_dotp)((bp->b_dotp)->l_fp); | |||
| 969 | bp->b_dotline++; | |||
| 970 | } | |||
| 971 | d_warpdot(bp->b_dotp, &bp->b_doto); | |||
| 972 | ||||
| 973 | (void)strlcpy(bp->b_fname, dname, sizeof(bp->b_fname)); | |||
| 974 | (void)strlcpy(bp->b_cwd, dname, sizeof(bp->b_cwd)); | |||
| 975 | if ((bp->b_modes[1] = name_mode("dired")) == NULL((void *)0)) { | |||
| 976 | bp->b_modes[0] = name_mode("fundamental"); | |||
| 977 | dobeep(); | |||
| 978 | ewprintf("Could not find mode dired"); | |||
| 979 | return (NULL((void *)0)); | |||
| 980 | } | |||
| 981 | (void)fupdstat(bp); | |||
| 982 | bp->b_nmodes = 1; | |||
| 983 | return (bp); | |||
| 984 | } | |||
| 985 | ||||
| 986 | /* | |||
| 987 | * Iterate through the lines of the dired buffer looking for files | |||
| 988 | * collected in the linked list made in createlist(). If a line is found | |||
| 989 | * replace 'D' as first char in a line. As lines are found, remove the | |||
| 990 | * corresponding item from the linked list. Iterate for as long as there | |||
| 991 | * are items in the linked list or until end of buffer is found. | |||
| 992 | */ | |||
| 993 | void | |||
| 994 | redelete(struct buffer *bp) | |||
| 995 | { | |||
| 996 | struct delentry *dt, *d1 = NULL((void *)0); | |||
| 997 | struct line *lp, *nlp; | |||
| 998 | char fname[NFILEN1024]; | |||
| 999 | char *p = fname; | |||
| 1000 | size_t plen, fnlen; | |||
| 1001 | int finished = 0; | |||
| 1002 | ||||
| 1003 | /* reset the deleted file buffer flag until a deleted file is found */ | |||
| 1004 | bp->b_flag &= ~BFDIREDDEL0x80; | |||
| 1005 | ||||
| 1006 | for (lp = bfirstlp(bp)((((bp)->b_headp)->l_fp)); lp != bp->b_headp; lp = nlp) { | |||
| 1007 | bp->b_dotp = lp; | |||
| 1008 | if ((p = findfname(lp, p)) == NULL((void *)0)) { | |||
| 1009 | nlp = lforw(lp)((lp)->l_fp); | |||
| 1010 | continue; | |||
| 1011 | } | |||
| 1012 | plen = strlen(p); | |||
| 1013 | SLIST_FOREACH_SAFE(d1, &delhead, entry, dt)for ((d1) = ((&delhead)->slh_first); (d1) && ( (dt) = ((d1)->entry.sle_next), 1); (d1) = (dt)) { | |||
| 1014 | fnlen = strlen(d1->fn); | |||
| 1015 | if ((plen == fnlen) && | |||
| 1016 | (strncmp(p, d1->fn, plen) == 0)) { | |||
| 1017 | lputc(bp->b_dotp, 0, DDELCHAR)((bp->b_dotp)->l_text[(0)]=(DDELCHAR)); | |||
| 1018 | bp->b_flag |= BFDIREDDEL0x80; | |||
| 1019 | SLIST_REMOVE(&delhead, d1, delentry, entry)do { if ((&delhead)->slh_first == (d1)) { do { ((& delhead))->slh_first = ((&delhead))->slh_first-> entry.sle_next; } while (0); } else { struct delentry *curelm = (&delhead)->slh_first; while (curelm->entry.sle_next != (d1)) curelm = curelm->entry.sle_next; curelm->entry .sle_next = curelm->entry.sle_next->entry.sle_next; } ; } while (0); | |||
| 1020 | if (SLIST_EMPTY(&delhead)(((&delhead)->slh_first) == ((void *)0))) { | |||
| 1021 | finished = 1; | |||
| 1022 | break; | |||
| 1023 | } | |||
| 1024 | } | |||
| 1025 | } | |||
| 1026 | if (finished) | |||
| 1027 | break; | |||
| 1028 | nlp = lforw(lp)((lp)->l_fp); | |||
| 1029 | } | |||
| 1030 | while (!SLIST_EMPTY(&delhead)(((&delhead)->slh_first) == ((void *)0))) { | |||
| 1031 | d1 = SLIST_FIRST(&delhead)((&delhead)->slh_first); | |||
| 1032 | SLIST_REMOVE_HEAD(&delhead, entry)do { (&delhead)->slh_first = (&delhead)->slh_first ->entry.sle_next; } while (0); | |||
| 1033 | free(d1->fn); | |||
| 1034 | free(d1); | |||
| 1035 | } | |||
| 1036 | return; | |||
| 1037 | } | |||
| 1038 | ||||
| 1039 | /* | |||
| 1040 | * Create a list of files marked for deletion. | |||
| 1041 | */ | |||
| 1042 | int | |||
| 1043 | createlist(struct buffer *bp) | |||
| 1044 | { | |||
| 1045 | struct delentry *d1 = NULL((void *)0), *d2; | |||
| 1046 | struct line *lp, *nlp; | |||
| 1047 | char fname[NFILEN1024]; | |||
| 1048 | char *p = fname; | |||
| 1049 | int ret = FALSE0; | |||
| 1050 | ||||
| 1051 | for (lp = bfirstlp(bp)((((bp)->b_headp)->l_fp)); lp != bp->b_headp; lp = nlp) { | |||
| 1052 | /* | |||
| 1053 | * Check if the line has 'D' on the first char and if a valid | |||
| 1054 | * filename can be extracted from it. | |||
| 1055 | */ | |||
| 1056 | if (((lp->l_text[0] != DDELCHAR)) || | |||
| 1057 | ((p = findfname(lp, p)) == NULL((void *)0))) { | |||
| 1058 | nlp = lforw(lp)((lp)->l_fp); | |||
| 1059 | continue; | |||
| 1060 | } | |||
| 1061 | if (SLIST_EMPTY(&delhead)(((&delhead)->slh_first) == ((void *)0))) { | |||
| 1062 | if ((d1 = malloc(sizeof(struct delentry))) | |||
| 1063 | == NULL((void *)0)) | |||
| 1064 | return (ABORT2); | |||
| 1065 | if ((d1->fn = strdup(p)) == NULL((void *)0)) { | |||
| 1066 | free(d1); | |||
| 1067 | return (ABORT2); | |||
| 1068 | } | |||
| 1069 | SLIST_INSERT_HEAD(&delhead, d1, entry)do { (d1)->entry.sle_next = (&delhead)->slh_first; ( &delhead)->slh_first = (d1); } while (0); | |||
| 1070 | } else { | |||
| 1071 | if ((d2 = malloc(sizeof(struct delentry))) | |||
| 1072 | == NULL((void *)0)) { | |||
| 1073 | free(d1->fn); | |||
| 1074 | free(d1); | |||
| 1075 | return (ABORT2); | |||
| 1076 | } | |||
| 1077 | if ((d2->fn = strdup(p)) == NULL((void *)0)) { | |||
| 1078 | free(d1->fn); | |||
| 1079 | free(d1); | |||
| 1080 | free(d2); | |||
| 1081 | return (ABORT2); | |||
| 1082 | } | |||
| 1083 | if (!d1) | |||
| 1084 | SLIST_INSERT_HEAD(&delhead, d2, entry)do { (d2)->entry.sle_next = (&delhead)->slh_first; ( &delhead)->slh_first = (d2); } while (0); | |||
| 1085 | else | |||
| 1086 | SLIST_INSERT_AFTER(d1, d2, entry)do { (d2)->entry.sle_next = (d1)->entry.sle_next; (d1)-> entry.sle_next = (d2); } while (0); | |||
| 1087 | d1 = d2; | |||
| 1088 | } | |||
| 1089 | ret = TRUE1; | |||
| 1090 | nlp = lforw(lp)((lp)->l_fp); | |||
| 1091 | } | |||
| 1092 | return (ret); | |||
| 1093 | } | |||
| 1094 | ||||
| 1095 | int | |||
| 1096 | dired_jump(int f, int n) | |||
| 1097 | { | |||
| 1098 | struct buffer *bp; | |||
| 1099 | const char *modename; | |||
| 1100 | char dname[NFILEN1024], *fname; | |||
| 1101 | int ret, i; | |||
| 1102 | ||||
| 1103 | /* | |||
| 1104 | * We use fundamental mode in dired, so just check we aren't in | |||
| 1105 | * dired mode for this specific function. Seems like a corner | |||
| 1106 | * case at the moment. | |||
| 1107 | */ | |||
| 1108 | for (i = 0; i <= curbp->b_nmodes; i++) { | |||
| 1109 | modename = curbp->b_modes[i]->p_name; | |||
| 1110 | if (strncmp(modename, "dired", 5) == 0) | |||
| 1111 | return (dobeep_msg("In dired mode already")); | |||
| 1112 | } | |||
| 1113 | ||||
| 1114 | if (getbufcwd(dname, sizeof(dname)) != TRUE1) | |||
| 1115 | return (FALSE0); | |||
| 1116 | ||||
| 1117 | fname = curbp->b_fname; | |||
| 1118 | ||||
| 1119 | if ((bp = dired_(dname)) == NULL((void *)0)) | |||
| 1120 | return (FALSE0); | |||
| 1121 | curbp = bp; | |||
| 1122 | ||||
| 1123 | ret = showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10); | |||
| 1124 | if (ret != TRUE1) | |||
| 1125 | return ret; | |||
| 1126 | ||||
| 1127 | fname = adjustname(fname, TRUE1); | |||
| 1128 | if (fname != NULL((void *)0)) | |||
| 1129 | gotofile(fname); | |||
| 1130 | ||||
| 1131 | return (TRUE1); | |||
| 1132 | } | |||
| 1133 | ||||
| 1134 | int | |||
| 1135 | d_gotofile(int f, int n) | |||
| 1136 | { | |||
| 1137 | size_t lenfpath; | |||
| 1138 | char fpath[NFILEN1024]; | |||
| 1139 | char *fpth, *fnp = NULL((void *)0); | |||
| 1140 | ||||
| 1141 | if (getbufcwd(fpath, sizeof(fpath)) != TRUE1) | |||
| ||||
| 1142 | fpath[0] = '\0'; | |||
| 1143 | lenfpath = strlen(fpath); | |||
| 1144 | fnp = eread("Goto file: ", fpath, NFILEN1024, | |||
| 1145 | EFNEW0x0008 | EFCR0x0010 | EFFILE0x0004 | EFDEF0x0020); | |||
| 1146 | if (fnp == NULL((void *)0)) | |||
| 1147 | return (ABORT2); | |||
| 1148 | else if (fnp[0] == '\0') | |||
| 1149 | return (FALSE0); | |||
| 1150 | ||||
| 1151 | fpth = adjustname(fpath, TRUE1); /* Removes last '/' if dir... */ | |||
| 1152 | if (fpth == NULL((void *)0) || strlen(fpth) == lenfpath - 1) { /* ...hence -1. */ | |||
| 1153 | ewprintf("No file to find"); /* Current directory given so */ | |||
| 1154 | return (TRUE1); /* return at present location. */ | |||
| 1155 | } | |||
| 1156 | return gotofile(fpth); | |||
| 1157 | } | |||
| 1158 | ||||
| 1159 | int | |||
| 1160 | gotofile(char *fpth) | |||
| 1161 | { | |||
| 1162 | struct line *lp, *nlp; | |||
| 1163 | char fname[NFILEN1024]; | |||
| 1164 | char *p; | |||
| 1165 | int tmp; | |||
| 1166 | ||||
| 1167 | (void)xbasename(fname, fpth, NFILEN1024); | |||
| 1168 | tmp = 0; | |||
| 1169 | for (lp = bfirstlp(curbp)((((curbp)->b_headp)->l_fp)); lp != curbp->b_headp; lp = nlp) { | |||
| 1170 | tmp++; | |||
| 1171 | if ((p = findfname(lp, p)) == NULL((void *)0)) { | |||
| ||||
| 1172 | nlp = lforw(lp)((lp)->l_fp); | |||
| 1173 | continue; | |||
| 1174 | } | |||
| 1175 | if (strcmp(fname, p) == 0) { | |||
| 1176 | curwp->w_dotp = lp; | |||
| 1177 | curwp->w_dotline = tmp; | |||
| 1178 | (void)d_warpdot(curwp->w_dotp, &curwp->w_doto); | |||
| 1179 | tmp--; | |||
| 1180 | break; | |||
| 1181 | } | |||
| 1182 | nlp = lforw(lp)((lp)->l_fp); | |||
| 1183 | } | |||
| 1184 | if (tmp == curbp->b_lines - 1) { | |||
| 1185 | ewprintf("File not found %s", fname); | |||
| 1186 | return (FALSE0); | |||
| 1187 | } else { | |||
| 1188 | ewprintf(""); | |||
| 1189 | return (TRUE1); | |||
| 1190 | } | |||
| 1191 | } | |||
| 1192 | ||||
| 1193 | /* | |||
| 1194 | * Look for and extract a file name on a dired buffer line. | |||
| 1195 | */ | |||
| 1196 | char * | |||
| 1197 | findfname(struct line *lp, char *fn) | |||
| 1198 | { | |||
| 1199 | int start; | |||
| 1200 | ||||
| 1201 | (void)d_warpdot(lp, &start); | |||
| 1202 | if (start < 1) | |||
| 1203 | return NULL((void *)0); | |||
| 1204 | fn = &lp->l_text[start]; | |||
| 1205 | return fn; | |||
| 1206 | } |