This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-mbse/lib/expipe.c
2001-08-17 05:46:24 +00:00

197 lines
4.6 KiB
C

/*****************************************************************************
*
* File ..................: expipe.c
* Purpose ...............: MBSE BBS Execute pipe
* Last modification date : 22-Apr-2001
*
*****************************************************************************
* Copyright (C) 1997-2001
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS 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, or (at your option) any
* later version.
*
* MBSE BBS 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 MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*****************************************************************************/
#include "libs.h"
#include "structs.h"
#include "records.h"
#include "clcomm.h"
#include "common.h"
static struct _fppid {
FILE *fp;
int pid;
} fppid[] = {
{NULL, 0}, {NULL, 0}, {NULL, 0}
};
#define maxfppid 2
FILE *expipe(char *cmd, char *from, char *to)
{
char buf[256], *buflimit;
char *vector[16];
int i, rc;
char *p, *q, *f=from, *t=to;
int pipedes[2];
FILE *fp;
int pid, slot;
buflimit = buf + sizeof(buf) -1 - (f&&t&&(strlen(f)>strlen(t))?strlen(f):t?strlen(t):0);
for (slot = 0; slot <= maxfppid; slot++) {
if (fppid[slot].fp == NULL)
break;
}
if (slot > maxfppid) {
WriteError("Attempt to pipe more than %d processes", maxfppid + 1);
return NULL;
}
for (p = cmd, q = buf; (*p); p++) {
if (q > buflimit) {
WriteError("Attempt to pipe too long command");
return NULL;
}
switch (*p) {
case '$': switch (*(++p)) {
case 'f':
case 'F': if ((f))
while (*f)
*(q++) = *(f++);
f=from;
break;
case 't':
case 'T': if ((t))
while (*t)
*(q++) = *(t++);
t=to;
break;
default: *(q++)='$';
*(q++)=*p;
break;
}
break;
case '\\': *(q++) = *(++p);
break;
default: *(q++) = *p;
break;
}
}
*q = '\0';
Syslog('+', "Expipe: %s",buf);
i = 0;
vector[i++] = strtok(buf," \t\n");
while ((vector[i++] = strtok(NULL," \t\n")) && (i<16));
vector[15] = NULL;
fflush(stdout);
fflush(stderr);
if (pipe(pipedes) != 0) {
WriteError("$Pipe failed for command \"%s\"", MBSE_SS(vector[0]));
return NULL;
}
Syslog('e', "pipe() returned read=%d, write=%d", pipedes[0], pipedes[1]);
if ((pid = fork()) == 0) {
close(pipedes[1]);
close(0);
if (dup(pipedes[0]) != 0) {
WriteError("$Reopen of stdin for command %s failed", MBSE_SS(vector[0]));
exit(-1);
}
rc = execv(vector[0],vector);
WriteError("$Exec \"%s\" returned %d", MBSE_SS(vector[0]), rc);
exit(-1);
}
close(pipedes[0]);
if ((fp = fdopen(pipedes[1],"w")) == NULL) {
WriteError("$fdopen failed for pipe to command \"%s\"", MBSE_SS(vector[0]));
}
fppid[slot].fp = fp;
fppid[slot].pid = pid;
return fp;
}
int exclose(FILE *fp)
{
int status, rc;
int pid, slot, sverr;
for (slot = 0; slot <= maxfppid; slot++) {
if (fppid[slot].fp == fp)
break;
}
if (slot > maxfppid) {
WriteError("Attempt to close unopened pipe");
return -1;
}
pid = fppid[slot].pid;
fppid[slot].fp = NULL;
fppid[slot].pid = 0;
Syslog('e', "Closing pipe to the child process %d",pid);
if ((rc = fclose(fp)) != 0) {
WriteError("$Error closing pipe to transport (rc=%d)", rc);
if ((rc = kill(pid,SIGKILL)) != 0)
WriteError("$kill for pid %d returned %d",pid,rc);
}
Syslog('e', "Waiting for process %d to finish",pid);
do {
rc = wait(&status);
sverr = errno;
if (status)
Syslog('e', "$Wait returned %d, status %d,%d", rc, status >> 8, status & 0xff);
} while (((rc > 0) && (rc != pid)) || ((rc == -1) && (sverr == EINTR)));
switch (rc) {
case -1:WriteError("$Wait returned %d, status %d,%d", rc, status >> 8, status & 0xff);
return -1;
case 0: return 0;
default:
if (WIFEXITED(status)) {
rc = WEXITSTATUS(status);
if (rc) {
WriteError("Expipe: returned error %d", rc);
return rc;
}
}
if (WIFSIGNALED(status)) {
rc = WTERMSIG(status);
WriteError("Wait stopped on signal %d", rc);
return rc;
}
if (rc)
WriteError("Wait stopped unknown, rc=%d", rc);
return rc;
}
return 0;
}