aboutsummaryrefslogtreecommitdiff
path: root/src/stable/process.h
blob: 4a3be3cce601447a577d4856247408c45cf7e6f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*
 * Copyright (C) 2007-2023 Xagasoft, All rights reserved.
 *
 * This file is part of the libbu++ library and is released under the
 * terms of the license contained in the file LICENSE.
 */

#ifndef BU_PROCESS_H
#define BU_PROCESS_H

#include <stdint.h>
#include <sys/types.h>

#include "bu/stream.h"
#include "bu/string.h"

namespace Bu
{
    /**
     * Runs a program and attaches streams to it's stdin, stdout, and stderr.
     * Reading from a Bu::Process will read from the program's standard output,
     * writing to a Bu::Process will write to the program's standard input.
     */
    class Process : public Bu::Stream
    {
    public:
        enum Flags
        {
            None    =   0x00,
            StdOut  =   0x01,
            StdErr  =   0x02,
            Both    =   0x03
        };

    public:
        class Options
        {
        public:
            enum OptFlags
            {
                None    = 0x00,
                SetUid  = 0x01,
                SetGid  = 0x02,
            };

            Options() : eFlags( None ) {}

            int eFlags;
            int iUid;
            int iGid;
        };

        Process( Flags eFlags, const char *sName, char *const argv[] );
        Process( Flags eFlags, const char *sName, const char *argv, ...);
        Process( Flags eFlags, const Options &opt, const char *sName, char *const argv[] );
        Process( Flags eFlags, const Options &opt, const char *sName, const char *argv, ...);
        virtual ~Process();

        /**
         * Waits until the process exits.  This blocks the caller until the
         * child process terminates.
         */
        void wait();

        virtual void close();
        virtual void closeStdIn();
        virtual void closeStdOut();
        virtual Bu::size read( void *pBuf, Bu::size nBytes );
        virtual Bu::size readErr( void *pBuf, Bu::size nBytes );
        virtual Bu::size write( const void *pBuf, Bu::size nBytes );
        using Stream::write;

        virtual Bu::size tell();
        virtual void seek( Bu::size offset );
        virtual void setPos( Bu::size pos );
        virtual void setPosEnd( Bu::size pos );
        virtual bool isEos();
        virtual bool isOpen();

        virtual void flush();

        virtual bool canRead();
        virtual bool canWrite();

        virtual bool isReadable();
        virtual bool isWritable();
        virtual bool isSeekable();

        virtual bool isBlocking();
        virtual void setBlocking( bool bBlocking=true );

        virtual void setSize( Bu::size iSize );

        virtual size getBlockSize() const;
        virtual size getSize() const;
        virtual Bu::String getLocation() const;

        void select( bool &bStdOut, bool &bStdErr );

        bool isRunning();
        void ignoreStdErr();

        /**
         * Returns the pid of the child process, or zero if there is no
         * currently running child.  Note that a read operation must be
         * performed in order to discover that the child has ended.
         */
        pid_t getPid();

        /**
         * Returns true if the child exited normally (by calling exit or
         * returning from main).
         */
        bool childExited();

        /**
         * Returns the 8 bit integer value returned from the child program if
         * childExited returned true.
         */
        int childExitStatus();

        /**
         * Returns true if the child exited because of a signal.
         */
        bool childSignaled();

        /**
         * Returns the signal ID if the childSignaled return true.
         */
        int childSignal();

        /**
         * Returns true if the child left a core dump behind when it exited.
         */
        bool childCoreDumped();

    private:
        class ProcData
        {
        public:
            ProcData();
#ifdef WIN32
            void *hStdIn;
            void *hStdOut;
            void *hStdErr;
            void *hProcess;
#else
            int iStdIn;
            int iStdOut;
            int iStdErr;
            pid_t iPid;
#endif
        };
        ProcData pd;
        int iProcStatus;
        bool bBlocking;
        bool bStdOutEos;
        bool bStdErrEos;

        void gexec( Flags eFlags, const char *sName, char *const argv[] );
        void checkClose();
        Options opt;
    };
}

#endif