#include "ftptool.h"
#pragma ident "@(#)change_dir.c 1.8 94/06/27"
int dirlastmtime;
#ifdef USE_PROTOTYPES
int checkdir(char *dirname)
#else
int checkdir(dirname)
char *dirname;
#endif
{
struct stat buf;
if (lstat(dirname, &buf) == -1) {
if (errno == ENOENT)
return (ENOENT);
return (1);
}
if (buf.st_mtime > local_dircache.first->mtime) {
return (1);
}
return (0);
}
#ifdef USE_PROTOTYPES
int dirwasmodified(void)
#else
int dirwasmodified()
#endif
{
int error;
char *dirname = local_dircache.first->name;
if (cache_lookup(&local_dircache, dirname) == NULL)
return (0);
/* first now */
error = checkdir(dirname);
if (error == ENOENT) {
if (xv_get(local_window.frame, XV_SHOW) == FALSE) {
xv_set(local_window.frame,
XV_SHOW, TRUE,
NULL);
}
local_footer_message(
"Current directory was deleted. Changing to /tmp.");
clear_slist(local_window.list);
xv_set(local_window.list,
XV_SHOW, TRUE,
NULL);
dircache_delete(&local_dircache, dirname);
change_local_dir("/tmp", 0);
return (1);
} else if (error != 0) {
local_footer_message(
"Current directory was modified. Rereading.");
if (xv_get(local_window.frame, XV_SHOW) == FALSE) {
xv_set(local_window.frame,
XV_SHOW, TRUE,
NULL);
}
clear_slist(local_window.list);
xv_set(local_window.list,
XV_SHOW, TRUE,
NULL);
dircache_delete(&local_dircache, dirname);
change_local_dir(dirname, 0);
return (1);
}
return (0);
}
#ifdef USE_PROTOTYPES
int change_local_dir(char *s, int force)
#else
int change_local_dir(s, force)
char *s;
int force;
#endif
{
static char cld[MAXPATHLEN + 2];
#ifndef __FreeBSD__
extern char *sys_errlist[];
#endif
struct dirlist *head = NULL;
int wasinactive;
int rval = 0;
int error;
char *dir = NULL;
#ifndef ultrix
#if defined(SYSV) || defined(SYSV386)
struct statvfs fsbuf;
#else
struct statfs fsbuf;
#endif
#else
struct fs_data fsbuf;
#endif
wasinactive = xv_get(local_window.list, PANEL_INACTIVE);
if (wasinactive == FALSE) {
xv_set(local_window.list,
PANEL_INACTIVE, TRUE,
NULL);
}
cursor_busy();
local_footer_message("Reading directory...");
local_right_footer_message("");
dir = s;
if (dir == NULL) {
fprintf(stderr, "out of memory\n");
goto out;
}
if (chdir(dir) == -1) {
if (errno == ENOENT) {
if ((rval = ask_make_dir(dir)) != 0) {
if (rval == -1) {
local_footer_message("");
/* user cancelled. */
goto out;
}
local_footer_message(
"Could not make directory: %s",
sys_errlist[rval]);
goto out;
}
if (chdir(dir) == -1) {
rval = errno;
local_footer_message(
"Could not change to directory: %s",
sys_errlist[rval]);
goto out;
}
} else {
rval = errno;
local_footer_message(
"Could not change to directory: %s",
sys_errlist[rval]);
goto out;
}
}
clear_slist(local_window.list);
local_list_ndirs = 0;
local_list_nfiles = 0;
local_list_nothers = 0;
change_local_list_menu();
if (getcwd(cld, sizeof (cld)) == NULL) {
/* Failure */
goto out;
}
xv_set(local_window.directory,
PANEL_VALUE, cld,
NULL);
#if defined(SYSV) || defined(SYSV386)
if (statvfs(cld, &fsbuf) == -1) {
sprintf(scratch, "statvfs failed: %s", sys_errlist[errno]);
}
#else
if (statfs(cld, &fsbuf) == -1) {
sprintf(scratch, "statfs failed: %s", sys_errlist[errno]);
}
#endif
else {
#ifndef ultrix
sprintf(scratch, "%d Kbytes (%d%% free)",
(int)(fsbuf.f_bsize / 1024.0 * fsbuf.f_bavail),
(int)(100.0 * fsbuf.f_bavail /
(fsbuf.f_blocks -
(fsbuf.f_bfree - fsbuf.f_bavail))));
#else
sprintf(scratch, "%d Kbytes (%d%% free)",
(int)(fsbuf.fd_req.bfreen),
(int)(100.0 * fsbuf.fd_req.bfreen /
(fsbuf.fd_req.btot -
(fsbuf.fd_req.bfree - fsbuf.fd_req.bfreen))));
#endif
}
xv_set(local_window.space,
PANEL_LABEL_STRING, scratch,
NULL);
if (force)
dircache_delete(&local_dircache, cld);
head = cache_lookup(&local_dircache, cld);
if (head == NULL) {
/* cache miss */
head = read_local_dir(cld);
if (head == NULL) {
fprintf(stderr, "Out of memory\n");
rval = 1;
goto out;
}
/* add to cache */
dircache_add(&local_dircache, cld, head);
local_dircache.first->mtime = dirlastmtime;
} else if ((error = checkdir(cld)) != 0) {
dircache_delete(&local_dircache, cld);
if (error == ENOENT) {
local_footer_message("%s does not exist.", cld);
goto out;
}
/* else reread */
head = read_local_dir(cld);
if (head == NULL) {
fprintf(stderr, "Out of memory\n");
rval = 1;
goto out;
}
/* add to cache */
dircache_add(&local_dircache, cld, head);
local_dircache.first->mtime = dirlastmtime;
}
dirlist_to_slist(local_window.list, head);
local_show_items();
local_footer_message("");
out:
cursor_normal();
if (wasinactive == FALSE) {
xv_set(local_window.list,
PANEL_INACTIVE, FALSE,
NULL);
}
XFlush(dpy);
return (rval);
}
#ifdef USE_PROTOTYPES
int change_remote_dir(char *s, int force)
#else
int change_remote_dir(s, force)
char *s;
int force;
#endif
{
char *ftperr;
char crd[MAXPATHLEN + 1];
struct dirlist *head = NULL;
int wasinactive;
char *dir = NULL;
int rval = 0;
int pwdfailed = 0;
char *quote;
wasinactive = xv_get(base_window.list, PANEL_INACTIVE);
if (wasinactive == FALSE) {
xv_set(base_window.list,
PANEL_INACTIVE, TRUE,
NULL);
}
if (ping_server())
goto out;
cursor_busy();
/* send cd command */
footer_message("Reading directory...");
right_footer_message("");
dir = strdup(s);
if (dir == NULL)
goto out;
if (!strcmp(dir, "..")) {
if (up_one_level())
goto out;
} else if (strcmp(dir, ".")) {
extern int code;
code = -1;
command("CWD %s", dir);
/* success */
/*
* 250 CWD command successful.
* 200 CWD command successful (OS9)
*/
/* failure */
/*
* 451 error changing directory to <name>: 000:214 {000:###} (OS9)
* 550 k: No such file or directory
*/
if (code == 451) {
ftperr = ftp_error(' ', response_line);
footer_message("Error changing to %s. (Not a Directory)", dir);
rval = ENOTDIR;
goto out;
}
if (code == 550) {
ftperr = index(response_line, ':');
if (ftperr == NULL) {
rval = 1;
goto out;
}
if (!strncmp(ftperr, ": Not a directory.", 18)) {
footer_message("%s is not a directory.", dir);
rval = ENOTDIR;
goto out;
}
if ((rval = ask_make_remote_dir(dir)) != 0) {
if (rval == -1) {
footer_message("");
/* user cancelled */
goto out;
}
footer_message("Could not make directory.");
goto out;
}
command("CWD %s", dir);
if (code == 550) {
sprintf(scratch,
"%s: No such file or directory.", dir);
ftperr = ftp_error(' ', scratch);
footer_message(ftperr);
rval = 1;
goto out;
}
}
}
clear_slist(base_window.list);
remote_list_ndirs = 0;
remote_list_nfiles = 0;
remote_list_nothers = 0;
change_remote_list_menu();
/* set current directory */
if (command("PWD") == ERROR && code == 500) {
/*
footer_message("pwd not recognized.");
*/
/* try quote xpwd */
if (command("XPWD") == ERROR && code == 500) {
footer_message("pwd and xpwd not recognized.");
pwdfailed = 1;
}
}
/* response */
/*
* 25[17] "/" is current directory.
* 257 PWD: "/Print_Output" is current directory.
*
* Skip to first double-quote, since they seem to have that.
*/
crd[0] = '\0';
if (pwdfailed) {
force = 1;
} else if (!strncmp(response_line, "257", 3) ||
!strncmp(response_line, "251", 3)) {
quote = strchr(response_line, '\"');
if (quote != NULL)
sscanf (quote, "\"%[^\"]\"", crd);
} else {
footer_message("pwd or xpwd returned bad response.");
force = 1;
}
xv_set(base_window.directory,
PANEL_VALUE, crd,
NULL);
if (force)
dircache_delete(&remote_dircache, crd);
head = cache_lookup(&remote_dircache, crd);
if (head == NULL) {
/* cache miss */
head = read_remote_dir();
if (head == NULL) {
rval = ETIMEDOUT;
goto out;
}
dircache_add(&remote_dircache, crd, head);
}
dirlist_to_slist(base_window.list, head);
remote_show_items();
out:
if (rval == 0)
footer_message("");
cursor_normal();
if (dir)
free(dir);
/*
if (head)
free_dirlist(head);
*/
if (wasinactive == FALSE) {
xv_set(base_window.list,
PANEL_INACTIVE, FALSE,
NULL);
}
if (timedout)
timeout_disconnect();
XFlush(dpy);
return (rval);
}
#ifdef USE_PROTOTYPES
char *expand_dirname(char *arg)
#else
char *expand_dirname(arg)
char *arg;
#endif
{
char *slash;
char *lastpart = "";
char *path;
struct passwd *pwd;
char *firstpart = "";
char *s;
if (arg[0] == '/' || (arg[0] != '~' && arg[0] != '$')) {
path = strdup(arg);
return (path);
}
s = strdup(arg);
if (s == NULL)
return (NULL);
if ((slash = index(s, '/')) != NULL) {
*slash = 0;
lastpart = slash + 1;
}
switch (s[0]) {
case '~': /* ~ or ~user */
if (s[1] == '\0') {
pwd = getpwuid(getuid());
if (pwd == NULL) {
footer_message(
"You are unknown to the system.");
free(s);
return (NULL);
}
} else {
pwd = getpwnam(&s[1]);
if (pwd == NULL) {
footer_message("Unknown user %s.", &s[1]);
free(s);
return (NULL);
}
}
firstpart = pwd->pw_dir;
break;
case '$': /* Environment variable */
firstpart = getenv(&s[1]);
if (firstpart == NULL) {
footer_message("Unknown variable %s.", &s[1]);
free(s);
return (NULL);
}
break;
}
path = (char *)malloc((unsigned int)(strlen(firstpart) +
1 + strlen(lastpart) + 1));
if (path == NULL) {
footer_message("Memory allocation failed.");
free(s);
return (NULL);
}
if (lastpart[0] != '\0')
sprintf(path, "%s/%s", firstpart, lastpart);
else
strcpy(path, firstpart);
free(s);
return (path);
}
#ifdef USE_PROTOTYPES
int delete_local_dir(char *dir)
#else
int delete_local_dir(dir)
char *dir;
#endif
{
struct dirlist *head = NULL;
struct dirlist *tmp;
#ifndef __FreeBSD__
extern char *sys_errlist[];
#endif
int rval = 0;
if (chdir(dir) == -1) {
local_footer_message("Can not change to %s: %s",
dir, sys_errlist[errno]);
return (errno);
}
head = read_local_dir(".");
if (head == NULL) {
fprintf(stderr, "Out of memory\n");
rval = ENOMEM;
goto out;
}
for (tmp = head->next; tmp != NULL; tmp = tmp->next)
if (S_ISDIR(tmp->mode)) {
if ((rval = delete_local_dir(tmp->name)) != 0)
goto out;
} else if ((rval = delete_local_file(tmp->name, unlink)) != 0)
goto out;
out:
if (head)
free_dirlist(head);
if (chdir("..") == -1) {
local_footer_message("Can not cd ..: %s", sys_errlist[errno]);
return (errno);
}
/* delete parent */
if (rval == 0)
rval = delete_local_file(dir, rmdir);
return (rval);
}
#ifdef USE_PROTOTYPES
int delete_local_file(char *filename, int (*deletefunc)(const char *filename))
#else
int delete_local_file(filename, deletefunc)
char *filename;
int (*deletefunc)();
#endif
{
int answer;
#ifndef __FreeBSD__
extern char *sys_errlist[];
#endif
#ifdef XVIEW3
Xv_notice notice;
#endif
if (confirmdeletes) {
sprintf(scratch, "Really delete %s?", filename);
#ifdef XVIEW3
notice = xv_create(base_window.panel, NOTICE,
NOTICE_MESSAGE_STRINGS,
scratch,
NULL,
NOTICE_BUTTON_YES, "Cancel",
NOTICE_BUTTON_NO, "Delete",
NOTICE_STATUS, &answer,
XV_SHOW, TRUE,
NULL);
xv_destroy_safe(notice);
#else
answer = notice_prompt(base_window.panel, NULL,
NOTICE_MESSAGE_STRINGS,
scratch,
NULL,
NOTICE_BUTTON_YES, "Cancel",
NOTICE_BUTTON_NO, "Delete",
NULL);
#endif
} else
answer = NOTICE_NO;
if (answer == NOTICE_NO) {
local_footer_message("Deleting %s", filename);
if ((*deletefunc)(filename) == -1) {
local_footer_message("delete %s failed: %s", filename,
sys_errlist[errno]);
return (1);
}
return (0);
}
return (1); /* deletion aborted */
}
#ifdef USE_PROTOTYPES
int delete_remote_dir(char *dir)
#else
int delete_remote_dir(dir)
char *dir;
#endif
{
struct dirlist *head = NULL;
struct dirlist *tmp;
int rval = 0;
char *ftperr;
if (command("CWD %s", dir) == ERROR && code == 550) {
sprintf(scratch, "Can not change to %s", dir);
ftperr = ftp_error(' ', scratch);
footer_message(ftperr);
return (1);
}
head = read_remote_dir();
if (head == NULL) {
rval = ENOMEM;
goto out;
}
for (tmp = head->next; tmp != NULL; tmp = tmp->next)
if (S_ISDIR(tmp->mode)) {
if ((rval = delete_remote_dir(tmp->name)) != 0)
goto out;
} else if ((rval = delete_remote_file(tmp->name, "DELE")) != 0)
goto out;
out:
if (head)
free_dirlist(head);
if (up_one_level())
footer_message("Can not cd ..");
/* delete parent */
if (rval == 0)
rval = delete_remote_file(dir, "RMD");
return (rval);
}
#ifdef USE_PROTOTYPES
int delete_remote_file(char *filename, char *deletecmd)
#else
int delete_remote_file(filename, deletecmd)
char *filename;
char *deletecmd;
#endif
{
char *ftperr;
int answer;
#ifdef XVIEW3
Xv_notice notice;
#endif
if (confirmdeletes) {
sprintf(scratch, "Really delete %s?", filename);
#ifdef XVIEW3
notice = xv_create(base_window.panel, NOTICE,
NOTICE_MESSAGE_STRINGS,
scratch,
NULL,
NOTICE_BUTTON_YES, "Cancel",
NOTICE_BUTTON_NO, "Delete",
NOTICE_STATUS, &answer,
XV_SHOW, TRUE,
NULL);
xv_destroy_safe(notice);
#else
answer = notice_prompt(base_window.panel, NULL,
NOTICE_MESSAGE_STRINGS,
scratch,
NULL,
NOTICE_BUTTON_YES, "Cancel",
NOTICE_BUTTON_NO, "Delete",
NULL);
#endif
} else
answer = NOTICE_NO;
if (answer == NOTICE_NO) {
footer_message("Deleting %s", filename);
if (command("%s %s", deletecmd, filename) == ERROR) {
sprintf(scratch, "delete %s failed", filename);
ftperr = ftp_error(' ', scratch);
footer_message(ftperr);
return (1);
}
return (0);
}
return (1); /* deletion aborted */
}
#ifdef USE_PROTOTYPES
int up_one_level(void)
#else
int up_one_level()
#endif
{
static struct {
char *cmd;
char *msg;
} method[] = {
{ "CDUP", "CDUP failed, trying XCUP" },
{ "XCUP", "CDUP and XCUP failed, trying 'CD ..'" },
{ "CWD ..", "CDUP, XCUP, and 'CD ..' failed. Try manually." },
{ NULL, NULL }
};
if (which_up_cmd != -1) {
if (command(method[which_up_cmd].cmd) == ERROR &&
code >= 500) {
footer_message(method[which_up_cmd].msg);
which_up_cmd = -1;
} else
return (0);
}
for (which_up_cmd = 0; method[which_up_cmd].cmd; which_up_cmd++) {
if (command(method[which_up_cmd].cmd) == ERROR &&
code >= 500)
footer_message(method[which_up_cmd].msg);
else
return (0);
}
which_up_cmd = -1;
return (1);
}
syntax highlighted by Code2HTML, v. 0.9.1