diff options
Diffstat (limited to 'src/LYLocal.c')
-rw-r--r-- | src/LYLocal.c | 294 |
1 files changed, 180 insertions, 114 deletions
diff --git a/src/LYLocal.c b/src/LYLocal.c index af1430d6..a2aa3d5b 100644 --- a/src/LYLocal.c +++ b/src/LYLocal.c @@ -1,5 +1,5 @@ /* - * $LynxId: LYLocal.c,v 1.95 2009/08/26 10:47:37 tom Exp $ + * $LynxId: LYLocal.c,v 1.104 2009/11/22 16:23:43 tom Exp $ * * Routines to manipulate the local filesystem. * Written by: Rick Mallett, Carleton University @@ -103,12 +103,30 @@ struct dired_menu { #define DE_FILE 3 #define DE_SYMLINK 4 char *sfx; + const char *c_sfx; char *link; + const char *c_link; char *rest; + const char *c_rest; char *href; + const char *c_href; struct dired_menu *next; }; +#define GetDiredSuffix(p) ((p)->sfx ? (p)->sfx : (p)->c_sfx) +#define GetDiredLink(p) ((p)->link ? (p)->link : (p)->c_link) +#define GetDiredRest(p) ((p)->rest ? (p)->rest : (p)->c_rest) +#define GetDiredHref(p) ((p)->href ? (p)->href : (p)->c_href) + +#undef DATA +#define DATA(cond, sfx, link, rest, href) { \ + cond, \ + NULL, sfx, \ + NULL, link, \ + NULL, rest, \ + NULL, href, \ + NULL } + static struct dired_menu *menu_head = NULL; static struct dired_menu defmenu[] = { @@ -119,149 +137,150 @@ static struct dired_menu defmenu[] = { * discarded entirely. */ #ifdef SUPPORT_CHDIR -{ 0, "", "Change directory", - "", "LYNXDIRED://CHDIR", NULL }, +DATA( 0, "", "Change directory", + "", "LYNXDIRED://CHDIR"), #endif -{ 0, "", "New File", -"(in current directory)", "LYNXDIRED://NEW_FILE%d", NULL }, +DATA( 0, "", "New File", +"(in current directory)", "LYNXDIRED://NEW_FILE%d"), -{ 0, "", "New Directory", -"(in current directory)", "LYNXDIRED://NEW_FOLDER%d", NULL }, +DATA( 0, "", "New Directory", +"(in current directory)", "LYNXDIRED://NEW_FOLDER%d"), #ifdef OK_INSTALL -{ DE_FILE, "", "Install", -"selected file to new location", "LYNXDIRED://INSTALL_SRC%p", NULL }, +DATA( DE_FILE, "", "Install", +"selected file to new location", "LYNXDIRED://INSTALL_SRC%p"), /* The following (installing a directory) doesn't work for me, at least with the "install" from GNU fileutils 4.0. I leave it in anyway, in case one compiles with INSTALL_PATH / INSTALL_ARGS defined to some other command for which it works (like a script, or maybe "cp -a"). - kw */ -{ DE_DIR, "", "Install", -"selected directory to new location", "LYNXDIRED://INSTALL_SRC%p", NULL }, +DATA( DE_DIR, "", "Install", +"selected directory to new location", "LYNXDIRED://INSTALL_SRC%p"), #endif /* OK_INSTALL */ -{ DE_FILE, "", "Modify File Name", -"(of current selection)", "LYNXDIRED://MODIFY_NAME%p", NULL }, -{ DE_DIR, "", "Modify Directory Name", -"(of current selection)", "LYNXDIRED://MODIFY_NAME%p", NULL }, +DATA( DE_FILE, "", "Modify File Name", +"(of current selection)", "LYNXDIRED://MODIFY_NAME%p"), +DATA( DE_DIR, "", "Modify Directory Name", +"(of current selection)", "LYNXDIRED://MODIFY_NAME%p"), #ifdef S_IFLNK -{ DE_SYMLINK, "", "Modify Name", -"(of selected symbolic link)", "LYNXDIRED://MODIFY_NAME%p", NULL }, +DATA( DE_SYMLINK, "", "Modify Name", +"(of selected symbolic link)", "LYNXDIRED://MODIFY_NAME%p"), #endif /* S_IFLNK */ #ifdef OK_PERMIT -{ DE_FILE, "", "Modify File Permissions", -"(of current selection)", "LYNXDIRED://PERMIT_SRC%p", NULL }, -{ DE_DIR, "", "Modify Directory Permissions", -"(of current selection)", "LYNXDIRED://PERMIT_SRC%p", NULL }, +DATA( DE_FILE, "", "Modify File Permissions", +"(of current selection)", "LYNXDIRED://PERMIT_SRC%p"), +DATA( DE_DIR, "", "Modify Directory Permissions", +"(of current selection)", "LYNXDIRED://PERMIT_SRC%p"), #endif /* OK_PERMIT */ -{ DE_FILE, "", "Change Location", -"(of selected file)" , "LYNXDIRED://MODIFY_LOCATION%p", NULL }, -{ DE_DIR, "", "Change Location", -"(of selected directory)", "LYNXDIRED://MODIFY_LOCATION%p", NULL }, +DATA( DE_FILE, "", "Change Location", +"(of selected file)" , "LYNXDIRED://MODIFY_LOCATION%p"), +DATA( DE_DIR, "", "Change Location", +"(of selected directory)", "LYNXDIRED://MODIFY_LOCATION%p"), #ifdef S_IFLNK -{ DE_SYMLINK, "", "Change Location", -"(of selected symbolic link)", "LYNXDIRED://MODIFY_LOCATION%p", NULL }, +DATA( DE_SYMLINK, "", "Change Location", +"(of selected symbolic link)", "LYNXDIRED://MODIFY_LOCATION%p"), #endif /* S_IFLNK */ -{ DE_FILE, "", "Remove File", - "(current selection)", "LYNXDIRED://REMOVE_SINGLE%p", NULL }, -{ DE_DIR, "", "Remove Directory", - "(current selection)", "LYNXDIRED://REMOVE_SINGLE%p", NULL }, +DATA( DE_FILE, "", "Remove File", + "(current selection)", "LYNXDIRED://REMOVE_SINGLE%p"), +DATA( DE_DIR, "", "Remove Directory", + "(current selection)", "LYNXDIRED://REMOVE_SINGLE%p"), #ifdef S_IFLNK -{ DE_SYMLINK, "", "Remove Symbolic Link", - "(current selection)", "LYNXDIRED://REMOVE_SINGLE%p", NULL }, +DATA( DE_SYMLINK, "", "Remove Symbolic Link", + "(current selection)", "LYNXDIRED://REMOVE_SINGLE%p"), #endif /* S_IFLNK */ #if defined(OK_UUDECODE) && !defined(ARCHIVE_ONLY) -{ DE_FILE, "", "UUDecode", - "(current selection)", "LYNXDIRED://UUDECODE%p", NULL }, +DATA( DE_FILE, "", "UUDecode", + "(current selection)", "LYNXDIRED://UUDECODE%p"), #endif /* OK_UUDECODE && !ARCHIVE_ONLY */ #if defined(OK_TAR) && !defined(ARCHIVE_ONLY) -{ DE_FILE, EXT_TAR_Z, "Expand", - "(current selection)", "LYNXDIRED://UNTAR_Z%p", NULL }, +DATA( DE_FILE, EXT_TAR_Z, "Expand", + "(current selection)", "LYNXDIRED://UNTAR_Z%p"), #endif /* OK_TAR && !ARCHIVE_ONLY */ #if defined(OK_TAR) && defined(OK_GZIP) && !defined(ARCHIVE_ONLY) -{ DE_FILE, ".tar.gz", "Expand", - "(current selection)", "LYNXDIRED://UNTAR_GZ%p", NULL }, +DATA( DE_FILE, ".tar.gz", "Expand", + "(current selection)", "LYNXDIRED://UNTAR_GZ%p"), -{ DE_FILE, ".tgz", "Expand", - "(current selection)", "LYNXDIRED://UNTAR_GZ%p", NULL }, +DATA( DE_FILE, ".tgz", "Expand", + "(current selection)", "LYNXDIRED://UNTAR_GZ%p"), #endif /* OK_TAR && OK_GZIP && !ARCHIVE_ONLY */ #ifndef ARCHIVE_ONLY -{ DE_FILE, EXT_Z, "Uncompress", - "(current selection)", "LYNXDIRED://DECOMPRESS%p", NULL }, +DATA( DE_FILE, EXT_Z, "Uncompress", + "(current selection)", "LYNXDIRED://DECOMPRESS%p"), #endif /* ARCHIVE_ONLY */ #if defined(OK_GZIP) && !defined(ARCHIVE_ONLY) -{ DE_FILE, ".gz", "Uncompress", - "(current selection)", "LYNXDIRED://UNGZIP%p", NULL }, +DATA( DE_FILE, ".gz", "Uncompress", + "(current selection)", "LYNXDIRED://UNGZIP%p"), #endif /* OK_GZIP && !ARCHIVE_ONLY */ #if defined(OK_ZIP) && !defined(ARCHIVE_ONLY) -{ DE_FILE, ".zip", "Uncompress", - "(current selection)", "LYNXDIRED://UNZIP%p", NULL }, +DATA( DE_FILE, ".zip", "Uncompress", + "(current selection)", "LYNXDIRED://UNZIP%p"), #endif /* OK_ZIP && !ARCHIVE_ONLY */ #if defined(OK_TAR) && !defined(ARCHIVE_ONLY) -{ DE_FILE, ".tar", "UnTar", - "(current selection)", "LYNXDIRED://UNTAR%p", NULL }, +DATA( DE_FILE, ".tar", "UnTar", + "(current selection)", "LYNXDIRED://UNTAR%p"), #endif /* OK_TAR && !ARCHIVE_ONLY */ #ifdef OK_TAR -{ DE_DIR, "", "Tar", - "(current selection)", "LYNXDIRED://TAR%p", NULL }, +DATA( DE_DIR, "", "Tar", + "(current selection)", "LYNXDIRED://TAR%p"), #endif /* OK_TAR */ #if defined(OK_TAR) && defined(OK_GZIP) -{ DE_DIR, "", "Tar and compress", - "(using GNU gzip)", "LYNXDIRED://TAR_GZ%p", NULL }, +DATA( DE_DIR, "", "Tar and compress", + "(using GNU gzip)", "LYNXDIRED://TAR_GZ%p"), #endif /* OK_TAR && OK_GZIP */ #if defined(OK_TAR) && defined(USE_COMPRESS) -{ DE_DIR, "", "Tar and compress", - "(using compress)", "LYNXDIRED://TAR_Z%p", NULL }, +DATA( DE_DIR, "", "Tar and compress", + "(using compress)", "LYNXDIRED://TAR_Z%p"), #endif /* OK_TAR && USE_COMPRESS */ #ifdef OK_ZIP -{ DE_DIR, "", "Package and compress", - "(using zip)", "LYNXDIRED://ZIP%p", NULL }, +DATA( DE_DIR, "", "Package and compress", + "(using zip)", "LYNXDIRED://ZIP%p"), #endif /* OK_ZIP */ -{ DE_FILE, "", "Compress", - "(using Unix compress)", "LYNXDIRED://COMPRESS%p", NULL }, +DATA( DE_FILE, "", "Compress", + "(using Unix compress)", "LYNXDIRED://COMPRESS%p"), #ifdef OK_GZIP -{ DE_FILE, "", "Compress", - "(using gzip)", "LYNXDIRED://GZIP%p", NULL }, +DATA( DE_FILE, "", "Compress", + "(using gzip)", "LYNXDIRED://GZIP%p"), #endif /* OK_GZIP */ #ifdef OK_ZIP -{ DE_FILE, "", "Compress", - "(using zip)", "LYNXDIRED://ZIP%p", NULL }, +DATA( DE_FILE, "", "Compress", + "(using zip)", "LYNXDIRED://ZIP%p"), #endif /* OK_ZIP */ -{ DE_TAG, "", "Move all tagged items to another location.", - "", "LYNXDIRED://MOVE_TAGGED%d", NULL }, +DATA( DE_TAG, "", "Move all tagged items to another location.", + "", "LYNXDIRED://MOVE_TAGGED%d"), #ifdef OK_INSTALL -{ DE_TAG, "", "Install tagged files into another directory.", - "", "LYNXDIRED://INSTALL_SRC%00", NULL }, +DATA( DE_TAG, "", "Install tagged files into another directory.", + "", "LYNXDIRED://INSTALL_SRC%00"), #endif -{ DE_TAG, "", "Remove all tagged files and directories.", - "", "LYNXDIRED://REMOVE_TAGGED", NULL }, +DATA( DE_TAG, "", "Remove all tagged files and directories.", + "", "LYNXDIRED://REMOVE_TAGGED"), -{ DE_TAG, "", "Untag all tagged files and directories.", - "", "LYNXDIRED://CLEAR_TAGGED", NULL }, +DATA( DE_TAG, "", "Untag all tagged files and directories.", + "", "LYNXDIRED://CLEAR_TAGGED"), -{ 0, NULL, NULL, - NULL, NULL, NULL } +DATA( 0, NULL, NULL, + NULL, NULL), }; +#undef DATA /* *INDENT-ON* */ static BOOLEAN cannot_stat(const char *name) @@ -278,11 +297,42 @@ static BOOLEAN cannot_stat(const char *name) static BOOLEAN ok_stat(const char *name, struct stat *sb) { + BOOLEAN rc = TRUE; + CTRACE((tfp, "testing ok_stat(%s)\n", name)); if (!OK_STAT(name, sb)) { - return cannot_stat(name); +#ifdef DOSPATH + size_t len = strlen(name); + + /* + * If a path ends with '\' or ':', we can guess that it may be + * a directory name. Adding a '.' (after a '\') will produce a + * pathname that stat() will accept as a directory name. + */ + if (len != 0 && (name[len - 1] == '\\' || name[len - 1] == ':')) { + char *temp = malloc(len + 3); + + if (temp != 0) { + strcpy(temp, name); + if (temp[len - 1] == '\\') { + strcpy(temp + len, "."); + } else { + strcpy(temp + len, "\\."); + } + rc = OK_STAT(temp, sb); + free(temp); + } else { + rc = FALSE; + } + } else +#endif + rc = FALSE; } - return TRUE; + + if (rc == FALSE) + rc = cannot_stat(name); + + return rc; } #ifdef HAVE_LSTAT @@ -335,13 +385,13 @@ static int LYExecv(const char *path, { int rc = 0; -#if defined(VMS) || defined(_WINDOWS) +#if defined(VMS) CTRACE((tfp, "LYExecv: Called inappropriately! (path=%s)\n", path)); #else int n; char *tmpbuf = 0; -#ifdef __DJGPP__ +#if defined(__DJGPP__) || defined(_WINDOWS) stop_curses(); HTSprintf0(&tmpbuf, "%s", path); for (n = 1; argv[n] != 0; n++) @@ -425,6 +475,7 @@ static int LYExecv(const char *path, FREE(tmpbuf); } #endif /* VMS || _WINDOWS */ + CTRACE((tfp, "LYexecv ->%d\n", rc)); return (rc); } @@ -449,6 +500,7 @@ static int make_directory(char *path) #else code = mkdir(path, 0777) ? -1 : 1; #endif + CTRACE((tfp, "builtin mkdir ->%d\n\t%s\n", code, path)); } return (code); } @@ -471,6 +523,7 @@ static int remove_file(char *path) FREE(tmpbuf); } else { code = remove(path) ? -1 : 1; + CTRACE((tfp, "builtin remove ->%d\n\t%s\n", code, path)); } return (code); } @@ -492,6 +545,7 @@ static int remove_directory(char *path) FREE(tmpbuf); } else { code = rmdir(path) ? -1 : 1; + CTRACE((tfp, "builtin rmdir ->%d\n\t%s\n", code, path)); } return (code); } @@ -514,12 +568,13 @@ static int touch_file(char *path) } else { FILE *fp; - if ((fp = fopen(path, "w")) != 0) { + if ((fp = fopen(path, BIN_W)) != 0) { fclose(fp); code = 1; } else { code = -1; } + CTRACE((tfp, "builtin touch ->%d\n\t%s\n", code, path)); } return (code); } @@ -551,9 +606,15 @@ static int move_file(char *source, char *target) CTRACE((tfp, "move_file source=%s, target=%s\n", source, target)); target = actual; } - if ((code = rename(source, target)) != 0) - if ((code = LYCopyFile(source, target)) >= 0) + code = rename(source, target); + CTRACE((tfp, "builtin move ->%d\n\tsource=%s\n\ttarget=%s\n", + code, source, target)); + if (code != 0) { /* it failed */ + if ((code = LYCopyFile(source, target)) >= 0) { code = remove(source); + CTRACE((tfp, "...remove source after copying ->%d\n", code)); + } + } if (code == 0) code = 1; if (actual != target) { @@ -732,11 +793,11 @@ static int modify_tagged(char *testpath) * If path is relative, prefix it with current location. */ if (!LYIsPathSep(given_target[0])) { - StrAllocCopy(dst_path, testpath); + dst_path = HTLocalName(testpath); LYAddPathSep(&dst_path); StrAllocCat(dst_path, given_target); } else { - StrAllocCopy(dst_path, given_target); + dst_path = HTLocalName(given_target); } if (!ok_stat(dst_path, &dst_info)) { @@ -866,12 +927,7 @@ static int modify_location(char *testpath) * Change the location of the file or directory. */ if (S_ISDIR(dir_info.st_mode)) { - if (HTGetProgramPath(ppMV) != NULL) { - cp = gettext("Enter new location for directory: "); - } else { - HTAlert(COULD_NOT_ACCESS_DIR); - return 0; - } + cp = gettext("Enter new location for directory: "); } else if (S_ISREG(dir_info.st_mode)) { cp = gettext("Enter new location for file: "); } else { @@ -1239,9 +1295,10 @@ static int permit_location(char *destpath, char *srcpath, char **newpath) { + int code = 0; + #ifndef UNIX HTAlert(gettext("Sorry, don't know how to permit non-UNIX files yet.")); - return (0); #else static char tempfile[LY_MAXPATH] = "\0"; char *cp; @@ -1264,14 +1321,14 @@ static int permit_location(char *destpath, */ if (!ok_lstat(srcpath, &dir_info) || !ok_file_or_dir(&dir_info)) - return 0; + return code; user_filename = LYPathLeaf(srcpath); LYRemoveTemp(tempfile); if ((fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w")) == NULL) { HTAlert(gettext("Unable to open permit options file")); - return (0); + return (code); } /* @@ -1358,7 +1415,7 @@ static int permit_location(char *destpath, LYCloseTempFP(fp0); LYforce_no_cache = TRUE; - return (PERMIT_FORM_RESULT); /* Special flag for LYMainLoop */ + code = PERMIT_FORM_RESULT; /* Special flag for LYMainLoop */ } else { /* The form being activated. */ mode_t new_mode = 0; @@ -1375,24 +1432,24 @@ static int permit_location(char *destpath, CTRACE((tfp, "permit_location: called for <%s>.\n", (destpath ? destpath : "NULL URL pointer"))); - return 0; + return code; } cp = destpath; while (*cp != '\0' && *cp != '?') { /* Find filename */ cp++; } if (*cp == '\0') { - return (0); /* Nothing to permit. */ + return (code); /* Nothing to permit. */ } *cp++ = '\0'; /* Null terminate file name and start working on the masks. */ /* Will now operate only on filename part. */ if ((destpath = HTURLPath_toFile(destpath, TRUE, FALSE)) == 0) - return (0); + return (code); if (strlen(destpath) >= LY_MAXPATH) { FREE(destpath); - return (0); + return (code); } strcpy(tmpdst, destpath); FREE(destpath); @@ -1409,7 +1466,7 @@ static int permit_location(char *destpath, fprintf(stderr, "%s\n", INVALID_PERMIT_URL); CTRACE((tfp, "permit_location: called for file '%s'.\n", destpath)); - return 0; + return code; } /* @@ -1418,7 +1475,7 @@ static int permit_location(char *destpath, destpath = strip_trailing_slash(destpath); if (!ok_stat(destpath, &dir_info) || !ok_file_or_dir(&dir_info)) { - return 0; + return code; } /* @@ -1447,11 +1504,11 @@ static int permit_location(char *destpath, new_mode |= mask; } else { HTAlert(gettext("Invalid mode format.")); - return 0; + return code; } } else { HTAlert(gettext("Invalid syntax format.")); - return 0; + return code; } cp = cr; @@ -1460,6 +1517,7 @@ static int permit_location(char *destpath, /* * Call chmod(). */ + code = 1; if ((program = HTGetProgramPath(ppCHMOD)) != NULL) { char *args[5]; char amode[10]; @@ -1472,18 +1530,21 @@ static int permit_location(char *destpath, args[2] = destpath; args[3] = (char *) 0; if (LYExecv(program, args, tmpbuf) <= 0) { - FREE(tmpbuf); - return (-1); + code = -1; } FREE(tmpbuf); } else { - if (chmod(destpath, new_mode) < 0) - return (-1); + if (chmod(destpath, new_mode) < 0) { + code = -1; + } + CTRACE((tfp, "builtin chmod %.4o ->%d\n\t%s\n", + new_mode, code, destpath)); } - LYforce_no_cache = TRUE; /* Force update of dired listing. */ - return 1; + if (code == 1) + LYforce_no_cache = TRUE; /* Force update of dired listing. */ } #endif /* !UNIX */ + return code; } #endif /* OK_PERMIT */ @@ -1833,7 +1894,7 @@ int local_dired(DocInfo *doc) handle_LYK_CHDIR(); do_pop_doc = FALSE; #endif - arg = "blah"; /* do something to avoid cc's complaints */ + arg = 0; /* do something to avoid cc's complaints */ } else if ((arg = match_op("NEW_FILE", line)) != 0) { if (create_file(arg) > 0) LYforce_no_cache = TRUE; @@ -1937,6 +1998,7 @@ int local_dired(DocInfo *doc) int dired_options(DocInfo *doc, char **newfile) { static char tempfile[LY_MAXPATH]; + const char *my_suffix; char *path; char *dir; lynx_list_item_type *nxt; @@ -2028,7 +2090,7 @@ int dired_options(DocInfo *doc, char **newfile) * If menu_head is NULL then use defaults and link them together now. */ if (menu_head == NULL) { - for (mp = defmenu; mp->href != NULL; mp++) + for (mp = defmenu; GetDiredHref(mp) != NULL; mp++) mp->next = (mp + 1); (--mp)->next = NULL; menu_head = defmenu; @@ -2050,18 +2112,22 @@ int dired_options(DocInfo *doc, char **newfile) (!*path || !S_ISLNK(dir_info.st_mode))) continue; #endif - if (*mp->sfx && - (strlen(path) < strlen(mp->sfx) || - strcmp(mp->sfx, &path[(strlen(path) - strlen(mp->sfx))]) != 0)) + my_suffix = GetDiredSuffix(mp); + if (non_empty(my_suffix) && + (strlen(path) < strlen(my_suffix) || + strcmp(my_suffix, &path[(strlen(path) - strlen(my_suffix))]) != 0)) continue; dir_url = HTEscape(dir, URL_PATH); path_url = HTEscape(path, URL_PATH); fprintf(fp0, "<a href=\"%s", - render_item(mp->href, path_url, dir_url, buf, sizeof(buf), YES)); + render_item(GetDiredHref(mp), + path_url, dir_url, buf, sizeof(buf), YES)); fprintf(fp0, "\">%s</a> ", - render_item(mp->link, path, dir, buf, sizeof(buf), NO)); + render_item(GetDiredLink(mp), + path, dir, buf, sizeof(buf), NO)); fprintf(fp0, "%s<br>\n", - render_item(mp->rest, path, dir, buf, sizeof(buf), NO)); + render_item(GetDiredRest(mp), + path, dir, buf, sizeof(buf), NO)); FREE(dir_url); FREE(path_url); } |