Index: ossp-pkg/l2/l2_ch_pipe.c RCS File: /v/ossp/cvs/ossp-pkg/l2/l2_ch_pipe.c,v rcsdiff -q -kk '-r1.11' '-r1.12' -u '/v/ossp/cvs/ossp-pkg/l2/l2_ch_pipe.c,v' 2>/dev/null --- l2_ch_pipe.c 2001/09/18 14:38:51 1.11 +++ l2_ch_pipe.c 2001/09/19 16:39:44 1.12 @@ -31,39 +31,51 @@ #include #include +#include #define L2_PIPE_MODEDIRECT 1 /* direct command execution */ #define L2_PIPE_MODESHELL 2 /* shell command execution */ #define L2_PIPE_MAXARGS 256 /* shell command execution */ +static l2_result_t hook_open(l2_context_t *, l2_channel_t *); /* prototypes */ + + /* declare private channel configuration */ typedef struct { - int piFd[2]; /* pipe file descriptor */ - int iMode; /* execution mode direct or shell */ - char *szCmdpath; /* path to command and arguments */ - char *pVec[L2_PIPE_MAXARGS]; /* vector of command and params */ + int piFd[2]; /* pipe file descriptor */ + int iMode; /* execution mode direct or shell */ + pid_t Pid; /* pid set during fork in hook_open() */ + char *szCmdpath; /* path to command and arguments */ } l2_ch_pipe_t; static void catchsignal(int sig, ...) { - va_list ap; - static l2_ch_pipe_t *cfg = NULL; - - va_start(ap, sig); - if (sig == 0) - cfg = va_arg(ap, l2_ch_pipe_t *); + int iStatus = 0; + va_list ap = NULL; + static l2_context_t *ctx = NULL; + static l2_channel_t *chan = NULL; + + if (sig == 0) { + va_start(ap, sig); + ctx = va_arg(ap, l2_context_t *); + chan = va_arg(ap, l2_channel_t *); + va_end(ap); + } else if (sig == SIGCHLD) { - fprintf(stderr, "Pipe: SIGCHLD caught\n"); - close(cfg->piFd[1]); - cfg->piFd[1] = -1; /* TODO: Fill in with new pipe fd */ +/* TRACE("SIGCHLD caught\n");*/ + waitpid(((l2_ch_pipe_t *)ctx->vp)->Pid, &iStatus, 0); + close(((l2_ch_pipe_t *)ctx->vp)->piFd[1]); + ((l2_ch_pipe_t *)ctx->vp)->piFd[1] = -1; + if (hook_open(ctx, chan) != L2_OK) { /* TODO: Fix infinit loop! */ + close(((l2_ch_pipe_t *)ctx->vp)->piFd[1]); + ((l2_ch_pipe_t *)ctx->vp)->piFd[1] = -1; + } } else if (sig == SIGPIPE) { - fprintf(stderr, "Pipe: SIGPIPE caught\n"); - close(cfg->piFd[1]); - cfg->piFd[1] = -1; /* TODO: Fill in with new pipe fd */ - /* ((l2_ch_pipe_t *)(int *)ctx->vp)->piFd[1] = -1; */ +/* TRACE("SIGPIPE caught\n");*/ + close(((l2_ch_pipe_t *)ctx->vp)->piFd[1]); + ((l2_ch_pipe_t *)ctx->vp)->piFd[1] = -1; } - va_end(ap); } /* create channel */ @@ -80,7 +92,6 @@ cfg->piFd[1] = -1; cfg->iMode = -1; cfg->szCmdpath = NULL; - memset(cfg->pVec, 0, sizeof(cfg->pVec)); /* link private channel configuration into channel context */ ctx->vp = cfg; @@ -94,26 +105,43 @@ l2_ch_pipe_t *cfg = (l2_ch_pipe_t *)ctx->vp; l2_param_t pa[3]; l2_result_t rv; - char szMode[16]; /* just eneough for double-byte "direct" and NULL */ + FILE *File; + char *szTemp; + char *pbIndex; /* feed and call generic parameter parsing engine */ - L2_PARAM_SET(pa[0], mode, CHARPTR, szMode); + L2_PARAM_SET(pa[0], mode, CHARPTR, &szTemp); L2_PARAM_SET(pa[1], path, STRING, &cfg->szCmdpath); L2_PARAM_END(pa[2]); - rv = l2_util_setparams(pa, fmt, ap); + if ((rv = l2_util_setparams(pa, fmt, ap)) != L2_OK) + return rv; - if (strcmp(szMode, "direct") == NULL) + if (strcmp(szTemp, "direct") == NULL) cfg->iMode = L2_PIPE_MODEDIRECT; - else if (strcmp(szMode, "shell") == NULL) + else if (strcmp(szTemp, "shell") == NULL) cfg->iMode = L2_PIPE_MODESHELL; else return L2_ERR_ARG; - catchsignal(0, cfg); /* initialize signal handler with incoming context */ + /* check to see if a file exists at the user specified path */ + if(cfg->iMode != L2_PIPE_MODESHELL) { + szTemp = strdup(cfg->szCmdpath); + for (pbIndex = szTemp; *pbIndex != NULL; pbIndex++); + *pbIndex = NULL; + if (!(File = fopen(szTemp, "r"))) + return L2_ERR_ARG; /* the command does not exist at the given path */ + else + fclose(File); + free(szTemp); + szTemp = NULL; + pbIndex = NULL; + } + + catchsignal(0, ctx, ch); /* initialize signal handler with context & ch */ signal(SIGCHLD, (void(*)())catchsignal); /* pipe changes descriptor */ signal(SIGPIPE, (void(*)())catchsignal); /* pipe closes reading fd */ - return rv; + return rv; /* all okay */ } /********************************************************** @@ -122,14 +150,15 @@ **********************************************************/ static l2_result_t parse_cmdpath (char *szBuf, char *szArgs[]) { int iCnt = 0; + while ((iCnt++ < L2_PIPE_MAXARGS) && (*szBuf != NULL)) { while ((*szBuf == ' ') || (*szBuf == '\t')) - *szBuf++ = '\0'; - *szArgs++ = szBuf; + *szBuf++ = '\0'; /* overwrite whitespace with EOL */ + *szArgs++ = szBuf; /* found the start of a new token */ while ((*szBuf != '\0') && (*szBuf != ' ') && (*szBuf != '\t')) szBuf++; } - *szArgs = NULL; + *szArgs = NULL; /* add a NULL to mark the end of the chain */ if (iCnt <= L2_PIPE_MAXARGS) return L2_OK; @@ -137,47 +166,48 @@ return L2_ERR_ARG; } -/********************************************************** - * child_exec: Helper method to hook_open * - * Redirect stdin to read from cfg->piFd. Exec a given * - * command or passes it to the sh shell for execution. * - **********************************************************/ -static l2_result_t child_exec(l2_ch_pipe_t *cfg) +/* open channel */ +static l2_result_t hook_open(l2_context_t *ctx, l2_channel_t *ch) { + l2_ch_pipe_t *cfg = (l2_ch_pipe_t *)ctx->vp; + char *pVec[L2_PIPE_MAXARGS]; + l2_result_t rv; + /* make sure a command path was set */ if (cfg->szCmdpath == NULL) return L2_ERR_USE; - close(cfg->piFd[1]); /* close the writing end, */ - cfg->piFd[1] = -1; /* because we don't use it */ - dup2(cfg->piFd[0], fileno(stdin)); /* copy the reading end */ + memset(pVec, 0, sizeof(pVec)); - return execvp(*cfg->pVec, cfg->pVec); /* launch */ -} - -/* open channel */ -static l2_result_t hook_open(l2_context_t *ctx, l2_channel_t *ch) -{ - l2_ch_pipe_t *cfg = (l2_ch_pipe_t *)ctx->vp; - l2_result_t rv; - pid_t Pid; + /* the distinction between modes is necessary, because only executing */ + /* commands in a shell environment allows usage of variables and such */ + if (cfg->iMode == L2_PIPE_MODESHELL) { + pVec[0] = "/bin/sh"; + pVec[1] = "-c"; + pVec[2] = cfg->szCmdpath; + pVec[3] = NULL; /* add a NULL to mark the end of the chain */ + } - if ((rv = parse_cmdpath(cfg->szCmdpath, cfg->pVec)) != L2_OK) - return rv; + else /* plain command execution */ + if ((rv = parse_cmdpath(cfg->szCmdpath, pVec)) != L2_OK) + return rv; - if (pipe(cfg->piFd) == -1) /* open the pipe */ + if (pipe(cfg->piFd) == -1) /* open the pipe */ return L2_ERR_SYS; - if ((Pid = fork()) > 0) { /* parent process */ - close(cfg->piFd[0]); + if ((cfg->Pid = fork()) > 0) { /* parent process */ + close(cfg->piFd[0]); /* half-duplex (no reading) */ cfg->piFd[0] = -1; } - else if ((Pid = fork()) == 0) { /* child process */ - /* if child returns, there was an error */ - if (child_exec(cfg) == -1) { - close(cfg->piFd[0]); + else if (cfg->Pid == 0) { /* child process */ + close(cfg->piFd[1]); /* close the writing end, */ + cfg->piFd[1] = -1; /* because we don't use it */ + dup2(cfg->piFd[0], fileno(stdin)); /* copy the reading end */ + + if (execvp(*pVec, pVec) == -1) { /* launch */ + close(cfg->piFd[0]); /* cleanup */ cfg->piFd[0] = -1; - return L2_ERR_SYS; + return L2_ERR_SYS; /* if child returns, we have an error */ } } else /* fork failed */ @@ -192,12 +222,11 @@ { l2_ch_pipe_t *cfg = (l2_ch_pipe_t *)ctx->vp; - /* validate the pipe fd */ - if (cfg->piFd[1] == -1) /* TODO: possibly remove this validation in */ - return L2_ERR_ARG; /* lieu of incoming SIGPIPE signal */ + if (cfg->piFd[1] == -1) + return L2_ERR_IO; /* write message to channel pipe */ - if (write(cfg->piFd[1], buf, buf_size) == -1) + else if (write(cfg->piFd[1], buf, buf_size) == -1) return L2_ERR_SYS; return L2_OK; @@ -221,7 +250,7 @@ l2_ch_pipe_t *cfg = (l2_ch_pipe_t *)ctx->vp; /* destroy channel configuration */ - free(&cfg->szCmdpath); + free(cfg->szCmdpath); cfg->szCmdpath = NULL; free(cfg); Index: ossp-pkg/l2/l2_test.c RCS File: /v/ossp/cvs/ossp-pkg/l2/l2_test.c,v rcsdiff -q -kk '-r1.25' '-r1.26' -u '/v/ossp/cvs/ossp-pkg/l2/l2_test.c,v' 2>/dev/null --- l2_test.c 2001/09/18 14:41:28 1.25 +++ l2_test.c 2001/09/19 16:39:44 1.26 @@ -131,13 +131,18 @@ if (l2_stream_channel(st, chSyslog, L2_LEVEL_UPTO(L2_LEVEL_WARNING), L2_LEVEL_NONE) != L2_OK) die("failed to attach channel syslog into stream"); -#endif +#endif /* Syslog */ #ifdef WITH_PIPE if ((chPipe = l2_channel_create(&l2_handler_pipe)) == NULL) /* Pipe */ die("failed to create pipe channel"); - if (l2_channel_configure(chPipe, "pipe", pipdesc[1]) != L2_OK) +#if 0 + if (l2_channel_configure(chPipe, "mode,path", "direct", "/u/ms/travail/cronolinux/sbin/cronolog -o /u/ms/tmp/crono.log") != L2_OK) + die("failed to configure pipe channel"); +#endif + + if (l2_channel_configure(chPipe, "mode,path", "shell", "$CRONOLOGDIR/cronolog -o $HOME/tmp/crono.log") != L2_OK) die("failed to configure pipe channel"); if (l2_channel_open(chPipe) != L2_OK) @@ -145,7 +150,7 @@ if (l2_stream_channel(st, chPipe, L2_LEVEL_UPTO(L2_LEVEL_WARNING), L2_LEVEL_NONE) != L2_OK) die("failed to attach channel pipe into stream"); -#endif +#endif /* Pipe */ #ifdef WITH_SOCKET /* Atenzione! Before doing any socket testing, make sure you have a valid */ @@ -167,7 +172,7 @@ if (l2_stream_channel(st, chSock, L2_LEVEL_UPTO(L2_LEVEL_WARNING), L2_LEVEL_NONE) != L2_OK) die("failed to attach channel socket into stream"); -#endif +#endif /* Socket */ #ifdef WITH_SMTP if ((chSmtp = l2_channel_create(&l2_handler_smtp)) == NULL) /* SMTP */ @@ -181,7 +186,7 @@ if (l2_stream_channel(st, chSmtp, L2_LEVEL_UPTO(L2_LEVEL_ERROR), L2_LEVEL_NONE) != L2_OK) die("failed to attach smtp channel into stream"); -#endif +#endif /* SMTP */ if (l2_stream_levels(st, L2_LEVEL_UPTO(L2_LEVEL_WARNING), L2_LEVEL_NONE) != L2_OK) die("failed to set global logging level");