301 lines
6.2 KiB
C
301 lines
6.2 KiB
C
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
|
|
|
|
#include <sys/socket.h>
|
|
#include <netax25/ax25.h>
|
|
#include <netrose/rose.h>
|
|
#include <netax25/axlib.h>
|
|
|
|
#include "node.h"
|
|
|
|
static void expand_string(char *dest, char *src, int argc, char **argv)
|
|
{
|
|
char tmpbuf[64], def[64];
|
|
char *p1, *p2, *cp;
|
|
int n, skip, nocopy;
|
|
|
|
if (strchr(src, '%') == NULL) {
|
|
strcpy(dest, src);
|
|
return;
|
|
}
|
|
p1 = src;
|
|
p2 = dest;
|
|
while (*p1) {
|
|
if (*p1 == '%') {
|
|
nocopy=1;
|
|
p1++;
|
|
skip = 1;
|
|
def[0] = 0;
|
|
if (*p1 == '{') {
|
|
p1++;
|
|
if ((cp = strchr(p1, '}')) != NULL) {
|
|
skip = cp - p1 + 1;
|
|
cp = p1;
|
|
if (*++cp == ':') {
|
|
cp++;
|
|
n = min(skip - 3, 63);
|
|
strncpy(def, cp, n);
|
|
def[n] = 0;
|
|
}
|
|
}
|
|
}
|
|
switch (*p1) {
|
|
case 'u':
|
|
case 'U':
|
|
strcpy(tmpbuf, User.call);
|
|
if ((cp = strrchr(tmpbuf, '-'))) *cp = 0;
|
|
break;
|
|
case 's':
|
|
case 'S':
|
|
strcpy(tmpbuf, User.call);
|
|
break;
|
|
case 'p':
|
|
case 'P':
|
|
strcpy(tmpbuf, User.ul_name);
|
|
if ((cp = strrchr(tmpbuf, '-'))) *cp = 0;
|
|
break;
|
|
case 'r':
|
|
case 'R':
|
|
strcpy(tmpbuf, User.ul_name);
|
|
break;
|
|
case 't':
|
|
case 'T':
|
|
switch (User.ul_type) {
|
|
case AF_FLEXNET:
|
|
strcpy(tmpbuf, "flexnet");
|
|
break;
|
|
case AF_AX25:
|
|
strcpy(tmpbuf, "ax25");
|
|
break;
|
|
case AF_NETROM:
|
|
strcpy(tmpbuf, "netrom");
|
|
break;
|
|
#ifdef HAVE_ROSE
|
|
case AF_ROSE:
|
|
strcpy(tmpbuf, "rose");
|
|
break;
|
|
#endif
|
|
case AF_INET:
|
|
strcpy(tmpbuf, "inet");
|
|
break;
|
|
case AF_UNSPEC:
|
|
strcpy(tmpbuf, "host");
|
|
break;
|
|
}
|
|
break;
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
n = *p1 - '0';
|
|
if (n < argc) strcpy(tmpbuf, argv[n]);
|
|
else strcpy(tmpbuf, def);
|
|
break;
|
|
case '*':
|
|
nocopy=0;
|
|
for(n=2;n<argc;n++) {
|
|
if (argv[n]==NULL) break;
|
|
strcpy(tmpbuf, argv[n]);
|
|
if (isalpha(*p1)) {
|
|
if (isupper(*p1)) strupr(tmpbuf);
|
|
else strlwr(tmpbuf);
|
|
}
|
|
strcpy(p2, tmpbuf);
|
|
p2 += strlen(tmpbuf);
|
|
}
|
|
break;
|
|
default:
|
|
strcpy(tmpbuf, "%");
|
|
break;
|
|
}
|
|
if (nocopy==1) {
|
|
if (isalpha(*p1)) {
|
|
if (isupper(*p1)) strupr(tmpbuf);
|
|
else strlwr(tmpbuf);
|
|
}
|
|
strcpy(p2, tmpbuf);
|
|
p2 += strlen(tmpbuf);
|
|
}
|
|
p1 += skip;
|
|
} else
|
|
*p2++ = *p1++;
|
|
}
|
|
*p2 = 0;
|
|
return;
|
|
}
|
|
|
|
/* This function is straight from *NOS */
|
|
|
|
static char *parse_string(char *str)
|
|
{
|
|
char *cp = str;
|
|
unsigned long num;
|
|
|
|
while (*str != '\0' && *str != '\"') {
|
|
if (*str == '\\') {
|
|
str++;
|
|
switch (*str++) {
|
|
case 'n': *cp++ = '\n'; break;
|
|
case 't': *cp++ = '\t'; break;
|
|
case 'v': *cp++ = '\v'; break;
|
|
case 'b': *cp++ = '\b'; break;
|
|
case 'r': *cp++ = '\r'; break;
|
|
case 'f': *cp++ = '\f'; break;
|
|
case 'a': *cp++ = '\007'; break;
|
|
case '\\': *cp++ = '\\'; break;
|
|
case '\"': *cp++ = '\"'; break;
|
|
case 'x':
|
|
num = strtoul(--str, &str, 16);
|
|
*cp++ = (char) num;
|
|
break;
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
num = strtoul(--str, &str, 8);
|
|
*cp++ = (char) num;
|
|
break;
|
|
case '\0':
|
|
return NULL;
|
|
default:
|
|
*cp++ = *(str - 1);
|
|
break;
|
|
};
|
|
} else {
|
|
*cp++ = *str++;
|
|
}
|
|
}
|
|
if (*str == '\"') str++; /* skip final quote */
|
|
*cp = '\0'; /* terminate string */
|
|
return str;
|
|
}
|
|
|
|
int parse_args(char **argv, char *cmd)
|
|
{
|
|
int ct = 0;
|
|
int quoted;
|
|
|
|
while (ct < 31) {
|
|
quoted = 0;
|
|
while (*cmd && isspace(*cmd)) cmd++;
|
|
if (*cmd == 0) break;
|
|
if (*cmd == '"') {
|
|
quoted++;
|
|
cmd++;
|
|
}
|
|
argv[ct++] = cmd;
|
|
if (quoted) {
|
|
if ((cmd = parse_string(cmd)) == NULL)
|
|
return 0;
|
|
} else {
|
|
while (*cmd && !isspace(*cmd)) cmd++;
|
|
}
|
|
if (*cmd) *cmd++ = 0;
|
|
}
|
|
argv[ct] = NULL;
|
|
return ct;
|
|
}
|
|
|
|
int cmdparse(struct cmd *list, char *cmdline)
|
|
{
|
|
struct cmd *cmdp;
|
|
int argc;
|
|
char *argv[32];
|
|
static char cmdbuf[1024];
|
|
|
|
/* convert cmdline to argc,argv[] if '#' or empty: return */
|
|
if ((argc = parse_args(argv, cmdline)) == 0 || *argv[0] == '#') return 2;
|
|
/* check if the command in argv[0] is in the list */
|
|
for (cmdp = list; cmdp != NULL; cmdp = cmdp->next) {
|
|
if (strlen(argv[0]) < cmdp->len || strlen(argv[0]) > strlen(cmdp->name)) continue;
|
|
if (strncasecmp(cmdp->name, argv[0], strlen(argv[0])) == 0) break;
|
|
}
|
|
if (cmdp == NULL) return -1;
|
|
strlwr(argv[0]);
|
|
switch (cmdp->type) {
|
|
case CMD_INTERNAL: /* execute internal command */
|
|
return (*cmdp->function)(argc, argv);
|
|
case CMD_ALIAS:
|
|
/* evaluate arguments */
|
|
expand_string(cmdbuf, cmdp->command, argc, argv);
|
|
aliascmd=1;
|
|
/* re-execute the command */
|
|
return cmdparse(list, cmdbuf);
|
|
case CMD_EXTERNAL:
|
|
/* evaluate arguments */
|
|
expand_string(cmdbuf, cmdp->command, argc, argv);
|
|
/* convert the cmdline to argc,argv[] */
|
|
argc = parse_args(argv, cmdbuf);
|
|
/* execute an external command */
|
|
if (User.ul_type == AF_NETROM) {
|
|
axio_printf(NodeIo, "%s} ", NodeId);
|
|
}
|
|
if (check_perms(PERM_ANSI, 0L) != -1) {
|
|
axio_printf(NodeIo,"\e[01;32mExecuting command...\e[0m\n");
|
|
} else {
|
|
axio_puts("Executing command... \n", NodeIo);
|
|
}
|
|
return extcmd(cmdp, argv);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void insert_cmd(struct cmd **list, struct cmd *new)
|
|
{
|
|
struct cmd *tmp, *p;
|
|
|
|
if (*list == NULL || strcasecmp(new->name, (*list)->name) < 0) {
|
|
tmp = *list;
|
|
*list = new;
|
|
new->next = tmp;
|
|
} else {
|
|
for (p = *list; p->next != NULL; p = p->next)
|
|
if (strcasecmp(new->name, p->next->name) < 0) break;
|
|
tmp = p->next;
|
|
p->next = new;
|
|
new->next = tmp;
|
|
}
|
|
}
|
|
|
|
int add_internal_cmd(struct cmd **list, char *name, int len, int (*function) (int argc, char **argv))
|
|
{
|
|
struct cmd *new;
|
|
|
|
if ((new = calloc(1, sizeof(struct cmd))) == NULL) {
|
|
node_perror("add_internal_cmd: calloc", errno);
|
|
return -1;
|
|
}
|
|
new->name = strdup(name);
|
|
new->len = len;
|
|
new->type = CMD_INTERNAL;
|
|
new->function = function;
|
|
insert_cmd(list, new);
|
|
return 0;
|
|
}
|
|
|
|
void free_cmdlist(struct cmd *list)
|
|
{
|
|
struct cmd *tmp;
|
|
|
|
while (list != NULL) {
|
|
free(list->name);
|
|
free(list->command);
|
|
free(list->path);
|
|
tmp = list;
|
|
list = list->next;
|
|
free(tmp);
|
|
}
|
|
}
|