1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
/*
0) alias file format.
alternating lines of alias and dir
(this enables embedded whitespace in dir and alias without quoting rules)
optional blank lines
optional lines beginning with '#' as comments
(no you can't put a '#' just anywhere)
1) data structure for alias list nodes.
typedef struct DirAlias_ {
char *alias;
char *dir;
struct DirAlias *next;
} DirAlias;
2) init routine
A) open alias file
B) while not EOF do
read line
parse line
dir must begin with "/"
allocate DirAlias and members
if tail is NULL then head and tail (global DirAlias_t pointers)
are set to member
else tail->next is set to member and then tail is set to member
3) lookup routine
A) given potential alias return dir or NULL
(walk list starting with head looking for match)
4) FTP CWD command mods
A) if chdir() fails try alias (use lookup routine)
5) FTP SITE ALIAS command
A) list aliases
*/
#include <config.h>
#ifdef WITH_DIRALIASES
#include "ftpd.h"
#include "messages.h"
#include "diraliases.h"
#ifdef WITH_DMALLOC
# include <dmalloc.h>
#endif
static DirAlias *head, *tail;
static signed char aliases_up;
/* returns: 0 on success, -1 on failure */
int init_aliases(void)
{
FILE *fp;
char alias[MAXALIASLEN + 1U];
char dir[PATH_MAX + 1U];
if ((fp = fopen(ALIASES_FILE, "r")) == NULL) {
return 0;
}
while (fgets(alias, sizeof alias, fp) != NULL) {
if (*alias == '#' || *alias == '\n' || *alias == 0) {
continue;
}
{
char * const z = alias + strlen(alias) - 1U;
if (*z != '\n') {
goto bad;
}
*z = 0;
}
do {
if (fgets(dir, sizeof dir, fp) == NULL || *dir == 0) {
goto bad;
}
{
char * const z = dir + strlen(dir) - 1U;
if (*z == '\n') {
*z = 0;
}
}
} while (*dir == '#' || *dir == 0);
if (head == NULL) {
if ((head = tail = malloc(sizeof *head)) == NULL ||
(tail->alias = strdup(alias)) == NULL ||
(tail->dir = strdup(dir)) == NULL) {
die_mem();
}
tail->next = NULL;
} else {
DirAlias *curr;
if ((curr = malloc(sizeof *curr)) == NULL ||
(curr->alias = strdup(alias)) == NULL ||
(curr->dir = strdup(dir)) == NULL) {
die_mem();
}
tail->next = curr;
tail = curr;
}
}
fclose(fp);
aliases_up++;
return 0;
bad:
fclose(fp);
logfile(LOG_ERR, MSG_ALIASES_BROKEN_FILE " [" ALIASES_FILE "]");
return -1;
}
char *lookup_alias(const char *alias)
{
const DirAlias *curr = head;
if (aliases_up == 0) {
return NULL;
}
while (curr != NULL) {
if (strcmp(curr->alias, alias) == 0) {
return curr->dir;
}
curr = curr->next;
}
return NULL;
}
void print_aliases(void)
{
const DirAlias *curr = head;
if (aliases_up == 0) {
addreply_noformat(502, MSG_CONF_ERR);
return;
}
addreply_noformat(214, MSG_ALIASES_LIST);
while (curr != NULL) {
char line[MAXALIASLEN + PATH_MAX + 3U];
snprintf(line, sizeof line, " %s %s", curr->alias, curr->dir);
addreply_noformat(0, line);
curr = curr->next;
}
addreply_noformat(214, " ");
}
#endif
|