#include "ftptool.h"
#pragma ident "@(#)dirlist.c 1.4 93/05/26"
#ifdef USE_PROTOTYPES
struct dirlist *new_dirlist(char *name, char *date, char *owner,
char *group, mode_t mode, size_t size)
#else
struct dirlist *new_dirlist(name, date, owner, group, mode, size)
char *name;
char *date;
char *owner;
char *group;
mode_t mode;
size_t size;
#endif
{
struct dirlist *tmp;
tmp = (struct dirlist *)malloc(sizeof (struct dirlist));
if (tmp == NULL)
return (NULL);
bzero((char *)tmp, sizeof (struct dirlist));
tmp->name = (char *)malloc((unsigned int)(strlen(name) + 1));
if (tmp->name == NULL) {
free_dirlist(tmp);
return (NULL);
}
tmp->date = (char *)malloc((unsigned int)(strlen(date) + 1));
if (tmp->date == NULL) {
free_dirlist(tmp);
return (NULL);
}
tmp->owner = (char *)malloc((unsigned int)(strlen(owner) + 1));
if (tmp->owner == NULL) {
free_dirlist(tmp);
return (NULL);
}
tmp->group = (char *)malloc((unsigned int)(strlen(group) + 1));
if (tmp->group == NULL) {
free_dirlist(tmp);
return (NULL);
}
strcpy(tmp->name, name);
strcpy(tmp->date, date);
strcpy(tmp->owner, owner);
strcpy(tmp->group, group);
tmp->mode = mode;
tmp->size = size;
tmp->next = NULL;
return (tmp);
}
#ifdef USE_PROTOTYPES
struct dirlist *add_dirname(struct dirlist *head, char *name, char *date,
char *owner, char *group, mode_t mode, size_t size, int sort_mode,
int sort_direction)
#else
struct dirlist *add_dirname(head, name, date, owner, group, mode,
size, sort_mode, sort_direction)
struct dirlist *head;
char *name;
char *date;
char *owner;
char *group;
mode_t mode;
size_t size;
int sort_mode;
int sort_direction;
#endif
{
struct dirlist *tmp;
struct dirlist *oldnext = NULL;
if (non_unix)
sort_mode = SORTBYNAME;
switch (sort_mode) {
default:
fprintf(stderr, "Unknown sort mode in add_dirname.\n");
/* Fall through */
case SORTBYNAME:
if (sort_direction == ASCENDING)
tmp = sortupbyname(head, name);
else
tmp = sortdownbyname(head, name);
break;
case SORTBYDATE:
if (sort_direction == ASCENDING)
tmp = sortupbydate(head, date);
else
tmp = sortdownbydate(head, date);
break;
case SORTBYSIZE:
if (sort_direction == ASCENDING)
tmp = sortupbysize(head, size);
else
tmp = sortdownbysize(head, size);
break;
}
oldnext = tmp->next;
tmp->next = new_dirlist(name, date, owner, group, mode, size);
if (tmp->next == NULL) {
tmp->next = oldnext;
return (NULL);
}
tmp->next->next = oldnext;
return (head);
}
#ifdef USE_PROTOTYPES
struct dirlist *add_dirlist_struct(struct dirlist *head,
struct dirlist *dlist, int sort_mode, int sort_direction)
#else
struct dirlist *add_dirlist_struct(head, dlist, sort_mode, sort_direction)
struct dirlist *head;
struct dirlist *dlist;
int sort_mode;
int sort_direction;
#endif
{
struct dirlist *tmp;
if (non_unix)
sort_mode = SORTBYNAME;
switch (sort_mode) {
default:
fprintf(stderr, "Unknown sort mode in add_dirlist_struct.\n");
/* Fall through */
case SORTBYNAME:
if (sort_direction == ASCENDING)
tmp = sortupbyname(head, dlist->name);
else
tmp = sortdownbyname(head, dlist->name);
break;
case SORTBYDATE:
if (sort_direction == ASCENDING)
tmp = sortupbydate(head, dlist->date);
else
tmp = sortdownbydate(head, dlist->date);
break;
case SORTBYSIZE:
if (sort_direction == ASCENDING)
tmp = sortupbysize(head, dlist->size);
else
tmp = sortdownbysize(head, dlist->size);
break;
}
dlist->next = tmp->next;
tmp->next = dlist;
return (head);
}
#ifdef USE_PROTOTYPES
void free_dirlist(struct dirlist *head)
#else
void free_dirlist(head)
struct dirlist *head;
#endif
{
struct dirlist *tmp;
while (head) {
tmp = head->next;
if (head->name)
free(head->name);
if (head->date)
free(head->date);
if (head->owner)
free(head->owner);
if (head->group)
free(head->group);
free((char *)head);
head = tmp;
}
}
/* alphabetical order */
#ifdef USE_PROTOTYPES
struct dirlist *sortupbyname(struct dirlist *head, char *name)
#else
struct dirlist *sortupbyname(head, name)
struct dirlist *head;
char *name;
#endif
{
struct dirlist *tmp;
int rval;
for (tmp = head; tmp->next != NULL; tmp = tmp->next) {
if (ignore_case)
rval = strcasecmp(name, tmp->next->name);
else
rval = strcmp(name, tmp->next->name);
if (rval < 0)
break; /* need to go before next entry. */
}
return (tmp);
}
/* least recently modified */
#ifdef USE_PROTOTYPES
struct dirlist *sortupbydate(struct dirlist *head, char *date)
#else
struct dirlist *sortupbydate(head, date)
struct dirlist *head;
char *date;
#endif
{
struct dirlist *tmp;
for (tmp = head; tmp->next != NULL; tmp = tmp->next) {
if (isearlier(date, tmp->next->date))
break; /* need to go before next entry. */
}
return (tmp);
}
/* smallest to largest */
#ifdef USE_PROTOTYPES
struct dirlist *sortupbysize(struct dirlist *head, size_t size)
#else
struct dirlist *sortupbysize(head, size)
struct dirlist *head;
size_t size;
#endif
{
struct dirlist *tmp;
for (tmp = head; tmp->next != NULL; tmp = tmp->next)
if (size <= tmp->next->size)
break; /* need to go before next entry. */
return (tmp);
}
int cummonthdays[] = {
0,
31,
59,
90,
120,
151,
181,
212,
243,
273,
304,
334
};
#ifdef USE_PROTOTYPES
long datetotime(char *date)
#else
long datetotime(date)
char *date;
#endif
{
struct tm tm;
/* "Aug 19 19:47" */
/* "Jan 10 1990" */
if (index(date, ':')) {
hour_time(date, &tm);
if (tm.tm_mon > current_month)
tm.tm_year = current_year - 1;
else
tm.tm_year = current_year;
} else {
year_time(date, &tm);
tm.tm_hour = 0;
tm.tm_min = 0;
}
return (tm.tm_min + tm.tm_hour * 60
+ (tm.tm_year * 365 + tm.tm_mday +
cummonthdays[tm.tm_mon]) * 1440);
}
#ifdef USE_PROTOTYPES
int isearlier(char *date1, char *date2)
#else
int isearlier(date1, date2)
char *date1, *date2;
#endif
{
long time1;
long time2;
time1 = datetotime(date1);
time2 = datetotime(date2);
if (time1 < time2)
return (1);
return (0);
}
/* reverse alphabetical order */
#ifdef USE_PROTOTYPES
struct dirlist *sortdownbyname(struct dirlist *head, char *name)
#else
struct dirlist *sortdownbyname(head, name)
struct dirlist *head;
char *name;
#endif
{
struct dirlist *tmp;
int rval;
for (tmp = head; tmp->next != NULL; tmp = tmp->next) {
if (ignore_case)
rval = strcasecmp(name, tmp->next->name);
else
rval = strcmp(name, tmp->next->name);
if (rval > 0)
break; /* need to go before next entry. */
}
return (tmp);
}
/* most recently modified */
#ifdef USE_PROTOTYPES
struct dirlist *sortdownbydate(struct dirlist *head, char *date)
#else
struct dirlist *sortdownbydate(head, date)
struct dirlist *head;
char *date;
#endif
{
struct dirlist *tmp;
for (tmp = head; tmp->next != NULL; tmp = tmp->next) {
if (!isearlier(date, tmp->next->date)) {
break; /* need to go before next entry. */
}
}
return (tmp);
}
/* largest to smallest */
#ifdef USE_PROTOTYPES
struct dirlist *sortdownbysize(struct dirlist *head, size_t size)
#else
struct dirlist *sortdownbysize(head, size)
struct dirlist *head;
size_t size;
#endif
{
struct dirlist *tmp;
for (tmp = head; tmp->next != NULL; tmp = tmp->next)
if (size >= tmp->next->size)
break; /* need to go before next entry. */
return (tmp);
}
#ifdef USE_PROTOTYPES
void clear_slist(Panel panel_list)
#else
void clear_slist(panel_list)
Panel panel_list;
#endif
{
int nitems, row;
struct dirlist *dotdot;
xv_set(panel_list,
XV_SHOW, FALSE,
NULL);
nitems = xv_get(panel_list, PANEL_LIST_NROWS);
if (nitems && (dotdot = (struct dirlist *)xv_get(panel_list,
PANEL_LIST_CLIENT_DATA, 0))) {
dotdot->next = NULL;
free_dirlist(dotdot);
}
for (row = nitems - 1; row >= 0; row--) {
xv_set(panel_list,
PANEL_LIST_DELETE, row,
PANEL_PAINT, PANEL_NONE,
NULL);
}
panel_paint(panel_list, PANEL_CLEAR);
xv_set(panel_list,
XV_SHOW, TRUE,
NULL);
}
#ifdef USE_PROTOTYPES
void actual_dirlist_to_slist(Panel panel_list, struct dirlist *head,
mode_t type, int showdotfiles)
#else
void actual_dirlist_to_slist(panel_list, head, type, showdotfiles)
Panel panel_list;
struct dirlist *head;
mode_t type;
int showdotfiles;
#endif
{
struct dirlist *tmp;
int row;
Xv_font entry_font;
char *d;
Server_image entry_glyph;
row = 0;
for (tmp = head->next; tmp != NULL; tmp = tmp->next) {
if (type && ((type & S_IFMT) != (tmp->mode & S_IFMT)))
continue;
if ((tmp != head->next) &&
(tmp->name[0] == '.' && !showdotfiles))
continue;
d = tmp->date;
if (!strcmp(tmp->date, "unknown"))
d = "";
if (tmp->size == -1)
sprintf(scratch, " %12s %10s %s", d, "",
tmp->name);
else
sprintf(scratch, " %12s %10d %s", d, tmp->size,
tmp->name);
switch (tmp->mode & S_IFMT) {
case S_IFDIR:
entry_font = bold_list_font;
if (row != 0)
entry_glyph = directory_glyph;
else
entry_glyph = dotdot_glyph;
strcat(scratch, "/");
break;
case S_IFREG:
entry_font = list_font;
entry_glyph = file_glyph;
break;
case S_IFLNK:
entry_font = list_font;
entry_glyph = link_glyph;
break;
default:
entry_font = list_font;
entry_glyph = unknown_glyph;
break;
}
xv_set(panel_list,
PANEL_LIST_INSERT, row,
PANEL_LIST_STRING, row, scratch,
PANEL_LIST_FONT, row, entry_font,
PANEL_LIST_GLYPH, row, entry_glyph,
PANEL_LIST_CLIENT_DATA, row, tmp,
PANEL_PAINT, PANEL_NONE,
NULL);
row++;
}
}
#ifdef USE_PROTOTYPES
void dirlist_to_slist(Panel panel_list, struct dirlist *head)
#else
void dirlist_to_slist(panel_list, head)
Panel panel_list;
struct dirlist *head;
#endif
{
struct dirlist *tmp;
int dotypesort = 0;
int showdotfiles = 0;
xv_set(panel_list,
XV_SHOW, FALSE,
NULL);
add_dotdot(head);
if (panel_list == local_window.list) {
showdotfiles = local_showdotfiles;
if (group_local_files)
dotypesort = 1;
} else {
/* panel_list == base_window.list */
showdotfiles = remote_showdotfiles;
if (group_remote_files)
dotypesort = 1;
}
if (dotypesort) {
/* have to insert backwards, since the routine inserts at 0 */
#ifdef S_IFIFO
actual_dirlist_to_slist(panel_list, head, S_IFIFO,
showdotfiles);
#endif
#ifdef S_IFSOCK
actual_dirlist_to_slist(panel_list, head, S_IFSOCK,
showdotfiles);
#endif
actual_dirlist_to_slist(panel_list, head, S_IFBLK,
showdotfiles);
actual_dirlist_to_slist(panel_list, head, S_IFCHR,
showdotfiles);
actual_dirlist_to_slist(panel_list, head, S_IFLNK,
showdotfiles);
actual_dirlist_to_slist(panel_list, head, S_IFREG,
showdotfiles);
actual_dirlist_to_slist(panel_list, head, S_IFDIR,
showdotfiles);
} else {
actual_dirlist_to_slist(panel_list, head, 0, showdotfiles);
}
/* now remove '..' from list */
tmp = head->next;
head->next = head->next->next;
tmp->next = NULL;
/* all entries attached as client_data */
xv_set(panel_list,
XV_SHOW, TRUE,
NULL);
}
#ifdef USE_PROTOTYPES
void add_dotdot(struct dirlist *head)
#else
void add_dotdot(head)
struct dirlist *head;
#endif
{
struct dirlist *tmp;
tmp = new_dirlist("..", "unknown", "", "", S_IFDIR, (size_t)-1);
if (tmp == NULL)
return;
tmp->next = head->next;
head->next = tmp;
}
#ifdef USE_PROTOTYPES
struct dirlist *sort_dirlist(struct dirlist *head, int sort_mode,
int sort_direction)
#else
struct dirlist *sort_dirlist(head, sort_mode, sort_direction)
struct dirlist *head;
int sort_mode;
int sort_direction;
#endif
{
struct dirlist *tmp;
struct dirlist *next;
if (head == NULL)
return (NULL);
/* sort current list into new one */
tmp = head->next;
head->next = NULL;
while (tmp) {
next = tmp->next;
tmp->next = NULL;
(void) add_dirlist_struct(head, tmp, sort_mode, sort_direction);
tmp = next;
}
return (head);
}
static char *abbrev_month[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
};
#ifdef USE_PROTOTYPES
void hour_time(char *date, struct tm *tm)
#else
void hour_time(date, tm)
char *date;
struct tm *tm;
#endif
{
char month[10];
int i;
bzero((char *)tm, sizeof (struct tm));
sscanf(date, "%s%d%d:%d", month, &tm->tm_mday,
&tm->tm_hour, &tm->tm_min);
for (i = 0; i < 12; i++)
if (!strncmp(month, abbrev_month[i], 3))
break;
if (i != 12)
tm->tm_mon = i;
}
#ifdef USE_PROTOTYPES
void year_time(char *date, struct tm *tm)
#else
void year_time(date, tm)
char *date;
struct tm *tm;
#endif
{
char month[10];
int i;
bzero((char *)tm, sizeof (struct tm));
sscanf(date, "%s%d%d", month, &tm->tm_mday, &tm->tm_year);
for (i = 0; i < 12; i++)
if (!strncmp(month, abbrev_month[i], 3))
break;
if (i != 12)
tm->tm_mon = i;
if (tm->tm_year > 1900)
tm->tm_year -= 1900;
}
syntax highlighted by Code2HTML, v. 0.9.1