Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  sesexec.c

  Sprache: C
 

/**
 * xrdp: A Remote Desktop Protocol server.
 *
 * Copyright (C) Matt Burt 2023
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


/**
 *
 * @file sesexec.c
 * @brief Main program file for session executive process
 * @author Matt Burt
 *
 */


#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif

#include <ctype.h>
#include <stdarg.h>

#include "arch.h"
#include "eicp.h"
#include "eicp_server.h"
#include "ercp.h"
#include "ercp_server.h"
#include "login_info.h"
#include "sesexec.h"
#include "sesman_config.h"
#include "log.h"
#include "os_calls.h"
#include "session.h"
#include "string_calls.h"
#include "trans.h"
#include "xrdp_sockets.h"

struct startup_params
{
    const char *sesman_ini;
};

/*
 * Program-scope globals
 */

struct config_sesman *g_cfg;
unsigned char g_fixedkey[8] = { 238210763578887 };
struct login_info *g_login_info;
struct session_data *g_session_data;

tintptr g_term_event = 0;
tintptr g_sigchld_event = 0;
pid_t g_pid;

/*
 * Module-scope globals
 */

static struct trans *g_ecp_trans;
static int g_terminate_loop = 0;
static int g_terminate_status = 0;

/*****************************************************************************/
/**
 * Command line argument parser
 * @param[in] argc number of command line arguments
 * @param[in] argv pointer array of commandline arguments
 * @param[out] startup_params Returned startup parameters
 * @return 0 on success
 */

static int
process_params(int argc, char **argv,
               struct startup_params *startup_params)
{
    int index;
    const char *option;
    const char *value;

    startup_params->sesman_ini = DEFAULT_SESMAN_INI;

    index = 1;

    while (index < argc)
    {
        option = argv[index];

        if (index + 1 < argc)
        {
            value = argv[index + 1];
        }
        else
        {
            value = "";
        }

        if (g_strcmp(option, "-c") == 0)
        {
            index++;
            startup_params->sesman_ini = value;
        }
        else /* unknown option */
        {
            return index;
        }

        index++;
    }

    return 0;
}

/******************************************************************************/
#if 0
static int
sesexec_scp_data_in(struct trans *self)
{
    int rv;
    int available;

    rv = scp_msg_in_check_available(self, &available);

    if (rv == 0 && available)
    {
        struct sesman_con *sc = (struct sesman_con *)self->callback_data;
        //if ((rv = scp_process(sc)) != 0)
        {
            LOG(LOG_LEVEL_ERROR, "%s: scp_process failed", __func__);
        }
        scp_msg_in_reset(self);
    }

    return rv;
}
#endif

/******************************************************************************/
static int
sesexec_eicp_data_in(struct trans *self)
{
    int rv;
    int available;

    rv = eicp_msg_in_check_available(self, &available);

    if (rv == 0 && available)
    {
        if ((rv = eicp_server(self)) != 0)
        {
            LOG(LOG_LEVEL_ERROR, "%s: eicp_server failed", __func__);
        }
        eicp_msg_in_reset(self);
    }

    return rv;
}

/******************************************************************************/
int
sesexec_ercp_data_in(struct trans *self)
{
    int rv;
    int available;

    rv = ercp_msg_in_check_available(self, &available);

    if (rv == 0 && available)
    {
        if ((rv = ercp_server(self)) != 0)
        {
            LOG(LOG_LEVEL_ERROR, "%s: ercp_server failed", __func__);
        }
        ercp_msg_in_reset(self);
    }

    return rv;
}

/******************************************************************************/
/**
 * Informs the main loop a termination signal has been received
 */

static void
set_term_event(int sig)
{
    /* Don't try to use a wait obj in a child process */
    if (g_getpid() == g_pid)
    {
        g_set_wait_obj(g_term_event);
    }
}

/*****************************************************************************/
/* No-op signal handler.
 */

static void
sig_no_op(int sig)
{
    /* no-op */
}

/******************************************************************************/
/**
 * Informs the main loop a child exiting signal has been received
 */

static void
set_sigchld_event(int sig)
{
    /* Don't try to use a wait obj in a child process */
    if (g_getpid() == g_pid)
    {
        g_set_wait_obj(g_sigchld_event);
    }
}

/******************************************************************************/
int
sesexec_is_term(void)
{
    return g_terminate_loop || g_is_wait_obj_set(g_term_event);
}

/******************************************************************************/
void
sesexec_terminate_main_loop(int status)
{
    g_terminate_loop = 1;
    g_terminate_status = status;
}

/******************************************************************************/
static void
process_sigchld_event(void)
{
    struct proc_exit_status e;
    int pid;

    // Check for any finished children
    while ((pid = g_waitchild(&e)) > 0)
    {
        session_process_child_exit(g_session_data, pid, &e);
    }
}

/******************************************************************************/
/**
 *
 * @brief Starts sesexec main loop
 *
 */

static int
sesexec_main_loop(void)
{
    int error = 0;
    int robjs_count;
    intptr_t robjs[32];

    g_terminate_loop = 0;
    g_terminate_status = 0;
    g_login_info = NULL;

    while (!g_terminate_loop)
    {
        robjs_count = 0;
        robjs[robjs_count++] = g_term_event;
        robjs[robjs_count++] = g_sigchld_event;

        error = trans_get_wait_objs(g_ecp_trans, robjs, &robjs_count);
        if (error != 0)
        {
            LOG(LOG_LEVEL_ERROR, "sesexec_main_loop: "
                "trans_get_wait_objs(ECP) failed");
            sesexec_terminate_main_loop(error);
            continue;
        }

        if (g_obj_wait(robjs, robjs_count, NULL, 0, -1) != 0)
        {
            /* should not get here */
            LOG(LOG_LEVEL_WARNING, "sesexec_main_loop: "
                "Unexpected error from g_obj_wait()");
            g_sleep(100);
            continue;
        }

        if (g_is_wait_obj_set(g_term_event)) /* term */
        {
            g_reset_wait_obj(g_term_event);
            if (session_active(g_session_data))
            {
                // Ask the active session to terminate
                LOG(LOG_LEVEL_INFO, "sesexec_main_loop: "
                    "sesexec asked to terminate. "
                    "Terminating active session");
                session_send_term(g_session_data);
            }
            else
            {
                // Terminate immediately
                LOG(LOG_LEVEL_INFO, "sesexec_main_loop: "
                    "sesexec asked to terminate. "
                    "No session is active");
                sesexec_terminate_main_loop(0);
                continue;
            }
        }

        if (g_is_wait_obj_set(g_sigchld_event)) /* SIGCHLD */
        {
            g_reset_wait_obj(g_sigchld_event);

            // See whether the session goes from active to inactive
            // after processing SIGCHLD
            int session_was_active = session_active(g_session_data);
            process_sigchld_event();
            if (session_was_active && !session_active(g_session_data))
            {
                // We've finished the session. Tell sesman and
                // finish up.
                (void)ercp_send_session_finished_event(g_ecp_trans);

                session_data_free(g_session_data);
                g_session_data = NULL;
                sesexec_terminate_main_loop(0);
                continue;
            }
        }

        error = trans_check_wait_objs(g_ecp_trans);
        if (error != 0)
        {
            LOG(LOG_LEVEL_ERROR, "sesexec_main_loop: "
                "trans_check_wait_objs failed for ECP transport");
            sesexec_terminate_main_loop(error);
            continue;
        }
    }

    login_info_free(g_login_info);

    return g_terminate_status;
}

/******************************************************************************/
static int start_logging(const char *sesman_ini)
{
    char text[256];
    int rv = 1;
    if (!g_file_exist(sesman_ini))
    {
        g_printf("Config file %s does not exist\n", sesman_ini);
    }
    else
    {
        enum logReturns log_error;
        log_error = log_start(sesman_ini, "xrdp-sesexec"0);

        if (log_error != LOG_STARTUP_OK)
        {
            switch (log_error)
            {
                case LOG_ERROR_MALLOC:
                    g_writeln("error on malloc. cannot start logging. quitting.");
                    break;
                case LOG_ERROR_FILE_OPEN:
                    g_writeln("error opening log file [%s]. quitting.",
                              getLogFile(text, sizeof(text) - 1));
                    break;
                default:
                    // Assume sufficient messages have already been generated
                    break;
            }
        }
        else
        {
            rv = 0;
        }
    }

    return rv;
}

/******************************************************************************/
static int
get_eicp_fd(char errstr[], unsigned int errstr_size)
{
    const char *s =  g_getenv("EICP_FD");
    const char *p;
    int fd;

    errstr[0] = '\0';

    if (s == NULL || s[0] == '\0')
    {
        g_snprintf(errstr, errstr_size,
                   "Can't read EICP_FD environment variable");
        return -1;
    }

    for (p = s ; isdigit(*p) ; ++p)
    {
        ;
    }

    if (*p != '\0')
    {
        g_snprintf(errstr, errstr_size, "EICP_FD has non-digit char '%c'", *p);
        return -1;
    }

    if ((p - s) > 4)
    {
        g_snprintf(errstr, errstr_size, "EICP_FD has too many digits");
        return -1;
    }

    fd = g_atoi(s);
    if (!g_file_is_open(fd))
    {
        g_snprintf(errstr, errstr_size, "EICP_FD %d is not open", fd);
        return -1;
    }

    return fd;
}

/******************************************************************************/
int
main(int argc, char **argv)
{
    int error = 1;
    struct startup_params startup_params = {0};
    int errored_argc;
    int eicp_fd;
    char eicp_errstr[128];
    /*
     * Check the EICP transport file descriptor is provided and open
     * before opening any log files, config files, etc. We then open
     * log files, and log errors at that point */

    eicp_fd = get_eicp_fd(eicp_errstr, sizeof(eicp_errstr));

    g_init("xrdp-sesexec");

    //g_sleep(15 * 1000);
    errored_argc = process_params(argc, argv, &startup_params);
    if (errored_argc > 0)
    {
        g_writeln("Unknown option: %s", argv[errored_argc]);
    }
    /* starting logging subsystem
     *
     * For historic reasons, we share a log file with sesman */

    else if (start_logging(startup_params.sesman_ini) == 0)
    {
        /* reading config
         *
         * For historic reasons, we share a config with sesman */

        if ((g_cfg = config_read(startup_params.sesman_ini)) == NULL)
        {
            LOG(LOG_LEVEL_ALWAYS, "error reading config %s: %s",
                startup_params.sesman_ini, g_get_strerror());
        }
        else if (eicp_fd < 0)
        {
            LOG(LOG_LEVEL_ERROR, "%s", eicp_errstr);
        }
        else
        {
            char text[128];

            g_pid = g_getpid();

            /* signal handling */
            g_snprintf(text, sizeof(text), "xrdp_sesexec_%8.8x_main_term",
                       g_pid);
            g_term_event = g_create_wait_obj(text);
            g_snprintf(text, sizeof(text), "xrdp_sesexec_%8.8x_sigchld",
                       g_pid);
            g_sigchld_event = g_create_wait_obj(text);

            // No need to terminate on SIGINT for sesexec. This can
            // also make it hard to debug sessions.
            //g_signal_user_interrupt(set_term_event);
            g_signal_terminate(set_term_event); /* SIGTERM */
            g_signal_pipe(sig_no_op);          /* SIGPIPE */
            g_signal_child_stop(set_sigchld_event);

            /* Set up an EICP process handler
             * Errors are logged by this call if necessary */

            g_ecp_trans = eicp_init_trans_from_fd(eicp_fd,
                                                  TRANS_TYPE_SERVER,
                                                  sesexec_is_term);
            if (g_ecp_trans != NULL)
            {
                g_ecp_trans->trans_data_in = sesexec_eicp_data_in;
                g_ecp_trans->callback_data = NULL;

                /* start program main loop */
                LOG(LOG_LEVEL_INFO, "starting xrdp-sesexec with pid %d", g_pid);
                error = sesexec_main_loop();
                trans_delete(g_ecp_trans);
            }

            g_delete_wait_obj(g_term_event);
        }
        config_free(g_cfg);
        log_end();
    }

    g_deinit();
    return error;
}

Messung V0.5 in Prozent
C=94 H=78 G=86

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-07-10) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik