~ubuntu-branches/ubuntu/trusty/miwm/trusty

« back to all changes in this revision

Viewing changes to EShellProcess.cc

  • Committer: Bazaar Package Importer
  • Author(s): Jari Aalto
  • Date: 2010-01-04 15:25:34 UTC
  • Revision ID: james.westby@ubuntu.com-20100104152534-l3fdvt162le460cv
Tags: upstream-1.1
ImportĀ upstreamĀ versionĀ 1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdio.h> // popen()
 
2
#include <stdlib.h> // system()
 
3
#include <sys/types.h> // pid_t
 
4
#include <sys/wait.h> // pid_t
 
5
#include <unistd.h> // fork()
 
6
 
 
7
#include "EShellProcess.h"
 
8
#include "EStringList.h"
 
9
#include <signal.h> // signal(), sighandler_t
 
10
#include <setjmp.h> // longjmp()
 
11
 
 
12
using std::string;
 
13
using std::endl;
 
14
 
 
15
sigjmp_buf EShellProcess_ctrl_c_jmp_buffer;
 
16
 
 
17
void EShellProcess_SIGINT(int)
 
18
{
 
19
        std::cout << "^C" << std::endl; // this really shouldn't be here, but i find it useful.
 
20
        ::siglongjmp( EShellProcess_ctrl_c_jmp_buffer, 1 );
 
21
}
 
22
 
 
23
int
 
24
EShellProcess::system( const std::string &cmdline, std::ostream & os  )
 
25
{
 
26
        return ::system( cmdline.c_str() ) / 256; // i don't like this /256. it's against the docs, but the return values aren't what the docs say :/
 
27
}
 
28
 
 
29
int
 
30
EShellProcess::fork( const std::string &cmdline, std::ostream & os  )
 
31
{ // my very first fork()/exec()
 
32
        pid_t pid;
 
33
        EStringList tokens = EStringList::tokenize( cmdline );
 
34
                
 
35
        pid = ::fork();
 
36
        if( pid == -1 )
 
37
        {
 
38
                os << "EShellProcess::fork("<<cmdline<<"): error fork()ing." << endl;
 
39
                return 1;
 
40
        }
 
41
        if( pid > 0 ) return 0; // parent, go away.
 
42
        // child...
 
43
 
 
44
        // i hate to do this array stuff, but i see no other
 
45
        // way around it without finding a template class for
 
46
        // dynamic arrays, and i'm not up for that right now...
 
47
        static const int maxargs = 100;
 
48
        char * args[maxargs];
 
49
        int tcount = tokens.count();
 
50
        int i = 0;
 
51
        string tok;
 
52
        string filearg;
 
53
        for( ; i < tcount; i++ )
 
54
        {
 
55
                tok = tokens.shift();
 
56
                if( i == 0 ) filearg = tok;
 
57
                if( tok.empty() ) continue;
 
58
                //os << "adding token ["<<tok<<"]"<<endl;
 
59
                args[i] = const_cast<char *>( tok.c_str() );
 
60
                // this ^^^^^^^^^^^ const_cast is theoretically okay
 
61
                // because we're not gonna de-allocate the
 
62
                // array and this process will never pass
 
63
                // control back to anyone else, so tokens
 
64
                // shouldn't be unduly molested behind our
 
65
                // back. i won't swear that it's safe, though :/.
 
66
        }
 
67
        if( i == maxargs )
 
68
        {
 
69
                os << __FILE__<<":"<<__LINE__<<": EShellProcess::fork(): you've met or overstepped the\n"
 
70
                   << "hard-coded limit of "<< maxargs<<" arguments.\n"
 
71
                   <<"Please contact the maintainer of this code with an example of how you're using it (stephan@wanderinghorse.net), "
 
72
                   << "or fix this bug and send him your fix :)."
 
73
                   << endl;
 
74
        }
 
75
        for( ; i < maxargs; i++ )
 
76
        {
 
77
                args[i] = NULL;
 
78
        }
 
79
        execvp( filearg.c_str(), args );
 
80
        _exit(0);
 
81
        return 0;
 
82
}
 
83
 
 
84
int
 
85
EShellProcess::pipe( const std::string &cmdline, std::ostream & os )
 
86
{
 
87
        if( cmdline.empty() )
 
88
        {
 
89
                os << "EShellProcess::pipe(): cannot run an empty command :(";
 
90
                return 1;
 
91
        }
 
92
        FILE *fp = 0;
 
93
        fp = ::popen( cmdline.c_str(), "r" );
 
94
        if( ! fp )
 
95
        {
 
96
                os << "EShellProcess::pipe(): popen("<<cmdline<<") failed :(" << std::endl;
 
97
                return 1;
 
98
        }
 
99
        ::fwrite( cmdline.c_str(), sizeof( char ), cmdline.size(), fp );
 
100
#define RESTORE_SIGNALS ::signal( SIGINT, old_sighandler )
 
101
        typedef void (*signalfunc)(int);
 
102
        signalfunc old_sighandler = ::signal( SIGINT, EShellProcess_SIGINT );
 
103
        int getcchar;
 
104
        if( 0 == ::sigsetjmp( EShellProcess_ctrl_c_jmp_buffer, 1 ) )
 
105
        {
 
106
                while( ! ::feof( fp ) )
 
107
                {
 
108
                        getcchar = ::getc( fp );
 
109
                        if( getcchar == EOF ) break;
 
110
                        os <<(unsigned char) getcchar;
 
111
                        if( ! os && (os != std::cerr) )
 
112
                        {
 
113
                                RESTORE_SIGNALS;
 
114
                                std::cerr << "EShellProcess::pipe(): error in output stream!" << std::endl;
 
115
                                return 1;
 
116
                        }
 
117
                }
 
118
        }
 
119
        RESTORE_SIGNALS;
 
120
        int ret = ::pclose( fp );
 
121
        return (ret == 0) ? 0 : (ret / 256);
 
122
}
 
123
 
 
124