/* Copyright 2003 Renzo Davoli
* Licensed under the GPL
*/
#include <config.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include <sys/types.h>
#include <signal.h>
#include <fcntl.h>
#if 0
#define execvp(X,Y) \
({ char **y; \
fprintf(stderr,"execvp \"%s\" -",(X)); \
for (y=(Y); *y != NULL; y++) \
fprintf(stderr,"\"%s\"",*y); \
fprintf(stderr,"\n"); \
sleep (10); \
})
#endif
static char *progname;
int splitindex(int argc, char *argv[], int *dirchar)
{
register int i;
for (i=0; i<argc; i++) {
if (*dirchar == argv[i][0] && argv[i][1] == '=' ) {
(argv[i])++;*dirchar=0;
}
if (argv[i][0] == '=') {
if (argv[i][1] == '}' || argv[i][1] == '{')
*dirchar=argv[i][1];
break;
}
}
return i;
}
void usage()
{
fprintf(stderr,"Usage:\n\t%s cmd1 [arg1...] = cmd2 [arg2...]\n\n",progname);
kill(getpgrp(),SIGTERM);
exit (-1);
}
static int alternate_stdin;
static int alternate_stdout;
static void alternate_fd()
{
char numstr[10];
alternate_stdin=open("/dev/null",O_RDONLY);
alternate_stdout=open("/dev/null",O_RDONLY);
close(alternate_stdin);
close(alternate_stdout);
snprintf(numstr,10,"%d",alternate_stdin);
setenv("ALTERNATE_STDIN",numstr,1);
snprintf(numstr,10,"%d",alternate_stdout);
setenv("ALTERNATE_STDOUT",numstr,1);
}
int recmain(int argc, char *argv[],int olddirchar)
{
int split;
int newdirchar=olddirchar;
split=splitindex(argc,argv,&newdirchar);
if (split >= argc) {
if (newdirchar != 0)
usage();
execvp(argv[0],argv);
}
else {
char **argv1,**argv2;
int p1[2],p2[2];
if (argc < 3 || split == 0 || split == argc-1)
usage();
pipe(p1);
if (olddirchar == 0) pipe(p2);
argv[split]=NULL;
argv1=argv;
argv2=argv+(split+1);
if (fork()) {
switch (olddirchar) {
case 0:
close(p1[1]); close(p2[0]);
if (p1[0] != alternate_stdin){
dup2(p1[0],alternate_stdin);
close(p1[0]);
}
if (p1[0] != alternate_stdout){
dup2(p2[1],alternate_stdout);
close(p2[1]);
}
break;
case '}':
close(p1[0]);
dup2(p1[1],STDOUT_FILENO);
close(p1[1]);
break;
case '{':
close(p1[1]);
dup2(p1[0],STDIN_FILENO);
close(p1[0]);
break;
default:
fprintf(stderr,"CHECA\n");
}
execvp(argv1[0],argv1);
} else {
switch (olddirchar) {
case 0:
close(p2[1]); close(p1[0]);
dup2(p2[0],STDIN_FILENO);
dup2(p1[1],STDOUT_FILENO);
close(p2[0]); close(p1[1]);
break;
case '}':
close(p1[1]);
dup2(p1[0],STDIN_FILENO);
close(p1[0]);
break;
case '{':
close(p1[0]);
dup2(p1[1],STDOUT_FILENO);
close(p1[1]);
break;
default:
fprintf(stderr,"CHECA\n");
}
recmain(argc-split-1,argv2,newdirchar);
}
}
return 0;
}
int main(int argc, char *argv[])
{
int split;
char **argv1,**argv2;
int p1[2],p2[2];
int dirchar=0;
progname=argv[0];
argv++;
argc--;
alternate_fd();
split=splitindex(argc,argv,&dirchar);
if (argc < 3 || split == 0 || split >= argc-1)
usage();
pipe(p1);
pipe(p2);
argv[split]=NULL;
argv1=argv;
argv2=argv+(split+1);
if (fork()) {
close(p1[1]); close(p2[0]);
dup2(p1[0],STDIN_FILENO);
dup2(p2[1],STDOUT_FILENO);
close(p1[0]); close(p2[1]);
execvp(argv1[0],argv1);
} else {
close(p2[1]); close(p1[0]);
dup2(p2[0],STDIN_FILENO);
dup2(p1[1],STDOUT_FILENO);
close(p1[1]); close(p2[0]);
recmain(argc-split-1,argv2,dirchar);
}
return (0);
}
syntax highlighted by Code2HTML, v. 0.9.1