/* * SPL - The SPL Programming Language * Copyright (C) 2004, 2005 Clifford Wolf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * mod_system.c: Module for calling shell commands */ /** * This module provides a simple API for calling shell commands */ #include #include #include #include #include "spl.h" #include "compat.h" extern void SPL_ABI(spl_mod_system_init)(struct spl_vm *vm, struct spl_module *mod, int restore); extern void SPL_ABI(spl_mod_system_done)(struct spl_vm *vm, struct spl_module *mod); /** * This function calls the specified shell command and returns the text written * to stdout. * * If the output is not UTF-8 encoded, the encoding must be specified with a * 2nd parameter. Valid encodings are the same as for the '#encoding' compiler * pragma (see 'SPL Language Reference' for a list). * * If UTF-8 encoding is expected but the output fails to pass the UTF-8 test, * the output is assumed to be latin1 encoded. * * A newline at the end of the output is automatically removed. */ // builtin system(command, encoding) static struct spl_node *handler_system(struct spl_task *task, void UNUSED(*data)) { char *command = spl_clib_get_string(task); char *encoding = spl_clib_get_string(task); char *output = malloc(512); int len = 0; int buffer = 512; int p[2]; pipe(p); int pid = fork(); if ( !pid ) { close(1); close(p[0]); dup2(p[1], 1); if (task->vm->current_dir_name) chdir(task->vm->current_dir_name); execlp("sh", "sh", "-c", command, NULL); _exit(1); } close(p[1]); while (1) { int rc = read(p[0], output+len, 512); if (rc <= 0) break; len += rc; if (len + 512 > buffer) { buffer = len*2 + 512; output = realloc(output, buffer); } } close(p[0]); waitpid(pid, 0, 0); output = realloc(output, len+1); output[len] = 0; if (len > 0 && output[len-1] == '\n') output[len-1] = 0; if (*encoding) { char *old_output = output; output = spl_utf8_import(old_output, encoding); if (!output) output = old_output; else free(old_output); } if (spl_utf8_check(output)) { char *old_output = output; output = spl_utf8_import(old_output, "latin_1"); free(old_output); /* this should never happen */ if (!output) output = strdup(""); } return SPL_NEW_STRING(output); } void SPL_ABI(spl_mod_system_init)(struct spl_vm *vm, struct spl_module UNUSED(*mod), int UNUSED(restore)) { spl_clib_reg(vm, "system", handler_system, 0); } void SPL_ABI(spl_mod_system_done)(struct spl_vm UNUSED(*vm), struct spl_module UNUSED(*mod)) { return; }