/* qi.c - UIUC CCSO nameserver query interpreter */
/* Bruce Tanner - Cerritos College */
/* Version history: */
/* 1.0 1993/08/15 Initial version */
/* 1.1 1993/08/25 Add field instance attribute, conditionalize options */
/* 1.2 1993/09/08 Soundex is now an indexed explicit field; exact match mode */
/* 1.3 1993/09/15 Added ID to index key to remove duplicate index records */
/* 2.0 1993/09/16 Add login mode (login, answer, clear, logout) */
/* 2.1 1993/09/20 Interactive mode */
Fields fields[MAX_FIELD]; /* field attributes, global */
int mode = DEFAULT_MODE; /* global mode flags */
extern int db_status; /* status of database */
char login_alias[KEYWORD_SIZE + 1]; /* current login */
char login_challenge[CHALLENGE_SIZE + 1];
int login_mode = MODE_ANONYMOUS;
void db_open();
void db_close();
int read_fields(char *);
int fields_cmd(char *, int);
char *new_string(char *);
char *getlogical(char *);
void qilog(int, char *, ...);
extern int query(char *, int);
extern char *get_value(int, char*, char*, char *);
int quit(char *, int);
Arg *parse_cmd(char *, int);
Arg *make_arg(char *, int, char *, int);
void free_args(Arg *);
void swrite(int, char *, ...);
void writestring(int, char *);
void qiabort(int, char *);
int id_cmd(char *, int);
int stat_cmd(char *, int);
int set_cmd(char *, int);
int site_cmd(char *, int);
int login_cmd(char *, int);
int answer_cmd(char *, int);
int clear_cmd(char *, int);
int logout_cmd(char *, int);
char *challenge(int size);
db_open();
while (process(sock, class == DC$_TERM));
closenet(sock);
db_close();
}
/* process a command stream */
int process(int sock, int interactive)
{
int status, ind, length;
static int bad_cmd = 0;
char *cp, inputline[MAX_INPUT], *vp, verb[MAX_INPUT];
strncpy(inputline, "", MAX_INPUT);
if (interactive) {
printf("qi> ");
fgets(inputline, MAX_INPUT, stdin);
length = strlen(inputline);
}
else
length = readline(sock, inputline, MAX_INPUT); /** Get the line **/
ZapCRLF(inputline);
qilog(sock, "Cmd: %s", inputline);
if (length <= 0) {
qilog(sock, "Remote end shutdown");
return False;
}
if (strlen(inputline) == 0) /* ignore blank lines */
return (++bad_cmd < MAX_BAD); /* return False if too many null cmds */
/* put first word of input in verb as lowercase */
strncpy(verb, "", sizeof(verb));
vp = verb;
for (cp = inputline; *cp; cp++)
if (*cp == ' ')
break; /* break on space */
else
*vp++ = _tolower(*cp); /* copy lower case char to verb */
for (ind = 0; ind < MAX_VERBS; ind++)
if (strcmp(verb, verbs[ind].name) == 0)
break;
if (ind == MAX_VERBS) {
qilog(sock, "Unknown command: /%s/%s/", verb, inputline);
writestring(sock, "514:Unknown command.\r\n");
return (++bad_cmd < MAX_BAD); /* return False if too many bad cmds */
}
if (((verbs[ind].mode & login_mode) == 0) && (login_mode == MODE_ANONYMOUS)) {
qilog(sock, "Not logged in: %s", inputline);
writestring(sock, "506:Request refused; must be logged in to execute.\r\n");
return (++bad_cmd < MAX_BAD); /* return False if too many bad cmds */
}
if (((verbs[ind].mode & login_mode) == 0) && (login_mode == MODE_PASSWORD)) {
qilog(sock, "Not answer or clear: %s", inputline);
writestring(sock, "523:Expecting 'answer' or 'clear'\r\n");
return (++bad_cmd < MAX_BAD); /* return False if too many bad cmds */
}
if ((ind < MAX_VERBS) && (verbs[ind].mode & login_mode))
status = (*verbs[ind].proc)(inputline, sock);
ptr = get_field(ptr, field, False); /* field option (ignore) */
for (;;) {
ptr = get_field(ptr, field, True); /* get attribute */
if (strlen(field) == 0)
break; /* no more attributes */
fields[field_idx].attrib |= field_attrib(field);
}
if (fields[field_idx].number < 1)
qilog(-1, "Field \"%s\" has illegal field number",
fields[field_idx].name);
}
fclose(cnf);
return True;
}
int write_afield(int field_num, int sock)
{
char line[128];
int aidx;
int fields_cmd(char *cmd, int sock)
{
int fidx, aidx, count = 0;
char line[256];
Arg *list, *listp;
list = listp = parse_cmd(cmd, sock);
if (list == NULL) /* null arg list means all fields */
for (fidx = 0; fidx < MAX_FIELD; fidx++)
count += write_afield(fidx, sock);
else
for (; listp; listp = listp->next)
if (listp->field > -1)
count += write_afield(listp->field, sock);
else
writestring(sock, "507:Field does not exist.\r\n");
free_args(list);
writestring(sock, "200:Ok.\r\n");
if (DEBUG) qilog(sock, "Sent %d field definitions", count);
return True;
}
id_cmd(char *cmd, int sock)
{
writestring(sock, "200:Thanks, but we don't use ids here.\r\n");
return True;
}
/* return the attribute value for the given field name */
int field_attrib(char *str)
{
int ind;
for (ind = 0; ind < MAX_ATTRIBUTES; ind++)
if (*str == _tolower(*attributes[ind].name)) /* check only first char */
return (attributes[ind].value);
return (0); /* no match = no bits */
}
/* return the field_number for the given field name */
int field_number(char *str)
{
int ind;
for (ind = 0; ind < MAX_FIELD; ind++)
if (fields[ind].name && (strcmp(str, fields[ind].name) == 0))
return (atoi(fields[ind].number));
return (-1); /* no field number */
}
/* get a token as part of the 'field=value' clause */
/* return pointer to terminator */
char *get_token(char *cp, char *dp)
{
int in_quote = False;
if (*cp) {
while (isspace(*cp)) cp++; /* skip space */
while (*cp && (in_quote || ((*cp != ' ') && (*cp != '='))))
if (*cp == '"') {
in_quote = !in_quote;
cp++;
}
else
*dp++ = in_quote ? *cp++ : tolower(*cp++);
}
*dp = '\0';
return cp;
}
cp = strchr(cmd, ' '); /* skip verb */
while (cp) {
cp = get_token(++cp, token);
if (strlen(token) == 0)
return start;
if (start == NULL)
start = end = make_arg(NULL, -1, NULL, 0);
else {
end->next = make_arg(NULL, -1, NULL, 0);
end = end->next;
}
if (*cp == '=') {
end->name = new_string(token);
end->field = field_number(token);
end->type |= TYPE_NAME | TYPE_EQUAL;
cp = get_token(++cp, token);
}
if (strlen(token)) {
end->value = new_string(token);
end->type |= TYPE_VALUE;
}
if (strcmp(token, "return") == 0) /* check for special names */
end->type |= TYPE_RETURN;
else if (strcmp(token, "on") == 0)
end->type |= TYPE_ON;
else if (strcmp(token, "off") == 0)
end->type |= TYPE_OFF;
if (end->field == -1) /* if there were no field name given */
end->field = field_number(token); /* try the field value as a field name */
if (DEBUG)
swrite(sock, "-100: Parse >> %s (field %d) = %s\r\n",
end->name ? end->name : "", end->field,
end->value ? end->value : "");
}
return start; /* should only get here on null list */
}
Arg *make_arg(char * name, int field, char *value, int type)
{
Arg *ptr;