| File: | src/usr.bin/mg/dired.c |
| Warning: | line 1157, column 12 2nd function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: dired.c,v 1.102 2023/03/08 04:43:11 guenther 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 | int | |||
| 232 | dired(int f, int n) | |||
| 233 | { | |||
| 234 | char dname[NFILEN1024], *bufp, *slash; | |||
| 235 | struct buffer *bp; | |||
| 236 | ||||
| 237 | if (curbp->b_fname[0] != '\0') { | |||
| 238 | (void)strlcpy(dname, curbp->b_fname, sizeof(dname)); | |||
| 239 | if ((slash = strrchr(dname, '/')) != NULL((void *)0)) { | |||
| 240 | *(slash + 1) = '\0'; | |||
| 241 | } | |||
| 242 | } else { | |||
| 243 | if (getcwd(dname, sizeof(dname)) == NULL((void *)0)) | |||
| 244 | dname[0] = '\0'; | |||
| 245 | } | |||
| 246 | ||||
| 247 | if ((bufp = eread("Dired (directory): ", dname, NFILEN1024, | |||
| 248 | EFDEF0x0020 | EFNEW0x0008 | EFCR0x0010)) == NULL((void *)0)) | |||
| 249 | return (ABORT2); | |||
| 250 | if (bufp[0] == '\0') | |||
| 251 | return (FALSE0); | |||
| 252 | if ((bp = dired_(bufp)) == NULL((void *)0)) | |||
| 253 | return (FALSE0); | |||
| 254 | ||||
| 255 | curbp = bp; | |||
| 256 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
| 257 | } | |||
| 258 | ||||
| 259 | int | |||
| 260 | d_otherwindow(int f, int n) | |||
| 261 | { | |||
| 262 | char dname[NFILEN1024], *bufp, *slash; | |||
| 263 | struct buffer *bp; | |||
| 264 | struct mgwin *wp; | |||
| 265 | ||||
| 266 | if (curbp->b_fname[0] != '\0') { | |||
| 267 | (void)strlcpy(dname, curbp->b_fname, sizeof(dname)); | |||
| 268 | if ((slash = strrchr(dname, '/')) != NULL((void *)0)) { | |||
| 269 | *(slash + 1) = '\0'; | |||
| 270 | } | |||
| 271 | } else { | |||
| 272 | if (getcwd(dname, sizeof(dname)) == NULL((void *)0)) | |||
| 273 | dname[0] = '\0'; | |||
| 274 | } | |||
| 275 | ||||
| 276 | if ((bufp = eread("Dired other window: ", dname, NFILEN1024, | |||
| 277 | EFDEF0x0020 | EFNEW0x0008 | EFCR0x0010)) == NULL((void *)0)) | |||
| 278 | return (ABORT2); | |||
| 279 | else if (bufp[0] == '\0') | |||
| 280 | return (FALSE0); | |||
| 281 | if ((bp = dired_(bufp)) == NULL((void *)0)) | |||
| 282 | return (FALSE0); | |||
| 283 | if ((wp = popbuf(bp, WNONE0x00)) == NULL((void *)0)) | |||
| 284 | return (FALSE0); | |||
| 285 | curbp = bp; | |||
| 286 | curwp = wp; | |||
| 287 | return (TRUE1); | |||
| 288 | } | |||
| 289 | ||||
| 290 | int | |||
| 291 | d_del(int f, int n) | |||
| 292 | { | |||
| 293 | if (n < 0) | |||
| 294 | return (FALSE0); | |||
| 295 | while (n--) { | |||
| 296 | if (d_warpdot(curwp->w_dotp, &curwp->w_doto) == TRUE1) { | |||
| 297 | lputc(curwp->w_dotp, 0, DDELCHAR)((curwp->w_dotp)->l_text[(0)]=(DDELCHAR)); | |||
| 298 | curbp->b_flag |= BFDIREDDEL0x80; | |||
| 299 | } | |||
| 300 | if (lforw(curwp->w_dotp)((curwp->w_dotp)->l_fp) != curbp->b_headp) { | |||
| 301 | curwp->w_dotp = lforw(curwp->w_dotp)((curwp->w_dotp)->l_fp); | |||
| 302 | curwp->w_dotline++; | |||
| 303 | } | |||
| 304 | } | |||
| 305 | curwp->w_rflag |= WFEDIT0x04 | WFMOVE0x02; | |||
| 306 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
| 307 | } | |||
| 308 | ||||
| 309 | int | |||
| 310 | d_undel(int f, int n) | |||
| 311 | { | |||
| 312 | if (n < 0) | |||
| 313 | return (d_undelbak(f, -n)); | |||
| 314 | while (n--) { | |||
| 315 | if (llength(curwp->w_dotp)((curwp->w_dotp)->l_used) > 0) | |||
| 316 | lputc(curwp->w_dotp, 0, ' ')((curwp->w_dotp)->l_text[(0)]=(' ')); | |||
| 317 | if (lforw(curwp->w_dotp)((curwp->w_dotp)->l_fp) != curbp->b_headp) { | |||
| 318 | curwp->w_dotp = lforw(curwp->w_dotp)((curwp->w_dotp)->l_fp); | |||
| 319 | curwp->w_dotline++; | |||
| 320 | } | |||
| 321 | } | |||
| 322 | curwp->w_rflag |= WFEDIT0x04 | WFMOVE0x02; | |||
| 323 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
| 324 | } | |||
| 325 | ||||
| 326 | int | |||
| 327 | d_undelbak(int f, int n) | |||
| 328 | { | |||
| 329 | if (n < 0) | |||
| 330 | return (d_undel(f, -n)); | |||
| 331 | while (n--) { | |||
| 332 | if (lback(curwp->w_dotp)((curwp->w_dotp)->l_bp) != curbp->b_headp) { | |||
| 333 | curwp->w_dotp = lback(curwp->w_dotp)((curwp->w_dotp)->l_bp); | |||
| 334 | curwp->w_dotline--; | |||
| 335 | } | |||
| 336 | if (llength(curwp->w_dotp)((curwp->w_dotp)->l_used) > 0) | |||
| 337 | lputc(curwp->w_dotp, 0, ' ')((curwp->w_dotp)->l_text[(0)]=(' ')); | |||
| 338 | } | |||
| 339 | curwp->w_rflag |= WFEDIT0x04 | WFMOVE0x02; | |||
| 340 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
| 341 | } | |||
| 342 | ||||
| 343 | int | |||
| 344 | d_findfile(int f, int n) | |||
| 345 | { | |||
| 346 | struct buffer *bp; | |||
| 347 | int s; | |||
| 348 | char fname[NFILEN1024]; | |||
| 349 | ||||
| 350 | if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT2) | |||
| 351 | return (FALSE0); | |||
| 352 | if (s == TRUE1) | |||
| 353 | bp = dired_(fname); | |||
| 354 | else | |||
| 355 | bp = findbuffer(fname); | |||
| 356 | if (bp == NULL((void *)0)) | |||
| 357 | return (FALSE0); | |||
| 358 | curbp = bp; | |||
| 359 | if (showbuffer(bp, curwp, WFFULL0x08) != TRUE1) | |||
| 360 | return (FALSE0); | |||
| 361 | if (bp->b_fname[0] != 0) | |||
| 362 | return (TRUE1); | |||
| 363 | return (readin(fname)); | |||
| 364 | } | |||
| 365 | ||||
| 366 | int | |||
| 367 | d_ffotherwindow(int f, int n) | |||
| 368 | { | |||
| 369 | char fname[NFILEN1024]; | |||
| 370 | int s; | |||
| 371 | struct buffer *bp; | |||
| 372 | struct mgwin *wp; | |||
| 373 | ||||
| 374 | if ((s = d_makename(curwp->w_dotp, fname, sizeof(fname))) == ABORT2) | |||
| 375 | return (FALSE0); | |||
| 376 | if ((bp = (s ? dired_(fname) : findbuffer(fname))) == NULL((void *)0)) | |||
| 377 | return (FALSE0); | |||
| 378 | if ((wp = popbuf(bp, WNONE0x00)) == NULL((void *)0)) | |||
| 379 | return (FALSE0); | |||
| 380 | curbp = bp; | |||
| 381 | curwp = wp; | |||
| 382 | if (bp->b_fname[0] != 0) | |||
| 383 | return (TRUE1); /* never true for dired buffers */ | |||
| 384 | return (readin(fname)); | |||
| 385 | } | |||
| 386 | ||||
| 387 | int | |||
| 388 | d_expunge(int f, int n) | |||
| 389 | { | |||
| 390 | struct line *lp, *nlp; | |||
| 391 | char fname[NFILEN1024], sname[NFILEN1024]; | |||
| 392 | int tmp; | |||
| 393 | ||||
| 394 | tmp = curwp->w_dotline; | |||
| 395 | curwp->w_dotline = 0; | |||
| 396 | ||||
| 397 | for (lp = bfirstlp(curbp)((((curbp)->b_headp)->l_fp)); lp != curbp->b_headp; lp = nlp) { | |||
| 398 | curwp->w_dotline++; | |||
| 399 | nlp = lforw(lp)((lp)->l_fp); | |||
| 400 | if (llength(lp)((lp)->l_used) && lgetc(lp, 0)(((unsigned char) ((lp)->l_text[(0)]))) == 'D') { | |||
| 401 | switch (d_makename(lp, fname, sizeof(fname))) { | |||
| 402 | case ABORT2: | |||
| 403 | dobeep(); | |||
| 404 | ewprintf("Bad line in dired buffer"); | |||
| 405 | curwp->w_dotline = tmp; | |||
| 406 | return (FALSE0); | |||
| 407 | case FALSE0: | |||
| 408 | if (unlink(fname) == -1) { | |||
| 409 | (void)xbasename(sname, fname, NFILEN1024); | |||
| 410 | dobeep(); | |||
| 411 | ewprintf("Could not delete '%s'", sname); | |||
| 412 | curwp->w_dotline = tmp; | |||
| 413 | return (FALSE0); | |||
| 414 | } | |||
| 415 | break; | |||
| 416 | case TRUE1: | |||
| 417 | if (rmdir(fname) == -1) { | |||
| 418 | (void)xbasename(sname, fname, NFILEN1024); | |||
| 419 | dobeep(); | |||
| 420 | ewprintf("Could not delete directory " | |||
| 421 | "'%s'", sname); | |||
| 422 | curwp->w_dotline = tmp; | |||
| 423 | return (FALSE0); | |||
| 424 | } | |||
| 425 | break; | |||
| 426 | } | |||
| 427 | lfree(lp); | |||
| 428 | curwp->w_bufp->b_lines--; | |||
| 429 | if (tmp > curwp->w_dotline) | |||
| 430 | tmp--; | |||
| 431 | curwp->w_rflag |= WFFULL0x08; | |||
| 432 | } | |||
| 433 | } | |||
| 434 | curwp->w_dotline = tmp; | |||
| 435 | d_warpdot(curwp->w_dotp, &curwp->w_doto); | |||
| 436 | ||||
| 437 | /* we have deleted all items successfully, remove del flag */ | |||
| 438 | curbp->b_flag &= ~BFDIREDDEL0x80; | |||
| 439 | ||||
| 440 | return (TRUE1); | |||
| 441 | } | |||
| 442 | ||||
| 443 | int | |||
| 444 | d_copy(int f, int n) | |||
| 445 | { | |||
| 446 | struct stat statbuf; | |||
| 447 | char frname[NFILEN1024], toname[NFILEN1024], sname[NFILEN1024]; | |||
| 448 | char *topath, *bufp; | |||
| 449 | int ret; | |||
| 450 | size_t off; | |||
| 451 | struct buffer *bp; | |||
| 452 | ||||
| 453 | if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE0) { | |||
| 454 | dobeep(); | |||
| 455 | ewprintf("Not a file"); | |||
| 456 | return (FALSE0); | |||
| 457 | } | |||
| 458 | off = strlcpy(toname, curbp->b_fname, sizeof(toname)); | |||
| 459 | if (off >= sizeof(toname) - 1) { /* can't happen, really */ | |||
| 460 | dobeep(); | |||
| 461 | ewprintf("Directory name too long"); | |||
| 462 | return (FALSE0); | |||
| 463 | } | |||
| 464 | (void)xbasename(sname, frname, NFILEN1024); | |||
| 465 | bufp = eread("Copy %s to: ", toname, sizeof(toname), | |||
| 466 | EFDEF0x0020 | EFNEW0x0008 | EFCR0x0010, sname); | |||
| 467 | if (bufp == NULL((void *)0)) | |||
| 468 | return (ABORT2); | |||
| 469 | else if (bufp[0] == '\0') | |||
| 470 | return (FALSE0); | |||
| 471 | ||||
| 472 | topath = adjustname(toname, TRUE1); | |||
| 473 | if (stat(topath, &statbuf) == 0) { | |||
| 474 | if (S_ISDIR(statbuf.st_mode)((statbuf.st_mode & 0170000) == 0040000)) { | |||
| 475 | ret = snprintf(toname, sizeof(toname), "%s/%s", | |||
| 476 | topath, sname); | |||
| 477 | if (ret < 0 || ret >= sizeof(toname) - 1) { | |||
| 478 | dobeep(); | |||
| 479 | ewprintf("Directory name too long"); | |||
| 480 | return (FALSE0); | |||
| 481 | } | |||
| 482 | topath = adjustname(toname, TRUE1); | |||
| 483 | } | |||
| 484 | } | |||
| 485 | if (topath == NULL((void *)0)) | |||
| 486 | return (FALSE0); | |||
| 487 | if (strcmp(frname, topath) == 0) { | |||
| 488 | ewprintf("Cannot copy to same file: %s", frname); | |||
| 489 | return (TRUE1); | |||
| 490 | } | |||
| 491 | ret = (copy(frname, topath) >= 0) ? TRUE1 : FALSE0; | |||
| 492 | if (ret != TRUE1) | |||
| 493 | return (ret); | |||
| 494 | if ((bp = refreshbuffer(curbp)) == NULL((void *)0)) | |||
| 495 | return (FALSE0); | |||
| 496 | ||||
| 497 | ewprintf("Copy: 1 file"); | |||
| 498 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
| 499 | } | |||
| 500 | ||||
| 501 | int | |||
| 502 | d_rename(int f, int n) | |||
| 503 | { | |||
| 504 | struct stat statbuf; | |||
| 505 | char frname[NFILEN1024], toname[NFILEN1024]; | |||
| 506 | char *topath, *bufp; | |||
| 507 | int ret; | |||
| 508 | size_t off; | |||
| 509 | struct buffer *bp; | |||
| 510 | char sname[NFILEN1024]; | |||
| 511 | ||||
| 512 | if (d_makename(curwp->w_dotp, frname, sizeof(frname)) != FALSE0) { | |||
| 513 | dobeep(); | |||
| 514 | ewprintf("Not a file"); | |||
| 515 | return (FALSE0); | |||
| 516 | } | |||
| 517 | off = strlcpy(toname, curbp->b_fname, sizeof(toname)); | |||
| 518 | if (off >= sizeof(toname) - 1) { /* can't happen, really */ | |||
| 519 | dobeep(); | |||
| 520 | ewprintf("Name too long"); | |||
| 521 | return (FALSE0); | |||
| 522 | } | |||
| 523 | (void)xbasename(sname, frname, NFILEN1024); | |||
| 524 | bufp = eread("Rename %s to: ", toname, | |||
| 525 | sizeof(toname), EFDEF0x0020 | EFNEW0x0008 | EFCR0x0010, sname); | |||
| 526 | if (bufp == NULL((void *)0)) | |||
| 527 | return (ABORT2); | |||
| 528 | else if (bufp[0] == '\0') | |||
| 529 | return (FALSE0); | |||
| 530 | ||||
| 531 | topath = adjustname(toname, TRUE1); | |||
| 532 | if (stat(topath, &statbuf) == 0) { | |||
| 533 | if (S_ISDIR(statbuf.st_mode)((statbuf.st_mode & 0170000) == 0040000)) { | |||
| 534 | ret = snprintf(toname, sizeof(toname), "%s/%s", | |||
| 535 | topath, sname); | |||
| 536 | if (ret < 0 || ret >= sizeof(toname) - 1) { | |||
| 537 | dobeep(); | |||
| 538 | ewprintf("Directory name too long"); | |||
| 539 | return (FALSE0); | |||
| 540 | } | |||
| 541 | topath = adjustname(toname, TRUE1); | |||
| 542 | } | |||
| 543 | } | |||
| 544 | if (topath == NULL((void *)0)) | |||
| 545 | return (FALSE0); | |||
| 546 | if (strcmp(frname, topath) == 0) { | |||
| 547 | ewprintf("Cannot move to same file: %s", frname); | |||
| 548 | return (TRUE1); | |||
| 549 | } | |||
| 550 | ret = (rename(frname, topath) >= 0) ? TRUE1 : FALSE0; | |||
| 551 | if (ret != TRUE1) | |||
| 552 | return (ret); | |||
| 553 | if ((bp = refreshbuffer(curbp)) == NULL((void *)0)) | |||
| 554 | return (FALSE0); | |||
| 555 | ||||
| 556 | ewprintf("Move: 1 file"); | |||
| 557 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
| 558 | } | |||
| 559 | ||||
| 560 | void | |||
| 561 | reaper(int signo __attribute__((unused))) | |||
| 562 | { | |||
| 563 | int save_errno = errno(*__errno()), status; | |||
| 564 | ||||
| 565 | while (waitpid(-1, &status, WNOHANG0x01) >= 0) | |||
| 566 | ; | |||
| 567 | errno(*__errno()) = save_errno; | |||
| 568 | } | |||
| 569 | ||||
| 570 | /* | |||
| 571 | * Pipe the currently selected file through a shell command. | |||
| 572 | */ | |||
| 573 | int | |||
| 574 | d_shell_command(int f, int n) | |||
| 575 | { | |||
| 576 | char command[512], fname[PATH_MAX1024], *bufp; | |||
| 577 | struct buffer *bp; | |||
| 578 | struct mgwin *wp; | |||
| 579 | char sname[NFILEN1024]; | |||
| 580 | ||||
| 581 | bp = bfind("*Shell Command Output*", TRUE1); | |||
| 582 | if (bclear(bp) != TRUE1) | |||
| 583 | return (ABORT2); | |||
| 584 | ||||
| 585 | if (d_makename(curwp->w_dotp, fname, sizeof(fname)) != FALSE0) { | |||
| 586 | dobeep(); | |||
| 587 | ewprintf("bad line"); | |||
| 588 | return (ABORT2); | |||
| 589 | } | |||
| 590 | ||||
| 591 | command[0] = '\0'; | |||
| 592 | (void)xbasename(sname, fname, NFILEN1024); | |||
| 593 | bufp = eread("! on %s: ", command, sizeof(command), EFNEW0x0008, sname); | |||
| 594 | if (bufp == NULL((void *)0)) | |||
| 595 | return (ABORT2); | |||
| 596 | ||||
| 597 | if (d_exec(0, bp, fname, "sh", "-c", command, NULL((void *)0)) != TRUE1) | |||
| 598 | return (ABORT2); | |||
| 599 | ||||
| 600 | if ((wp = popbuf(bp, WNONE0x00)) == NULL((void *)0)) | |||
| 601 | return (ABORT2); /* XXX - free the buffer?? */ | |||
| 602 | curwp = wp; | |||
| 603 | curbp = wp->w_bufp; | |||
| 604 | return (TRUE1); | |||
| 605 | } | |||
| 606 | ||||
| 607 | /* | |||
| 608 | * Pipe input file to cmd and insert the command's output in the | |||
| 609 | * given buffer. Each line will be prefixed with the given | |||
| 610 | * number of spaces. | |||
| 611 | */ | |||
| 612 | static int | |||
| 613 | d_exec(int space, struct buffer *bp, const char *input, const char *cmd, ...) | |||
| 614 | { | |||
| 615 | char buf[BUFSIZ1024]; | |||
| 616 | va_list ap; | |||
| 617 | struct sigaction olda, newa; | |||
| 618 | char **argv = NULL((void *)0), *cp; | |||
| 619 | FILE *fin; | |||
| 620 | int fds[2] = { -1, -1 }; | |||
| 621 | int infd = -1; | |||
| 622 | int ret = (ABORT2), n; | |||
| 623 | pid_t pid; | |||
| 624 | ||||
| 625 | if (sigaction(SIGCHLD20, NULL((void *)0), &olda) == -1) | |||
| 626 | return (ABORT2); | |||
| 627 | ||||
| 628 | /* Find the number of arguments. */ | |||
| 629 | va_start(ap, cmd)__builtin_va_start((ap), cmd); | |||
| 630 | for (n = 2; va_arg(ap, char *)__builtin_va_arg((ap), char *) != NULL((void *)0); n++) | |||
| 631 | ; | |||
| 632 | va_end(ap)__builtin_va_end((ap)); | |||
| 633 | ||||
| 634 | /* Allocate and build the argv. */ | |||
| 635 | if ((argv = calloc(n, sizeof(*argv))) == NULL((void *)0)) { | |||
| 636 | dobeep(); | |||
| 637 | ewprintf("Can't allocate argv : %s", strerror(errno(*__errno()))); | |||
| 638 | goto out; | |||
| 639 | } | |||
| 640 | ||||
| 641 | n = 1; | |||
| 642 | argv[0] = (char *)cmd; | |||
| 643 | va_start(ap, cmd)__builtin_va_start((ap), cmd); | |||
| 644 | while ((argv[n] = va_arg(ap, char *)__builtin_va_arg((ap), char *)) != NULL((void *)0)) | |||
| 645 | n++; | |||
| 646 | va_end(ap)__builtin_va_end((ap)); | |||
| 647 | ||||
| 648 | if (input == NULL((void *)0)) | |||
| 649 | input = "/dev/null"; | |||
| 650 | ||||
| 651 | if ((infd = open(input, O_RDONLY0x0000)) == -1) { | |||
| 652 | dobeep(); | |||
| 653 | ewprintf("Can't open input file : %s", strerror(errno(*__errno()))); | |||
| 654 | goto out; | |||
| 655 | } | |||
| 656 | ||||
| 657 | if (pipe(fds) == -1) { | |||
| 658 | dobeep(); | |||
| 659 | ewprintf("Can't create pipe : %s", strerror(errno(*__errno()))); | |||
| 660 | goto out; | |||
| 661 | } | |||
| 662 | ||||
| 663 | newa.sa_handler__sigaction_u.__sa_handler = reaper; | |||
| 664 | newa.sa_flags = 0; | |||
| 665 | if (sigaction(SIGCHLD20, &newa, NULL((void *)0)) == -1) | |||
| 666 | goto out; | |||
| 667 | ||||
| 668 | if ((pid = fork()) == -1) { | |||
| 669 | dobeep(); | |||
| 670 | ewprintf("Can't fork"); | |||
| 671 | goto out; | |||
| 672 | } | |||
| 673 | ||||
| 674 | switch (pid) { | |||
| 675 | case 0: /* Child */ | |||
| 676 | close(fds[0]); | |||
| 677 | dup2(infd, STDIN_FILENO0); | |||
| 678 | dup2(fds[1], STDOUT_FILENO1); | |||
| 679 | dup2(fds[1], STDERR_FILENO2); | |||
| 680 | if (execvp(argv[0], argv) == -1) | |||
| 681 | ewprintf("Can't exec %s: %s", argv[0], strerror(errno(*__errno()))); | |||
| 682 | exit(1); | |||
| 683 | break; | |||
| 684 | default: /* Parent */ | |||
| 685 | close(infd); | |||
| 686 | close(fds[1]); | |||
| 687 | infd = fds[1] = -1; | |||
| 688 | if ((fin = fdopen(fds[0], "r")) == NULL((void *)0)) | |||
| 689 | goto out; | |||
| 690 | while (fgets(buf, sizeof(buf), fin) != NULL((void *)0)) { | |||
| 691 | cp = strrchr(buf, *bp->b_nlchr); | |||
| 692 | if (cp == NULL((void *)0) && !feof(fin)(!__isthreaded ? (((fin)->_flags & 0x0020) != 0) : (feof )(fin))) { /* too long a line */ | |||
| 693 | int c; | |||
| 694 | addlinef(bp, "%*s%s...", space, "", buf); | |||
| 695 | while ((c = getc(fin)(!__isthreaded ? (--(fin)->_r < 0 ? __srget(fin) : (int )(*(fin)->_p++)) : (getc)(fin))) != EOF(-1) && | |||
| 696 | c != *bp->b_nlchr) | |||
| 697 | ; | |||
| 698 | continue; | |||
| 699 | } else if (cp) | |||
| 700 | *cp = '\0'; | |||
| 701 | addlinef(bp, "%*s%s", space, "", buf); | |||
| 702 | } | |||
| 703 | fclose(fin); | |||
| 704 | break; | |||
| 705 | } | |||
| 706 | ret = (TRUE1); | |||
| 707 | ||||
| 708 | out: | |||
| 709 | if (sigaction(SIGCHLD20, &olda, NULL((void *)0)) == -1) | |||
| 710 | ewprintf("Warning, couldn't reset previous signal handler"); | |||
| 711 | if (fds[0] != -1) | |||
| 712 | close(fds[0]); | |||
| 713 | if (fds[1] != -1) | |||
| 714 | close(fds[1]); | |||
| 715 | if (infd != -1) | |||
| 716 | close(infd); | |||
| 717 | free(argv); | |||
| 718 | return ret; | |||
| 719 | } | |||
| 720 | ||||
| 721 | int | |||
| 722 | d_create_directory(int f, int n) | |||
| 723 | { | |||
| 724 | int ret; | |||
| 725 | struct buffer *bp; | |||
| 726 | ||||
| 727 | ret = ask_makedir(); | |||
| 728 | if (ret != TRUE1) | |||
| 729 | return(ret); | |||
| 730 | ||||
| 731 | if ((bp = refreshbuffer(curbp)) == NULL((void *)0)) | |||
| 732 | return (FALSE0); | |||
| 733 | ||||
| 734 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
| 735 | } | |||
| 736 | ||||
| 737 | int | |||
| 738 | d_killbuffer_cmd(int f, int n) | |||
| 739 | { | |||
| 740 | return(killbuffer_cmd(FFRAND8, 0)); | |||
| 741 | } | |||
| 742 | ||||
| 743 | int | |||
| 744 | d_refreshbuffer(int f, int n) | |||
| 745 | { | |||
| 746 | struct buffer *bp; | |||
| 747 | ||||
| 748 | if ((bp = refreshbuffer(curbp)) == NULL((void *)0)) | |||
| 749 | return (FALSE0); | |||
| 750 | ||||
| 751 | return (showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10)); | |||
| 752 | } | |||
| 753 | ||||
| 754 | /* | |||
| 755 | * Kill then re-open the requested dired buffer. | |||
| 756 | * If required, take a note of any files marked for deletion. Then once | |||
| 757 | * the buffer has been re-opened, remark the same files as deleted. | |||
| 758 | */ | |||
| 759 | struct buffer * | |||
| 760 | refreshbuffer(struct buffer *bp) | |||
| 761 | { | |||
| 762 | char *tmp_b_fname; | |||
| 763 | int i, tmp_w_dotline, ddel = 0; | |||
| 764 | ||||
| 765 | /* remember directory path to open later */ | |||
| 766 | tmp_b_fname = strdup(bp->b_fname); | |||
| 767 | if (tmp_b_fname == NULL((void *)0)) { | |||
| 768 | dobeep(); | |||
| 769 | ewprintf("Out of memory"); | |||
| 770 | return (NULL((void *)0)); | |||
| 771 | } | |||
| 772 | tmp_w_dotline = curwp->w_dotline; | |||
| 773 | ||||
| 774 | /* create a list of files for deletion */ | |||
| 775 | if (bp->b_flag & BFDIREDDEL0x80) | |||
| 776 | ddel = createlist(bp); | |||
| 777 | ||||
| 778 | killbuffer(bp); | |||
| 779 | ||||
| 780 | /* dired_() uses findbuffer() to create new buffer */ | |||
| 781 | if ((bp = dired_(tmp_b_fname)) == NULL((void *)0)) { | |||
| 782 | free(tmp_b_fname); | |||
| 783 | return (NULL((void *)0)); | |||
| 784 | } | |||
| 785 | free(tmp_b_fname); | |||
| 786 | ||||
| 787 | /* remark any previously deleted files with a 'D' */ | |||
| 788 | if (ddel) | |||
| 789 | redelete(bp); | |||
| 790 | ||||
| 791 | /* find dot line */ | |||
| 792 | bp->b_dotp = bfirstlp(bp)((((bp)->b_headp)->l_fp)); | |||
| 793 | if (tmp_w_dotline > bp->b_lines) | |||
| 794 | tmp_w_dotline = bp->b_lines - 1; | |||
| 795 | for (i = 1; i < tmp_w_dotline; i++) | |||
| 796 | bp->b_dotp = lforw(bp->b_dotp)((bp->b_dotp)->l_fp); | |||
| 797 | ||||
| 798 | bp->b_dotline = i; | |||
| 799 | bp->b_doto = 0; | |||
| 800 | d_warpdot(bp->b_dotp, &bp->b_doto); | |||
| 801 | ||||
| 802 | curbp = bp; | |||
| 803 | ||||
| 804 | return (bp); | |||
| 805 | } | |||
| 806 | ||||
| 807 | static int | |||
| 808 | d_makename(struct line *lp, char *fn, size_t len) | |||
| 809 | { | |||
| 810 | int start, nlen, ret; | |||
| 811 | char *namep; | |||
| 812 | ||||
| 813 | if (d_warpdot(lp, &start) == FALSE0) | |||
| 814 | return (ABORT2); | |||
| 815 | namep = &lp->l_text[start]; | |||
| 816 | nlen = llength(lp)((lp)->l_used) - start; | |||
| 817 | ||||
| 818 | ret = snprintf(fn, len, "%s%.*s", curbp->b_fname, nlen, namep); | |||
| 819 | if (ret < 0 || ret >= (int)len) | |||
| 820 | return (ABORT2); /* Name is too long. */ | |||
| 821 | ||||
| 822 | /* Return TRUE if the entry is a directory. */ | |||
| 823 | return ((lgetc(lp, 2)(((unsigned char) ((lp)->l_text[(2)]))) == 'd') ? TRUE1 : FALSE0); | |||
| 824 | } | |||
| 825 | ||||
| 826 | #define NAME_FIELD9 9 | |||
| 827 | ||||
| 828 | static int | |||
| 829 | d_warpdot(struct line *dotp, int *doto) | |||
| 830 | { | |||
| 831 | char *tp = dotp->l_text; | |||
| 832 | int off = 0, field = 0, len; | |||
| 833 | ||||
| 834 | /* | |||
| 835 | * Find the byte offset to the (space-delimited) filename | |||
| 836 | * field in formatted ls output. | |||
| 837 | */ | |||
| 838 | len = llength(dotp)((dotp)->l_used); | |||
| 839 | while (off < len) { | |||
| 840 | if (tp[off++] == ' ') { | |||
| 841 | if (++field == NAME_FIELD9) { | |||
| 842 | *doto = off; | |||
| 843 | return (TRUE1); | |||
| 844 | } | |||
| 845 | /* Skip the space. */ | |||
| 846 | while (off < len && tp[off] == ' ') | |||
| 847 | off++; | |||
| 848 | } | |||
| 849 | } | |||
| 850 | /* We didn't find the field. */ | |||
| 851 | *doto = 0; | |||
| 852 | return (FALSE0); | |||
| 853 | } | |||
| 854 | ||||
| 855 | static int | |||
| 856 | d_forwpage(int f, int n) | |||
| 857 | { | |||
| 858 | forwpage(f | FFRAND8, n); | |||
| 859 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
| 860 | } | |||
| 861 | ||||
| 862 | static int | |||
| 863 | d_backpage (int f, int n) | |||
| 864 | { | |||
| 865 | backpage(f | FFRAND8, n); | |||
| 866 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
| 867 | } | |||
| 868 | ||||
| 869 | static int | |||
| 870 | d_forwline (int f, int n) | |||
| 871 | { | |||
| 872 | forwline(f | FFRAND8, n); | |||
| 873 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
| 874 | } | |||
| 875 | ||||
| 876 | static int | |||
| 877 | d_backline (int f, int n) | |||
| 878 | { | |||
| 879 | backline(f | FFRAND8, n); | |||
| 880 | return (d_warpdot(curwp->w_dotp, &curwp->w_doto)); | |||
| 881 | } | |||
| 882 | ||||
| 883 | int | |||
| 884 | d_filevisitalt (int f, int n) | |||
| 885 | { | |||
| 886 | char fname[NFILEN1024]; | |||
| 887 | ||||
| 888 | if (d_makename(curwp->w_dotp, fname, sizeof(fname)) == ABORT2) | |||
| 889 | return (FALSE0); | |||
| 890 | ||||
| 891 | return(do_filevisitalt(fname)); | |||
| 892 | } | |||
| 893 | ||||
| 894 | /* | |||
| 895 | * XXX dname needs to have enough place to store an additional '/'. | |||
| 896 | */ | |||
| 897 | struct buffer * | |||
| 898 | dired_(char *dname) | |||
| 899 | { | |||
| 900 | struct buffer *bp; | |||
| 901 | int i; | |||
| 902 | size_t len; | |||
| 903 | ||||
| 904 | if ((dname = adjustname(dname, TRUE1)) == NULL((void *)0)) { | |||
| 905 | dobeep(); | |||
| 906 | ewprintf("Bad directory name"); | |||
| 907 | return (NULL((void *)0)); | |||
| 908 | } | |||
| 909 | /* this should not be done, instead adjustname() should get a flag */ | |||
| 910 | len = strlen(dname); | |||
| 911 | if (dname[len - 1] != '/') { | |||
| 912 | dname[len++] = '/'; | |||
| 913 | dname[len] = '\0'; | |||
| 914 | } | |||
| 915 | if ((access(dname, R_OK0x04 | X_OK0x01)) == -1) { | |||
| 916 | if (errno(*__errno()) == EACCES13) { | |||
| 917 | dobeep(); | |||
| 918 | ewprintf("Permission denied: %s", dname); | |||
| 919 | } else { | |||
| 920 | dobeep(); | |||
| 921 | ewprintf("Error opening: %s", dname); | |||
| 922 | } | |||
| 923 | return (NULL((void *)0)); | |||
| 924 | } | |||
| 925 | for (bp = bheadp; bp != NULL((void *)0); bp = bp->b_bufpb_list.l_p.x_bp) { | |||
| 926 | if (strcmp(bp->b_fname, dname) == 0) { | |||
| 927 | if (fchecktime(bp) != TRUE1) | |||
| 928 | ewprintf("Directory has changed on disk;" | |||
| 929 | " type g to update Dired"); | |||
| 930 | return (bp); | |||
| 931 | } | |||
| 932 | ||||
| 933 | } | |||
| 934 | bp = bfind(dname, TRUE1); | |||
| 935 | bp->b_flag |= BFREADONLY0x10 | BFIGNDIRTY0x40; | |||
| 936 | ||||
| 937 | if ((d_exec(2, bp, NULL((void *)0), "ls", "-al", dname, NULL((void *)0))) != TRUE1) | |||
| 938 | return (NULL((void *)0)); | |||
| 939 | ||||
| 940 | /* Find the line with ".." on it. */ | |||
| 941 | bp->b_dotp = bfirstlp(bp)((((bp)->b_headp)->l_fp)); | |||
| 942 | bp->b_dotline = 1; | |||
| 943 | for (i = 0; i < bp->b_lines; i++) { | |||
| 944 | bp->b_dotp = lforw(bp->b_dotp)((bp->b_dotp)->l_fp); | |||
| 945 | bp->b_dotline++; | |||
| 946 | if (d_warpdot(bp->b_dotp, &bp->b_doto) == FALSE0) | |||
| 947 | continue; | |||
| 948 | if (strcmp(ltext(bp->b_dotp)((bp->b_dotp)->l_text) + bp->b_doto, "..") == 0) | |||
| 949 | break; | |||
| 950 | } | |||
| 951 | ||||
| 952 | /* We want dot on the entry right after "..", if possible. */ | |||
| 953 | if (++i < bp->b_lines - 2) { | |||
| 954 | bp->b_dotp = lforw(bp->b_dotp)((bp->b_dotp)->l_fp); | |||
| 955 | bp->b_dotline++; | |||
| 956 | } | |||
| 957 | d_warpdot(bp->b_dotp, &bp->b_doto); | |||
| 958 | ||||
| 959 | (void)strlcpy(bp->b_fname, dname, sizeof(bp->b_fname)); | |||
| 960 | (void)strlcpy(bp->b_cwd, dname, sizeof(bp->b_cwd)); | |||
| 961 | if ((bp->b_modes[1] = name_mode("dired")) == NULL((void *)0)) { | |||
| 962 | bp->b_modes[0] = name_mode("fundamental"); | |||
| 963 | dobeep(); | |||
| 964 | ewprintf("Could not find mode dired"); | |||
| 965 | return (NULL((void *)0)); | |||
| 966 | } | |||
| 967 | (void)fupdstat(bp); | |||
| 968 | bp->b_nmodes = 1; | |||
| 969 | return (bp); | |||
| 970 | } | |||
| 971 | ||||
| 972 | /* | |||
| 973 | * Iterate through the lines of the dired buffer looking for files | |||
| 974 | * collected in the linked list made in createlist(). If a line is found | |||
| 975 | * replace 'D' as first char in a line. As lines are found, remove the | |||
| 976 | * corresponding item from the linked list. Iterate for as long as there | |||
| 977 | * are items in the linked list or until end of buffer is found. | |||
| 978 | */ | |||
| 979 | void | |||
| 980 | redelete(struct buffer *bp) | |||
| 981 | { | |||
| 982 | struct delentry *dt, *d1 = NULL((void *)0); | |||
| 983 | struct line *lp, *nlp; | |||
| 984 | char fname[NFILEN1024]; | |||
| 985 | char *p = fname; | |||
| 986 | size_t plen, fnlen; | |||
| 987 | int finished = 0; | |||
| 988 | ||||
| 989 | /* reset the deleted file buffer flag until a deleted file is found */ | |||
| 990 | bp->b_flag &= ~BFDIREDDEL0x80; | |||
| 991 | ||||
| 992 | for (lp = bfirstlp(bp)((((bp)->b_headp)->l_fp)); lp != bp->b_headp; lp = nlp) { | |||
| 993 | bp->b_dotp = lp; | |||
| 994 | if ((p = findfname(lp, p)) == NULL((void *)0)) { | |||
| 995 | nlp = lforw(lp)((lp)->l_fp); | |||
| 996 | continue; | |||
| 997 | } | |||
| 998 | plen = strlen(p); | |||
| 999 | SLIST_FOREACH_SAFE(d1, &delhead, entry, dt)for ((d1) = ((&delhead)->slh_first); (d1) && ( (dt) = ((d1)->entry.sle_next), 1); (d1) = (dt)) { | |||
| 1000 | fnlen = strlen(d1->fn); | |||
| 1001 | if ((plen == fnlen) && | |||
| 1002 | (strncmp(p, d1->fn, plen) == 0)) { | |||
| 1003 | lputc(bp->b_dotp, 0, DDELCHAR)((bp->b_dotp)->l_text[(0)]=(DDELCHAR)); | |||
| 1004 | bp->b_flag |= BFDIREDDEL0x80; | |||
| 1005 | 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); | |||
| 1006 | if (SLIST_EMPTY(&delhead)(((&delhead)->slh_first) == ((void *)0))) { | |||
| 1007 | finished = 1; | |||
| 1008 | break; | |||
| 1009 | } | |||
| 1010 | } | |||
| 1011 | } | |||
| 1012 | if (finished) | |||
| 1013 | break; | |||
| 1014 | nlp = lforw(lp)((lp)->l_fp); | |||
| 1015 | } | |||
| 1016 | while (!SLIST_EMPTY(&delhead)(((&delhead)->slh_first) == ((void *)0))) { | |||
| 1017 | d1 = SLIST_FIRST(&delhead)((&delhead)->slh_first); | |||
| 1018 | SLIST_REMOVE_HEAD(&delhead, entry)do { (&delhead)->slh_first = (&delhead)->slh_first ->entry.sle_next; } while (0); | |||
| 1019 | free(d1->fn); | |||
| 1020 | free(d1); | |||
| 1021 | } | |||
| 1022 | return; | |||
| 1023 | } | |||
| 1024 | ||||
| 1025 | /* | |||
| 1026 | * Create a list of files marked for deletion. | |||
| 1027 | */ | |||
| 1028 | int | |||
| 1029 | createlist(struct buffer *bp) | |||
| 1030 | { | |||
| 1031 | struct delentry *d1 = NULL((void *)0), *d2; | |||
| 1032 | struct line *lp, *nlp; | |||
| 1033 | char fname[NFILEN1024]; | |||
| 1034 | char *p = fname; | |||
| 1035 | int ret = FALSE0; | |||
| 1036 | ||||
| 1037 | for (lp = bfirstlp(bp)((((bp)->b_headp)->l_fp)); lp != bp->b_headp; lp = nlp) { | |||
| 1038 | /* | |||
| 1039 | * Check if the line has 'D' on the first char and if a valid | |||
| 1040 | * filename can be extracted from it. | |||
| 1041 | */ | |||
| 1042 | if (((lp->l_text[0] != DDELCHAR)) || | |||
| 1043 | ((p = findfname(lp, p)) == NULL((void *)0))) { | |||
| 1044 | nlp = lforw(lp)((lp)->l_fp); | |||
| 1045 | continue; | |||
| 1046 | } | |||
| 1047 | if (SLIST_EMPTY(&delhead)(((&delhead)->slh_first) == ((void *)0))) { | |||
| 1048 | if ((d1 = malloc(sizeof(struct delentry))) | |||
| 1049 | == NULL((void *)0)) | |||
| 1050 | return (ABORT2); | |||
| 1051 | if ((d1->fn = strdup(p)) == NULL((void *)0)) { | |||
| 1052 | free(d1); | |||
| 1053 | return (ABORT2); | |||
| 1054 | } | |||
| 1055 | SLIST_INSERT_HEAD(&delhead, d1, entry)do { (d1)->entry.sle_next = (&delhead)->slh_first; ( &delhead)->slh_first = (d1); } while (0); | |||
| 1056 | } else { | |||
| 1057 | if ((d2 = malloc(sizeof(struct delentry))) | |||
| 1058 | == NULL((void *)0)) { | |||
| 1059 | free(d1->fn); | |||
| 1060 | free(d1); | |||
| 1061 | return (ABORT2); | |||
| 1062 | } | |||
| 1063 | if ((d2->fn = strdup(p)) == NULL((void *)0)) { | |||
| 1064 | free(d1->fn); | |||
| 1065 | free(d1); | |||
| 1066 | free(d2); | |||
| 1067 | return (ABORT2); | |||
| 1068 | } | |||
| 1069 | if (!d1) | |||
| 1070 | SLIST_INSERT_HEAD(&delhead, d2, entry)do { (d2)->entry.sle_next = (&delhead)->slh_first; ( &delhead)->slh_first = (d2); } while (0); | |||
| 1071 | else | |||
| 1072 | SLIST_INSERT_AFTER(d1, d2, entry)do { (d2)->entry.sle_next = (d1)->entry.sle_next; (d1)-> entry.sle_next = (d2); } while (0); | |||
| 1073 | d1 = d2; | |||
| 1074 | } | |||
| 1075 | ret = TRUE1; | |||
| 1076 | nlp = lforw(lp)((lp)->l_fp); | |||
| 1077 | } | |||
| 1078 | return (ret); | |||
| 1079 | } | |||
| 1080 | ||||
| 1081 | int | |||
| 1082 | dired_jump(int f, int n) | |||
| 1083 | { | |||
| 1084 | struct buffer *bp; | |||
| 1085 | const char *modename; | |||
| 1086 | char dname[NFILEN1024], *fname; | |||
| 1087 | int ret, i; | |||
| 1088 | ||||
| 1089 | /* | |||
| 1090 | * We use fundamental mode in dired, so just check we aren't in | |||
| 1091 | * dired mode for this specific function. Seems like a corner | |||
| 1092 | * case at the moment. | |||
| 1093 | */ | |||
| 1094 | for (i = 0; i <= curbp->b_nmodes; i++) { | |||
| 1095 | modename = curbp->b_modes[i]->p_name; | |||
| 1096 | if (strncmp(modename, "dired", 5) == 0) | |||
| 1097 | return (dobeep_msg("In dired mode already")); | |||
| 1098 | } | |||
| 1099 | ||||
| 1100 | if (getbufcwd(dname, sizeof(dname)) != TRUE1) | |||
| 1101 | return (FALSE0); | |||
| 1102 | ||||
| 1103 | fname = curbp->b_fname; | |||
| 1104 | ||||
| 1105 | if ((bp = dired_(dname)) == NULL((void *)0)) | |||
| 1106 | return (FALSE0); | |||
| 1107 | curbp = bp; | |||
| 1108 | ||||
| 1109 | ret = showbuffer(bp, curwp, WFFULL0x08 | WFMODE0x10); | |||
| 1110 | if (ret != TRUE1) | |||
| 1111 | return ret; | |||
| 1112 | ||||
| 1113 | fname = adjustname(fname, TRUE1); | |||
| 1114 | if (fname != NULL((void *)0)) | |||
| 1115 | gotofile(fname); | |||
| 1116 | ||||
| 1117 | return (TRUE1); | |||
| 1118 | } | |||
| 1119 | ||||
| 1120 | int | |||
| 1121 | d_gotofile(int f, int n) | |||
| 1122 | { | |||
| 1123 | size_t lenfpath; | |||
| 1124 | char fpath[NFILEN1024]; | |||
| 1125 | char *fpth, *fnp = NULL((void *)0); | |||
| 1126 | ||||
| 1127 | if (getbufcwd(fpath, sizeof(fpath)) != TRUE1) | |||
| ||||
| 1128 | fpath[0] = '\0'; | |||
| 1129 | lenfpath = strlen(fpath); | |||
| 1130 | fnp = eread("Goto file: ", fpath, NFILEN1024, | |||
| 1131 | EFNEW0x0008 | EFCR0x0010 | EFFILE0x0004 | EFDEF0x0020); | |||
| 1132 | if (fnp == NULL((void *)0)) | |||
| 1133 | return (ABORT2); | |||
| 1134 | else if (fnp[0] == '\0') | |||
| 1135 | return (FALSE0); | |||
| 1136 | ||||
| 1137 | fpth = adjustname(fpath, TRUE1); /* Removes last '/' if dir... */ | |||
| 1138 | if (fpth == NULL((void *)0) || strlen(fpth) == lenfpath - 1) { /* ...hence -1. */ | |||
| 1139 | ewprintf("No file to find"); /* Current directory given so */ | |||
| 1140 | return (TRUE1); /* return at present location. */ | |||
| 1141 | } | |||
| 1142 | return gotofile(fpth); | |||
| 1143 | } | |||
| 1144 | ||||
| 1145 | int | |||
| 1146 | gotofile(char *fpth) | |||
| 1147 | { | |||
| 1148 | struct line *lp, *nlp; | |||
| 1149 | char fname[NFILEN1024]; | |||
| 1150 | char *p; | |||
| 1151 | int tmp; | |||
| 1152 | ||||
| 1153 | (void)xbasename(fname, fpth, NFILEN1024); | |||
| 1154 | tmp = 0; | |||
| 1155 | for (lp = bfirstlp(curbp)((((curbp)->b_headp)->l_fp)); lp != curbp->b_headp; lp = nlp) { | |||
| 1156 | tmp++; | |||
| 1157 | if ((p = findfname(lp, p)) == NULL((void *)0)) { | |||
| ||||
| 1158 | nlp = lforw(lp)((lp)->l_fp); | |||
| 1159 | continue; | |||
| 1160 | } | |||
| 1161 | if (strcmp(fname, p) == 0) { | |||
| 1162 | curwp->w_dotp = lp; | |||
| 1163 | curwp->w_dotline = tmp; | |||
| 1164 | (void)d_warpdot(curwp->w_dotp, &curwp->w_doto); | |||
| 1165 | tmp--; | |||
| 1166 | break; | |||
| 1167 | } | |||
| 1168 | nlp = lforw(lp)((lp)->l_fp); | |||
| 1169 | } | |||
| 1170 | if (tmp == curbp->b_lines - 1) { | |||
| 1171 | ewprintf("File not found %s", fname); | |||
| 1172 | return (FALSE0); | |||
| 1173 | } else { | |||
| 1174 | eerase(); | |||
| 1175 | return (TRUE1); | |||
| 1176 | } | |||
| 1177 | } | |||
| 1178 | ||||
| 1179 | /* | |||
| 1180 | * Look for and extract a file name on a dired buffer line. | |||
| 1181 | */ | |||
| 1182 | char * | |||
| 1183 | findfname(struct line *lp, char *fn) | |||
| 1184 | { | |||
| 1185 | int start; | |||
| 1186 | ||||
| 1187 | (void)d_warpdot(lp, &start); | |||
| 1188 | if (start < 1) | |||
| 1189 | return NULL((void *)0); | |||
| 1190 | fn = &lp->l_text[start]; | |||
| 1191 | return fn; | |||
| 1192 | } |