winix/winixd/core/run.h

200 lines
5.0 KiB
C
Raw Normal View History

/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2011-2018, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef headerfile_winix_core_run
#define headerfile_winix_core_run
#include <string>
#include <cstdio>
#include <unistd.h>
#include "winixbase.h"
namespace Winix
{
/*
how many parameters and environment variables can be passed to a program
*/
#define WINIX_RUN_MAX_PARAMETERS 30
/*
objects of this class allows you to run an external program
when you call Go() then:
1. winix creates pipes for communicating with a child process
2. then winix fork()
3. the child process execve() the specified command
4. winix (parent) sends 'in' to the standard input of the child process
5. after sending it closes the descriptor so the child sees it as end-of-file
6. now winix reads what the child sends to standard output (until EOF)
7. winix waitpid() for the child
8. Go() returns
*/
class Run : public WinixBase
{
public:
Run();
/*
clearing parameters, environment variables and the command
(and clearing LastStatus and LastResult)
so you can call another different program now
*/
void Clear();
/*
setting parameters
each parameter should be passed in different call to Par() method
sample:
if you want to call from your shell:
$ myprog -a -b -f "test file"
you should call Par() in this way:
Par("-a");
Par("-b");
Par("test file"); // apostrophes are not needed here
arguments passed to Par() should not be changed afterwards, this method does not copy them anywhere
it uses only the pointer
*/
void Par(const char * p);
void Par(const std::string & p);
/*
setting environment variables
one variable per one Env() call
arguments passed to Env() should not be changed afterwards, this method does not copy them anywhere
it uses only the pointer
*/
void Env(const char * e);
void Env(const std::string & e);
/*
full path to command you want to execute
arguments passed to Cmd() should not be changed afterwards, this method does not copy them anywhere
it uses only the pointer
*/
void Cmd(const char * c);
void Cmd(const std::string & c);
/*
executing the command
you should call Par(), Env() and Cmd() beforehand
*/
int Go(const char * in, size_t inlen, std::string & out);
int Go(const char * in, std::string & out);
int Go(const char * in, size_t inlen);
int Go(const char * in);
int Go(const std::string in, std::string & out);
int Go(const std::string in);
int Go(std::string & out);
int Go();
/*
last status:
0 - ok (program was successfully called)
1 - pipe failed
2 - fork failed
3 - write failed
4 - read failed
5 - child process has done something wrong (caught a signal etc.)
6 - waitpid failed
7 - the command is not set (call Cmd method first)
*/
int LastStatus();
/*
the code which the command returned (usually "0" means no errors found)
if LastStatus is different from zero then LastReturn always returns 255
(so you don't have to check LastStatus() first)
*/
int LastReturn();
private:
int Go(const char * in, size_t inlen, std::string * out);
void SetName();
void CheckStatus();
void WriteRead(const char * in, size_t inlen, std::string * out);
bool CreatePipes();
bool Fork();
void ChildThrow();
void Child();
void Write(const char * in, size_t inlen);
void Read(std::string & out);
int last_status;
// the return code returned by a program (if last_status==0)
// if last_status!=0 then last_return is 255
int last_return;
int desin[2];
int desout[2];
char * par[WINIX_RUN_MAX_PARAMETERS + 2];
char * env[WINIX_RUN_MAX_PARAMETERS + 1];
const char * command;
size_t parlen;
size_t envlen;
pid_t childpid;
};
} // namespace Winix
#endif