I am trying to execute multiple commands in my customised shell using pipe. While the code doesn't show any error, the terminal just hangs there without any output. My code snippet is as follows :
void exe_pipe(char *pipe1[])
{
int pipe_end[2*l], n=0;
for( i = 0; i < l; i++ ) {
pipe ( pipe_end + i*2 );
}
for( m = 0; m < (l+1); m++ ) // l is no. of pipes
{
pid = fork();
if( pid == 0 )
{
if ( m > 0 )
dup2( pipe_end[ (n-1)*2] , 0 );
if ( m < (l+1) )
dup2( pipe_end[ (n*2)+1] , 1 );
execlp( pipe1[m], pipe1[m], (char*)NULL );
}
}
for( i = 0; i < 2 * l; i++ )
{
close( pipe_end[i] );
}
while(waitpid(-1, NULL, 0) != -1);
}
Ok I think I got it. My edits :
for( m = 0; m < l+1; m++ )
{
pid = fork();
if( pid == 0 )
{
if ( m > 0 )
{
dup2( pipe_end[ (m-1)*2 ] , 0 );
}
if ( m < (l+1) )
{
dup2( pipe_end[ (m*2)+1 ] , 1 );
}
for(i = 0; i < 2 * l; i++){
close(pipe_end[i]);}
execlp( pipe1[m], pipe1[m], (char*)NULL );
}
}
Related
I'm trying to write a function that copies all of the values in source1 which are also found in source2 into a destination and then returns the number of elements copied into the destination.
int common_elements(int length, int source1[length], int source2[length], int destination[length])
{
int counter = 0;
int i = 0;
while (i < length) {
int j = 0;
while (j < length) {
if ( source1[i] == source2[j]) {
destination[counter] = source1[i];
counter++;
}
j++;
}
i++;
}
return counter;
}
The problem is e.g. given (common_elements(5, {1,2,3,4,5}, {1,2,3,2,1}, [])), the correct input should be
1,2,3
return value: 3
However, the program is accounting for the duplicates and produces :
1,1,2,2,3
return value: 5
which is incorrect.
How can I remedy this?
In this while loop
int j = 0;
while (j < length) {
if ( source1[i] == source2[j]) {
destination[counter] = source1[i];
counter++;
}
j++;
}
you are counting all elements in the array source2 that are equal to the element source1[i].
I can suggest the following solution provided that the source arrays may not be changed within the function.
#include <stdio.h>
size_t common_elements( int destination[],
const int source1[],
const int source2[],
size_t n )
{
size_t counter = 0;
for ( size_t i = 0; i < n; i++ )
{
size_t number = 1;
for ( size_t j = 0; j < i; j++ )
{
if ( source1[i] == source1[j] ) ++number;
}
for ( size_t j = 0; number && j < n; j++ )
{
if ( source1[i] == source2[j] ) --number;
}
if ( number == 0 ) destination[counter++] = source1[i];
}
return counter;
}
int main(void)
{
enum { N = 5 };
int source1[N] = { 1, 2, 3, 4, 5 };
int source2[N] = { 1, 2, 3, 2, 1 };
int destination[N];
size_t n = common_elements( destination, source1, source2, N );
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", destination[i] );
}
putchar( '\n' );
return 0;
}
The program output is
1 2 3
I'm learning C and currently i'm trying to make a shell. Anyway i made a test program to figure out how multiple pipes work. I changed the program to use a single pipe command and it prints the result fine. Then i changed it back to this code where that runs it for 2 pipes, but i always get output 0. I really have no clue why the output is 0. Can you help me?
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <fcntl.h>
int main(int argc, char * argv[])
{
int j;
pid_t pid;
int pfd[4];
char * ls[] = {"ls","-l",0};
char * sort[] = {"sort","-u",0};
char * wc[] = {"wc","-l",0};
int fd = open("outputfolder.txt", O_WRONLY | O_CREAT | O_APPEND);
for ( int i = 0; i < 4; i++ )
{
if ( pipe(pfd + i*2) < 0 )
{
perror("pipe\n");
exit(EXIT_FAILURE);
}
}
for ( int i = 0; i <= 2; i ++ )
{
if ( i == 2 )
{
pid = fork();
if ( pid == 0 )
{
if ( dup2(pfd[(i-1)*2],0) < 0 )
{
perror("dup2\n");
exit(EXIT_FAILURE);
}
if ( dup2(fd,1) < 0 )
{
perror("dup2\n");
exit(EXIT_FAILURE);
}
for (j = 0; j < 4; j++ )
{
close(pfd[j]);
}
if ( execvp(wc[0],wc) < 0 )
{
perror("execvpwc\n");
exit(EXIT_FAILURE);
}
}
else if ( pid == -1 )
{
perror("fork\n");
exit(EXIT_FAILURE);
}
}
else if ( i != 2 )
{
pid = fork();
if ( pid == 0 )
{
if ( i != 0 )
{
if ( dup2(pfd[(i-1)*2],0) < 0 )
{
perror("dup2\n");
exit(EXIT_FAILURE);
}
}
if ( dup2(pfd[i*2+1],1) < 0 )
{
perror("dup2\n");
exit(EXIT_FAILURE);
}
for ( j = 0; j < 4; j++ )
{
close(pfd[j]);
}
if (i == 0)
{
if ( execvp(ls[0],ls) < 0 )
{
perror("execvpls\n");
exit(EXIT_FAILURE);
}
}
else if ( i == 1 )
{
if ( execvp(sort[0],sort) < 0 )
{
perror("execvpsort\n");
exit(EXIT_FAILURE);
}
}
}
else if ( pid == -1 )
{
perror("fork\n");
exit(EXIT_FAILURE);
}
}
}
for ( j = 0; j < 4; j++ )
{
close(pfd[j]);
}
while(waitpid(0,0,0)>=0);
return 0;
}
EDIT: The number that it should print should be 19 for my directory
I need to copy a two-dimensional array into a second, identically-sized array, but the while loops finishes before I want it to, and I don't know why.
Here is my code.
memcpy( array2, array1, sizeof(array1) );
do
{
for( i = 0; i < rows; i++ )
{
for( j = 0; j < columns; j++ )
{
if( array1[i][j] == '!' )
{
if( array1[(i + 1)][j] == 'o' )
{
array2[(i + 1)][j] = '!';
condition1 = 1;
}
else
{
condition1 = 0;
}
if( array1[(i - 1)][j] == 'o' )
{
array2[(i - 1)][j] = '!';
condition2 = 1;
}
else
{
condition2 = 0;
}
if( array1[i][(j + 1)] == 'o' )
{
array2[i][(j + 1)] = '!';
contidion3 = 1;
}
else
{
condition3 = 0;
}
if( array1[i][(j - 1)] == 'o' )
{
array2[i][(j - 1)] = '!';
condition4 = 1;
}
else
{
condition4 = 0;
}
}
}
}
memcpy( array1, array2, sizeof(array2) );
count++;
}
while( condition1 != 0 && condition2 != 0 && condition3 != 0 && condition4 != 0 );
I've checked the state of each of the 4 condition variables, but every time I print them out I recieve 1 for all of them. I will be grateful for any advice.
I am trying to get the highest and lowest value from last 20 bar. I have no issue to obtaining highest value, however my code doesn't seem to work properly in order to obtain the lowest value. Just wondering if there is any suggestion about it.
OnEveryNewBar1();
void OnEveryNewBar1()
{ PipValue = 1;
if ( NDigits == 3 || NDigits == 5 ) PipValue = 10;
if ( BarTime1 < Time[0] ) // we have a new bar opened
{ BarTime1 = Time[0]; // keep the new bar open time
TechnicalAnalysis_S();
TechnicalAnalysis_L();
}
}
void TechnicalAnalysis_S()
{
int m = 2;
int n = 3;
l = 1000;
while ( m <= 20 )
{
if ( 1 < 2 )
{ if ( ( Close[2] > Open[2] ) || ( Close[1] > Open[1] ) ) int i = 2;
while ( i > 0 )
{
if ( Low[i] < l ) l = Low[i];
i = i - 1;
}
print ( "Lowest" + l );
l = 1000;
}
m++;
n++;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void TechnicalAnalysis_L()
{
int m = 2;
int n = 3;
while ( m <= 20 )
{
if ( 2 > 0 )
{
if ( ( Close[2] < Open[2] ) || ( Close[1] < Open[1] ) ) int i=2;
while ( i > 0 )
{
if ( High[i] > h ) h = High[i];
i = i - 1;
}
print ( "Highest" + h );
h = 0;
}
m++;
n++;
}
}
While there are some strange parts in the code, while some variables are missing their declaration, the language has built-in functions for this.
Solution:
double aLowestLOW_InTheLast20BARs,
aHighestHIGH_InTheLast20BARs;
// -----------------------------------------------------------------------------
aLowestLOW_InTheLast20BARs = Low[iLowest( _Symbol, // .self
PERIOD_CURRENT, // .self
MODE_LOW, // LOW
20, // Last 20 BARs
0 // from [0]
)
];
// -----------------------------------------------------------------------------
aHighestHIGH_InTheLast20BARs = High[iHighest( _Symbol, // .self
PERIOD_CURRENT, // .self
MODE_HIGH, // HIGH
20, // Last 20 BARs
0 // from [0]
)
];
all. I've been banging my head up against this one for a while... I'm trying to put together an example of basically perlembed + perlcall and more or less "borrowed" it from evpsgi. The problem is that it grows about 1MB in size for every 1000 iterations. This isn't the greatest situation to be in when running in a long lived process (which is the use case that I'm working with).
As the title states, if I run with valgrind it reports that there are no leaks possible. I ran with --trace-malloc=yes and it appears that free is only ever called at the end in a big batch of calls. I understand that this may be perl's MO but it would be nice if it at least re-used the memory and didn't grow until the OS killed off the process.
The entry for sv_2mortal mentions something about the buffer being available to be "stolen" but I've peppered the code with calls to sv_2mortal but there was no change.
Without further ado, here is the code. Please forgive the cargo cultishness of it. Thanks in advance!
/*
*
* cc `perl -MExtUtils::Embed -e ccopts -e ldopts` -Wall -ggdb test_perl_2.c -o test_perl_2
*
* # test.psgi
* use strict;
* use warnings;
* my $app = sub {
* return [ 200, [ test => 1 ], [ sprintf( "%d: Hello!!! from %s\n", $$, __FILE__ ) ] ];
* };
*
*/
#include <stdio.h>
#include <EXTERN.h> /* from the Perl distribution */
#include <perl.h> /* from the Perl distribution */
static PerlInterpreter *perlinterp; /*** The Perl interpreter ***/
static SV *app;
void do_stuff( void );
SV * get_stuff( void );
SV * call_stuff( SV * );
EXTERN_C void xs_init( pTHX );
EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
EXTERN_C void xs_init( pTHX ) {
char *file = __FILE__;
dXSUB_SYS;
/* DynaLoader is a special case */
newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
}
int main( int argc, char **argv, char **env ) {
char code[ 1024 ];
char psgi[] = "test.psgi";
char *embedding[] = { "", "-e", "0" };
PERL_SYS_INIT3( &argc, &argv, &env );
perlinterp = perl_alloc();
PERL_SET_CONTEXT( perlinterp );
perl_construct( perlinterp );
perl_parse( perlinterp, xs_init, 3, embedding, (char **)NULL );
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
sprintf( code, "do '%s' or die $#", psgi );
app = eval_pv( code, TRUE ); /* croak_on_error */
do_stuff();
PL_perl_destruct_level = 1;
perl_destruct( perlinterp );
perl_free( perlinterp );
PERL_SYS_TERM();
return 0;
}
void do_stuff( void ) {
int body_lastindex, i, count;
AV *response_av, *body_av;
SV *stuff_sv, *response_sv, *status, *tmp_body_sv, *body_sv;
// count = 10000;
count = 10;
while( count-- ) {
ENTER;
SAVETMPS;
stuff_sv = get_stuff();
response_sv = call_stuff( stuff_sv );
if(
NULL == response_sv ||
! SvROK( response_sv ) ||
SvTYPE( SvRV( response_sv ) ) != SVt_PVAV
) {
printf( "NULL == response_sv\n" );
goto CLIENT_END;
}
response_av = (AV *)SvRV( response_sv );
status = *av_fetch( response_av, 0, 0 );
printf( "status = %ld\n", (long)SvIV( status ) );
body_av = (AV *)SvRV( *av_fetch( response_av, 2, 0 ) );
body_sv = newSV( 0 );
body_lastindex = av_len( body_av );
for( i = 0; i <= body_lastindex; i++ ) {
tmp_body_sv = (SV *)*av_fetch( body_av, i, 0 );
if( SvOK( tmp_body_sv ) ) {
sv_catsv( body_sv, tmp_body_sv );
}
}
printf( "body_sv = %s\n", SvPV_nolen( body_sv ) );
CLIENT_END:
FREETMPS;
LEAVE;
}
}
SV * get_stuff( void ) {
HV *stuff_hv;
// stuff_hv = (HV *)sv_2mortal((SV *)newHV());
stuff_hv = newHV();
if( NULL == hv_store( stuff_hv, "SCRIPT_NAME", strlen( "SCRIPT_NAME" ), newSVpv( "", 0 ), 0 ) ) {
croak( "hv_store( 'SCRIPT_NAME' )" );
}
if( NULL == hv_store( stuff_hv, "REQUEST_METHOD", strlen( "REQUEST_METHOD" ), newSVpv( "GET", 3 ), 0 ) ) {
croak( "hv_store( 'REQUEST_METHOD' )" );
}
if( NULL == hv_store( stuff_hv, "REQUEST_URI", strlen( "REQUEST_URI" ), newSVpv( "/abc?def", 8 ), 0 ) ) {
croak( "hv_store( 'REQUEST_URI' )" );
}
if( NULL == hv_store( stuff_hv, "PATH_INFO", strlen( "PATH_INFO" ), newSVpv( "/abc", 4 ), 0 ) ) {
croak( "hv_store( 'PATH_INFO' )" );
}
if( NULL == hv_store( stuff_hv, "QUERY_STRING", strlen( "QUERY_STRING" ), newSVpv( "def", 3 ), 0 ) ) {
croak( "hv_store( 'QUERY_STRING' )" );
}
return newRV_inc( (SV *)stuff_hv );
}
SV * call_stuff( SV *stuff_sv ) {
SV *response_sv;
int count;
// printf( "REQUEST_URI = %s\n", SvPV_nolen( *hv_fetch( (HV *)SvRV( stuff_sv ), "REQUEST_URI", strlen( "REQUEST_URI" ), 0 ) ) );
dSP;
ENTER;
SAVETMPS;
PUSHMARK( SP );
XPUSHs( stuff_sv ); // stuff_sv is not mortal.
PUTBACK;
count = call_sv( app, G_EVAL | G_SCALAR | G_KEEPERR );
SPAGAIN;
if( SvTRUE( ERRSV ) ) {
response_sv = NULL;
fprintf( stderr, "FATAL: %s", SvPV_nolen( ERRSV ) );
/* CLEAR_ERRSV() is only available 5.8.9 or later */
if( SvMAGICAL( ERRSV ) ) {
mg_free( ERRSV );
mg_clear( ERRSV );
}
sv_setpvn_mg( ERRSV, "", 0 );
POPs; // causes "warning: value computed is not used"
}
else if( count > 0 ) {
response_sv = POPs; // is this mortal?
SvREFCNT_inc( response_sv );
} else {
response_sv = NULL;
}
PUTBACK;
FREETMPS;
LEAVE;
return response_sv;
}
You don't free anything! You get a scalar from Perl and you create two yourself, but none of them are getting freed.
Leak 1
You have:
HV *stuff_hv;
stuff_hv = newHV();
return newRV_inc( (SV *)stuff_hv );
Two problems with that:
You're creating an HV with a refcnt of 2.
Change newRV_inc to newRV_noinc.
You never free it (or return it from a XS func as a mortal).
Use SvREFCNT_dec( stuff_sv ) when you're done with it, perhaps after the call to call_stuff.
Leak 2
You have:
body_sv = newSV( 0 );
Again, there's no corresponding freeing of that scalar. You need
SvREFCNT_dec( body_sv );
after the printf.
Leak 3
You have:
response_sv = POPs; // is this mortal?
SvREFCNT_inc( response_sv );
It doesn't really matter if it's mortal or not. You need to claim ownership of it in case it is, so the inc is appropriate. But you must later release it when you're done with it.
SvREFCNT_dec( response_sv );