123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- /**
- * @PROJECT CGI Bash Shell Interface
- * @COPYRIGHT See COPYING in the top level directory
- * @FILE subshell.c
- * @PURPOSE Subshell execution
- * @DEVELOPERS Nathan Angelacos <nangel@users.sourceforge.net>
- * Rafal Kupiec <belliash@asiotec.eu.org>
- */
-
- #include <stdio.h>
- #include <unistd.h>
- #include <time.h>
- #include <getopt.h>
- #include <sys/mman.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <sys/stat.h>
- #include <sys/fcntl.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
-
- #include "common.h"
- #include "buffer.h"
- #include "error.h"
- #include "subshell.h"
- #include "cbsi.h"
-
- char open_tag[3] = "<%";
- char close_tag[3] = "%>";
-
- const char* g_tag[] = {
- "",
- "",
- ":",
- "@",
- ""
- };
-
- token_t* build_token_list(script_t* scriptbuf, token_t* tokenlist) {
- char* start;
- char* end;
- char* curpos;
- char* endpos;
- token_t* curtoken;
- token_t* firsttoken;
-
- curtoken = tokenlist;
- firsttoken = tokenlist;
- curpos = scriptbuf->buf + scriptbuf->curpos;
- endpos = scriptbuf->buf + scriptbuf->size;
- while(curpos < endpos) {
- start = strstr(curpos, open_tag);
- end = strstr(curpos, close_tag);
- if(start && !end) {
- die_with_message(scriptbuf, start, g_err_msg[E_NO_END_MARKER], open_tag[1]);
- }
- if((start > end) || (!start && end)) {
- die_with_message(scriptbuf, end, g_err_msg[E_END_BEFORE_BEGIN], open_tag[1], open_tag[1]);
- }
- if(start && (strstr(start + 1, open_tag) && (strstr (start + 1, open_tag) < end)))
- die_with_message(scriptbuf, start, g_err_msg[E_NO_END_MARKER], open_tag[1]);
- if(end) {
- curtoken = push_token_on_list(curtoken, scriptbuf, curpos, start - curpos);
- if(firsttoken == NULL) {
- firsttoken = curtoken;
- }
- curtoken = push_token_on_list(curtoken, scriptbuf, start, end - start);
- if(firsttoken == NULL) {
- firsttoken = curtoken;
- }
- curpos = end + 2;
- } else {
- curtoken = push_token_on_list(curtoken, scriptbuf, curpos, endpos - curpos);
- if(firsttoken == NULL) {
- firsttoken = curtoken;
- }
- curpos = endpos;
- }
- }
- return firsttoken;
- }
-
- void free_script_list(script_t* script) {
- script_t* next;
-
- while(script) {
- next = script->next;
- if(script->name) {
- free(script->name);
- }
- if(script->buf) {
- free(script->buf);
- }
- free(script);
- script = next;
- }
- }
-
- void free_token_list(token_t* tokenlist) {
- token_t* next;
-
- while(tokenlist) {
- next = tokenlist->next;
- free(tokenlist);
- tokenlist = next;
- }
- }
-
- script_t* load_script(char* filename, script_t* scriptlist) {
- script_t* scriptbuf;
- int scriptfp;
- struct stat filestat;
-
- scriptfp = open(filename, O_NONBLOCK + O_RDONLY);
- if(scriptfp == -1) {
- die_with_message(NULL, NULL, g_err_msg[E_FILE_OPEN_FAIL], filename);
- }
- fstat(scriptfp, &filestat);
- scriptbuf = (script_t *) xmalloc(sizeof (script_t));
- scriptbuf->name = (char *) xmalloc(strlen (filename) + 1);
- scriptbuf->buf = (char *) xmalloc(filestat.st_size + 1);
- memset(scriptbuf->name, 0, strlen(filename) + 1);
- memcpy(scriptbuf->name, filename, strlen(filename));
- memset(scriptbuf->buf, 0, filestat.st_size + 1);
- read(scriptfp, scriptbuf->buf, filestat.st_size);
- scriptbuf->size = filestat.st_size;
- scriptbuf->uid = filestat.st_uid;
- scriptbuf->gid = filestat.st_gid;
- scriptbuf->curpos = 0;
- scriptbuf->next = NULL;
- if(scriptlist != NULL) {
- while(scriptlist->next) {
- scriptlist = scriptlist->next;
- }
- scriptlist->next = scriptbuf;
- }
- if(memcmp(scriptbuf->buf, "#!", 2) == 0) {
- while((scriptbuf->curpos < scriptbuf->size) && ((char) scriptbuf->buf[scriptbuf->curpos] != '\n')) {
- (scriptbuf->curpos)++;
- }
- (scriptbuf->curpos)++;
- }
- close(scriptfp);
- return scriptbuf;
- }
-
- void preprocess_token_list(token_t* tokenlist) {
- script_t* newscript;
- token_t* me;
- char* cp;
-
- me = tokenlist;
- while(me) {
- if(memcmp(me->buf, open_tag, 2)) {
- me->tag = HTML;
- } else {
- me->tag = NOOP;
- me->buf[me->len] = '\0';
- cp = me->buf + 2;
- if(memcmp(cp, g_tag[ECHO], 1) == 0) {
- me->tag = ECHO;
- me->buf = find_whitespace(me->buf);
- me->len = strlen(me->buf);
- } else if(memcmp(cp, g_tag[TRANSLATE], 1) == 0) {
- me->tag = TRANSLATE;
- me->buf = find_whitespace(me->buf);
- me->len = strlen(me->buf);
- }
- if(isspace(*cp)) {
- me->tag = RUN;
- me->buf = cp;
- }
- if(me->tag == NOOP) {
- die_with_message(me->script, cp, g_err_msg[E_NO_OP]);
- }
- me->len = strlen(me->buf);
- }
- me = me->next;
- }
- }
-
- token_t* process_token_list(buffer_t* buf, token_t* token) {
- char *c;
-
- buffer_init(buf);
- subshell_exec(buf, "\n");
- while(token) {
- switch(token->tag) {
- case HTML:
- c = token->buf;
- while((c < (token->buf + token->len)) && (isspace(*c))) {
- c++;
- }
- if(c != token->buf + token->len) {
- subshell_echo (buf, token->buf, token->len);
- }
- break;
- case RUN:
- subshell_exec(buf, token->buf);
- subshell_exec(buf, "\n");
- break;
- case ECHO:
- subshell_eval(buf, token->buf, token->len);
- break;
- case TRANSLATE:
- subshell_translate(buf, token->buf, token->len);
- break;
- default:
- break;
- }
- token = token->next;
- }
- return token;
- }
-
- token_t* push_token_on_list(token_t* tokenlist, script_t* scriptbuf, char* start, size_t len) {
- token_t* me;
- token_t* next;
-
- if(len == 0) {
- return tokenlist;
- }
- me = (token_t*) xmalloc(sizeof(token_t));
- if(tokenlist == NULL) {
- next = NULL;
- } else {
- next = tokenlist->next;
- tokenlist->next = me;
- }
- me->next = next;
- me->script = scriptbuf;
- me->buf = start;
- me->len = len;
- return me;
- }
-
- void subshell_destroy(void) {
- int status;
- waitpid(subshell_pid, &status, 0);
- }
-
- void subshell_doscript(buffer_t* script, char* name) {
- static char postfix[] = "\nexit\n";
-
- write(subshell_pipe[PARENT_OUT], script->data, script->ptr - script->data);
- write(subshell_pipe[PARENT_OUT], postfix, strlen(postfix));
- return;
- }
-
- void subshell_echo(buffer_t* buf, char* str, size_t len) {
- static char echo_start[] = "printf '%s' '";
- static char echo_quote[] = "'\\''";
- static char echo_end[] = "'\n";
- const size_t maxlen = 3096;
- size_t pos;
-
- if(len == 0) {
- return;
- }
- pos = 0;
- buffer_add(buf, echo_start, strlen(echo_start));
- while(pos < len) {
- if (str[pos] == '\'') {
- buffer_add(buf, echo_quote, strlen(echo_quote));
- } else {
- buffer_add(buf, str + pos, 1);
- }
- pos++;
- if((pos % maxlen) == 0) {
- buffer_add(buf, echo_end, strlen(echo_end));
- buffer_add(buf, echo_start, strlen(echo_start));
- }
- }
- buffer_add(buf, echo_end, strlen(echo_end));
- }
-
- void subshell_eval(buffer_t* buf, char* str, size_t len) {
- static char echo_start[] = "echo -n ";
- static char echo_end[] = "\n";
-
- if(len == 0) {
- return;
- }
- str = trim(str);
- if(!*str) {
- return;
- }
- buffer_add(buf, echo_start, strlen(echo_start));
- buffer_add(buf, str, len);
- buffer_add(buf, echo_end, strlen(echo_end));
- }
-
- void subshell_exec(buffer_t* buf, char* str) {
- buffer_add (buf, str, strlen (str));
- return;
- }
-
- void subshell_setup (char* shell, list_t* env) {
- int retcode = 0;
- int count;
- argv_t* argv;
- char* av[20];
- list_t* next;
-
- if(shell == NULL) {
- return;
- }
- retcode = pipe(&subshell_pipe[PARENT_IN]);
- if(retcode == 0) {
- subshell_pid = fork();
- if(subshell_pid == -1) {
- die_with_message(NULL, NULL, g_err_msg[E_SUBSHELL_FAIL]);
- }
- if(subshell_pid == 0) {
- dup2(subshell_pipe[PARENT_IN], STDIN_FILENO);
- close(subshell_pipe[PARENT_IN]);
- close(subshell_pipe[PARENT_OUT]);
- count = argc_argv(shell, &argv);
- if(count > 19) {
- av[19] = "\0";
- count = 18;
- }
- while(count >= 0) {
- av[count] = argv[count].string;
- count--;
- }
- while(env) {
- next = env->next;
- putenv(env->buf);
- env = next;
- }
- execv(argv[0].string, av);
- free(argv);
- die_with_message(NULL, NULL, g_err_msg[E_SUBSHELL_FAIL]);
- } else {
- close(subshell_pipe[PARENT_IN]);
- }
- }
- }
-
- void subshell_translate(buffer_t* buf, char* str, size_t len) {
- static char echo_start[] = "echo -n \"";
- static char echo_end[] = "\"\n";
- short hash;
- lstr* i;
- char* text = NULL;
-
- if(len == 0) {
- return;
- }
- str = trim(str);
- if(!*str) {
- return;
- }
- if(language != NULL && translations > 0) {
- hash = generateHash(str);
- i = ltable[hash];
- while(text == NULL && i != NULL) {
- if(strcmp(str, i->msgid) == 0) {
- text = i->msgstr;
- } else {
- i = i->next;
- }
- }
- }
- if(text == NULL) {
- text = str;
- }
- buffer_add(buf, echo_start, strlen(echo_start));
- buffer_add(buf, text, strlen(text));
- buffer_add(buf, echo_end, strlen(echo_end));
- }
|