wmaker-eukara/dockapps/wmnd/src/misc.c

219 lines
4.0 KiB
C

/*
* misc: miscellaneus dockapp routines - implementation
* Copyright(c) 1997 by Alfredo K. Kojima
* Copyright(c) 2004 by wave++ "Yuri D'Elia" <wavexx@users.sf.net>
* Distributed under GNU GPL (v2 or above) WITHOUT ANY WARRANTY.
*/
#include "config.h"
#include "misc.h"
#include "list.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/*
*----------------------------------------------------------------------
* parse_command--
* Divides a command line into a argv/argc pair.
*----------------------------------------------------------------------
*/
#define PRC_ALPHA 0
#define PRC_BLANK 1
#define PRC_ESCAPE 2
#define PRC_DQUOTE 3
#define PRC_EOS 4
#define PRC_SQUOTE 5
typedef struct
{
short nstate;
short output;
} DFA;
static DFA mtable[9][6] =
{
{{ 3, 1}, { 0, 0}, { 4, 0}, { 1, 0}, { 8, 0}, { 6, 0}},
{{ 1, 1}, { 1, 1}, { 2, 0}, { 3, 0}, { 5, 0}, { 1, 1}},
{{ 1, 1}, { 1, 1}, { 1, 1}, { 1, 1}, { 5, 0}, { 1, 1}},
{{ 3, 1}, { 5, 0}, { 4, 0}, { 1, 0}, { 5, 0}, { 6, 0}},
{{ 3, 1}, { 3, 1}, { 3, 1}, { 3, 1}, { 5, 0}, { 3, 1}},
{{-1, -1}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}},
{{ 6, 1}, { 6, 1}, { 7, 0}, { 6, 1}, { 5, 0}, { 3, 0}},
{{ 6, 1}, { 6, 1}, { 6, 1}, { 6, 1}, { 5, 0}, { 6, 1}},
{{-1, -1}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
};
char*
next_token(const char *word, const char** next)
{
const char* ptr;
char* ret;
char* t;
int state, ctype;
t = ret = (char*)malloc(strlen(word) + 1);
ptr = word;
state = 0;
*t = 0;
for(;;)
{
if(*ptr == 0)
ctype = PRC_EOS;
else if(*ptr == '\\')
ctype = PRC_ESCAPE;
else if(*ptr == '"')
ctype = PRC_DQUOTE;
else if(*ptr == '\'')
ctype = PRC_SQUOTE;
else if(*ptr == ' ' || *ptr == '\t')
ctype = PRC_BLANK;
else
ctype = PRC_ALPHA;
if(mtable[state][ctype].output)
{
*t = *ptr;
t++;
*t = 0;
}
state = mtable[state][ctype].nstate;
ptr++;
if(mtable[state][0].output < 0)
break;
}
if(*ret == 0)
t = NULL;
else
t = strdup(ret);
free(ret);
if(ctype == PRC_EOS)
*next = NULL;
else
*next = ptr;
return t;
}
void
parse_command(const char* command, char*** argv, int* argc)
{
LinkedList* list = NULL;
char* token;
const char* line;
int count, i;
line = command;
do
{
token = next_token(line, &line);
if(token)
list = list_cons(token, list);
}
while(token && line);
count = list_length(list);
*argv = (char**)malloc(sizeof(char*) * count);
i = count;
while(list)
{
(*argv)[--i] = (char*)list->head;
list_remove_head(&list);
}
*argc = count;
}
pid_t
exec_command(const char* command)
{
pid_t pid;
char** argv;
int argc;
parse_command(command, &argv, &argc);
if(!argv)
return 0;
if((pid = fork()) == 0)
{
char** args;
int i;
args = (char**)malloc(sizeof(char*) * (argc + 1));
if(!args)
exit(10);
for(i = 0; i < argc; i++)
args[i] = argv[i];
args[argc] = NULL;
execvp(argv[0], args);
exit(10);
}
return pid;
}
char*
percsubst(const char* string, const perctbl_t* table, int elements)
{
size_t inlen = strlen(string);
size_t outlen = inlen * 2;
char* buf = (char*)malloc(outlen);
const char* rptr;
char* wptr;
const perctbl_t* it;
size_t len;
size_t dist;
for(wptr = buf, rptr = string; *rptr;)
{
/* normal characters */
if(*rptr != '%')
{
*(wptr++) = *(rptr++);
continue;
}
/* peek the next one */
if(*(++rptr) == '%')
{
*(wptr++) = *(rptr++);
continue;
}
/* search for an element in the table */
for(it = table; it != table + elements; ++it)
if(*rptr == it->c)
{
len = strlen(it->value);
dist = wptr - buf;
if((outlen - dist) >= len)
{
outlen += len * 2;
buf = (char*)realloc(buf, outlen);
wptr = buf + dist;
}
memcpy(wptr, it->value, len);
wptr += len;
break;
}
/* go on */
++rptr;
}
*wptr = 0;
return buf;
}