📄 gbx_c_process.c
字号:
/*************************************************************************** CProcess.c The process management class (c) 2000-2004 Beno顃 Minisini <gambas@users.sourceforge.net> 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define __GBX_C_PROCESS_C#include "gb_common.h"#include "gb_common_buffer.h"#include <signal.h>#include <fcntl.h>#include <sys/wait.h>#include <sys/time.h>#include <sys/resource.h>#include "gbx_api.h"#include "gambas.h"#include "gbx_stream.h"#include "gb_array.h"#include "gbx_exec.h"#include "gbx_trace.h"#include "gbx_class.h"#include "gbx_watch.h"#include "gbx_c_array.h"#include "gbx_c_process.h"//#define DEBUG_MEextern char **environ;DECLARE_EVENT(EVENT_Read);DECLARE_EVENT(EVENT_Error);DECLARE_EVENT(EVENT_Kill);static CPROCESS *RunningProcessList = NULL;static int _pipe_child[2];static bool _init = FALSE;static void init_child(void);static void exit_child(void);static void callback_write(int fd, int type, CPROCESS *process){ #if 0 if (process->to_string) { int n = read(fd, COMMON_buffer, 256); if (n > 0) { STRING_add(&process->result, COMMON_buffer, n); CSTREAM_stream(process)->process.read_something = TRUE; #ifdef DEBUG_ME fprintf(stderr, "callback_write: result = '%s'\n", process->result); #endif } } else #endif if (!STREAM_eof(CSTREAM_stream(process))) //process->running && GB_Raise(process, EVENT_Read, 0);}static int callback_error(int fd, int type, CPROCESS *process){ /*fprintf(stderr, ">> Write\n"); fflush(stderr);*/ char buffer[256]; int n; n = read(fd, buffer, sizeof(buffer)); if (n <= 0) /* || !process->running)*/ { /*close(process->err);*/ return TRUE; } /*printf("callback_error: (%d) %.*s\n", n, n, buffer);*/ GB_Raise(process, EVENT_Error, 1, GB_T_STRING, buffer, n); return FALSE; /*fprintf(stderr, "<< Write\n"); fflush(stderr);*/}static void update_stream(CPROCESS *process){ STREAM *stream = &process->ob.stream; stream->type = &STREAM_process; (*stream->type->open)(stream, NULL, 0, process);}static void init_process(CPROCESS *process){ process->watch = GB_WATCH_NONE; process->in = process->out = process->err = -1; update_stream(process);}static void exit_process(CPROCESS *_object){ /* Normalement impossible */ /* if (THIS->running) { fprintf(stderr, "WARNING: CPROCESS_free: running ?\n"); stop_process(THIS); } */ #ifdef DEBUG_ME fprintf(stderr, "exit_process: %p\n", _object); #endif if (THIS->in >= 0) { if (THIS->in != THIS->out) close(THIS->in); THIS->in = -1; } if (THIS->out >= 0) { GB_Watch(THIS->out, GB_WATCH_NONE, NULL, 0); close(THIS->out); THIS->out = -1; } if (THIS->err >= 0) { GB_Watch(THIS->err, GB_WATCH_NONE, NULL, 0); close(THIS->err); THIS->err = -1; } update_stream(THIS);}static void stop_process_after(CPROCESS *_object){ STREAM *stream; //long long len; #ifdef DEBUG_ME fprintf(stderr, "stop_process_after: %p\n", _object); #endif /* Vidage du tampon d'erreur */ if (THIS->err >= 0) while (callback_error(THIS->err, 0, THIS) == 0); /* Vidage du tampon de sortie */ if (THIS->out >= 0) { stream = CSTREAM_stream(THIS); while (!STREAM_eof(stream)) { stream->process.read_something = FALSE; callback_write(THIS->out, 0, THIS); //GB_Raise(THIS, EVENT_Read, 0); if (!stream->process.read_something) break; } } GB_Raise(THIS, EVENT_Kill, 0); exit_process(THIS); GB_Detach(THIS); /*printf("** stop_process_after\n");*/ //GB_Unref((void **)&_object); /* Ref du post */}static void stop_process(CPROCESS *process){ if (!process->running) return; #ifdef DEBUG_ME fprintf(stderr, "stop_process: %p\n", process); #endif /*process->pid = -1;*/ /* Remove from running process list */ if (process->prev) process->prev->next = process->next; if (process->next) process->next->prev = process->prev; if (process == RunningProcessList) RunningProcessList = process->next; process->running = FALSE; /*printf("** stop_process\n");*/ stop_process_after(process); GB_Unref((void **)&process); /* Le processus ne tourne plus */ if (!RunningProcessList) exit_child();}static void run_process(CPROCESS *process, int mode, void *cmd){ static const char *shell[] = { "sh", "-c", NULL, NULL }; int fdin[2], fdout[2], fderr[2]; pid_t pid; char **argv; CARRAY *array; int n; sigset_t sig, old; /* for terminal */ /*int fd_master = -1; int fd_slave; char *slave = NULL; struct termios termios_stdin; struct termios termios_master;*/ init_child(); if (mode & PM_SHELL) { #ifdef DEBUG_ME fprintf(stderr, "run_process %p: %s\n", process, (char *)cmd); #endif argv = (char **)shell; argv[2] = (char *)cmd; if (argv[2] == NULL || *argv[2] == 0) { /*stop_process(process, FALSE);*/ return; } } else { array = (CARRAY *)cmd; n = ARRAY_count(array->data); if (n == 0) { /*stop_process(process, FALSE);*/ return; } ALLOC(&argv, sizeof(*argv) * (n + 1), "run_process"); memcpy(argv, array->data, sizeof(*argv) * n); argv[n] = NULL; #ifdef DEBUG_ME { int i; fprintf(stderr, "run_process %p: ", process); for (i = 0; i < n; i++) fprintf(stderr, "%s ", argv[i]); fprintf(stderr, "\n"); } #endif } /*printf("** run_process\n");*/ GB_Ref(process); /* Process is running */ /* Adding to the running process list */ if (RunningProcessList) RunningProcessList->prev = process; process->next = RunningProcessList; process->prev = NULL; RunningProcessList = process; process->running = TRUE; #if 0 if (mode & PM_STRING) { process->to_string = TRUE; process->result = NULL; mode |= PM_READ; } #endif #if 0 if (mode & PM_TERM) { fd_master = getpt(); if (fd_master < 0) THROW_SYSTEM(errno, NULL); grantpt(fd_master); unlockpt(fd_master); slave = ptsname(fd_master); tcgetattr(STDIN_FILENO, &termios_stdin); } else #endif { /* Create pipes */ if ((mode & PM_WRITE) && pipe(fdin) != 0) THROW_SYSTEM(errno, NULL); if ((mode & PM_READ) && (pipe(fdout) != 0 || pipe(fderr) != 0)) THROW_SYSTEM(errno, NULL); } /* Block SIGCHLD */ sigemptyset(&sig); sigaddset(&sig, SIGCHLD); sigprocmask(SIG_BLOCK, &sig, &old); pid = fork(); if (pid == (-1)) { stop_process(process); sigprocmask(SIG_SETMASK, &old, &sig); THROW_SYSTEM(errno, NULL); } if (pid) { process->pid = pid; #ifdef DEBUG_ME fprintf(stderr, "fork: pid = %d\n", pid); #endif /*printf("Running process %d\n", pid); fflush(NULL);*/ #if 0 if (mode & PM_TERM) { tcgetattr(fd_master, &termios_master); cfmakeraw(&termios_master); //termios_master.c_lflag &= ~ECHO; tcsetattr(fd_master, TCSANOW, &termios_master); } #endif if (mode & PM_WRITE) { #if 0 if (mode & PM_TERM) { process->in = fd_master; } else #endif { close(fdin[0]); process->in = fdin[1]; } } if (mode & PM_READ) { #if 0 if (mode & PM_TERM) { process->out = fd_master;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -