<commit_before>#include "main.h"

#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <stropts.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
#include <errno.h>

#include <security/pam_appl.h>

#define _XOPEN_SOURCE 500
#include <termios.h>

#define WRITE 1
#define READ 0

#define LAST_TTY 63
#define FIRST_TTY 10 -1

typedef struct {
    struct {
        int fd[2];
    } com;
    struct {
        SpawnServiceJobCb cb;
        void *data;
    } job;
    const char *service;
    const char *usr;
    const char *pw;
} Spawn_Try;

static SpawnDoneCb _done;
static void *_done_data;
static Spawn_Try *spawn_try = NULL;

static int tty_counter = FIRST_TTY;

static int child_run(void);
static int open_tty(char *tty, const char *usr);
static int pam_auth(char ***env, int tty);

static void
_spawn_try_free(int success)
{
    close(spawn_try->com.fd[READ]);
    close(spawn_try->com.fd[WRITE]);

    free(spawn_try);
    spawn_try = NULL;

    if (success > -1) {
        if (_done) _done(_done_data, success);
    }
}
static void
_process_message(Spawny__Spawn__Message *msg)
{
    switch(msg->type) {
        case SPAWNY__SPAWN__MESSAGE__TYPE__CONNECT:
            //FIXME kill timer for none come up sessions
        break;
        case SPAWNY__SPAWN__MESSAGE__TYPE__SETUP_DONE:
            //we need to activate the passed session
            printf("Activating session\n");
            session_activate(msg->session);
        break;
        case SPAWNY__SPAWN__MESSAGE__TYPE__SESSION_ACTIVE:
            //the session is up, and will die now
            printf("Session is up\n");
            manager_unregister_fd(spawn_try->com.fd[READ]);
            _spawn_try_free(1);
        break;
        case SPAWNY__SPAWN__MESSAGE__TYPE__ERROR_EXIT:
            //print the error somewhere
            printf("Session exit with %s\n", msg->exit);
            manager_unregister_fd(spawn_try->com.fd[READ]);
            _spawn_try_free(0);
        break;
        default:
        break;
    }
}

static void
_child_data(void *data, int fd)
{
   uint8_t buf[2064];
   int len = 0;
   Spawny__Spawn__Message *msg = NULL;

   len = read(fd, buf, sizeof(buf));

   if (len == 0) {
     //we are likly at the end
     manager_unregister_fd(fd);
     return;
   }

   msg = spawny__spawn__message__unpack(NULL, len, buf);

   if (!msg) {
     printf("Got a wrong message.\n");
     return;
   }

   _process_message(msg);

   spawny__spawn__message__free_unpacked(msg, NULL);
}

int
spawnservice_init(SpawnDoneCb done, void *data) {
    _done_data = data;
    _done = done;

    return 1;
}

int
spawnservice_spawn(SpawnServiceJobCb job, const char *service,
    const char *usr, const char *pw, void *data) {

    if (spawn_try) return 0;

    spawn_try = calloc(1, sizeof(Spawn_Try));

    if (pipe(spawn_try->com.fd) < 0) {
        perror("Failed to open pipe");
        free(spawn_try);
        spawn_try = NULL;
        return 0;
    }

    spawn_try->job.cb = job;
    spawn_try->job.data = data;

    spawn_try->pw = pw;
    spawn_try->usr = usr;
    spawn_try->service = service;

    if (!child_run()) {
        _spawn_try_free(-1);
        return 0;
    }

    return 1;
}

void
spawnservice_shutdown(void) {

}

//=====================================================
//BE AWARE
//the following stuff is 99% into a seperated process,
//=====================================================

static char *
available_tty(void) {
    char buf[PATH_MAX];

    if (tty_counter > LAST_TTY) return NULL;
    tty_counter ++;


    snprintf(buf, sizeof(buf), "/dev/tty%d", tty_counter);

    return strdup(buf);
}<commit_msg>spawnservice: Check if tty is used before using it<commit_after>#include "main.h"

#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <stropts.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
#include <errno.h>

#include <security/pam_appl.h>

#define _XOPEN_SOURCE 500
#include <termios.h>

#define WRITE 1
#define READ 0

#define LAST_TTY 63
#define FIRST_TTY 10 -1

typedef struct {
    struct {
        int fd[2];
    } com;
    struct {
        SpawnServiceJobCb cb;
        void *data;
    } job;
    const char *service;
    const char *usr;
    const char *pw;
} Spawn_Try;

static SpawnDoneCb _done;
static void *_done_data;
static Spawn_Try *spawn_try = NULL;

static int tty_counter = FIRST_TTY;

static int child_run(void);
static int open_tty(char *tty, const char *usr);
static int pam_auth(char ***env, int tty);

static void
_spawn_try_free(int success)
{
    close(spawn_try->com.fd[READ]);
    close(spawn_try->com.fd[WRITE]);

    free(spawn_try);
    spawn_try = NULL;

    if (success > -1) {
        if (_done) _done(_done_data, success);
    }
}
static void
_process_message(Spawny__Spawn__Message *msg)
{
    switch(msg->type) {
        case SPAWNY__SPAWN__MESSAGE__TYPE__CONNECT:
            //FIXME kill timer for none come up sessions
        break;
        case SPAWNY__SPAWN__MESSAGE__TYPE__SETUP_DONE:
            //we need to activate the passed session
            printf("Activating session\n");
            session_activate(msg->session);
        break;
        case SPAWNY__SPAWN__MESSAGE__TYPE__SESSION_ACTIVE:
            //the session is up, and will die now
            printf("Session is up\n");
            manager_unregister_fd(spawn_try->com.fd[READ]);
            _spawn_try_free(1);
        break;
        case SPAWNY__SPAWN__MESSAGE__TYPE__ERROR_EXIT:
            //print the error somewhere
            printf("Session exit with %s\n", msg->exit);
            manager_unregister_fd(spawn_try->com.fd[READ]);
            _spawn_try_free(0);
        break;
        default:
        break;
    }
}

static void
_child_data(void *data, int fd)
{
   uint8_t buf[2064];
   int len = 0;
   Spawny__Spawn__Message *msg = NULL;

   len = read(fd, buf, sizeof(buf));

   if (len == 0) {
     //we are likly at the end
     manager_unregister_fd(fd);
     return;
   }

   msg = spawny__spawn__message__unpack(NULL, len, buf);

   if (!msg) {
     printf("Got a wrong message.\n");
     return;
   }

   _process_message(msg);

   spawny__spawn__message__free_unpacked(msg, NULL);
}

int
spawnservice_init(SpawnDoneCb done, void *data) {
    _done_data = data;
    _done = done;

    return 1;
}

int
spawnservice_spawn(SpawnServiceJobCb job, const char *service,
    const char *usr, const char *pw, void *data) {

    if (spawn_try) return 0;

    spawn_try = calloc(1, sizeof(Spawn_Try));

    if (pipe(spawn_try->com.fd) < 0) {
        perror("Failed to open pipe");
        free(spawn_try);
        spawn_try = NULL;
        return 0;
    }

    spawn_try->job.cb = job;
    spawn_try->job.data = data;

    spawn_try->pw = pw;
    spawn_try->usr = usr;
    spawn_try->service = service;

    if (!child_run()) {
        _spawn_try_free(-1);
        return 0;
    }

    return 1;
}

void
spawnservice_shutdown(void) {

}

//=====================================================
//BE AWARE
//the following stuff is 99% into a seperated process,
//=====================================================

static char
_tty_used(char *buf) {
    unsigned int number;
    char **sessions;

    session_enumerate(&sessions, &number);
    for(int i = 0; i < number; i++){
        char *tty;

        session_details(sessions[i], NULL, NULL, NULL, &tty);

        if (!strcmp(tty, buf))
            return 1;
    }
    return 0;
}

static char *
available_tty(void) {
    char buf[PATH_MAX];

    do {
        if (tty_counter > LAST_TTY) return NULL;
        tty_counter ++;

        snprintf(buf, sizeof(buf), "/dev/tty%d", tty_counter);
    } while(!_tty_used(buf));

    return strdup(buf);
}
{'fraction_non_alphanumeric': 0.14241960183767227, 'fraction_numerical': 0.008295048494129658, 'mean_word_length': 2.77504816955684, 'pattern_counts': {'":': 0, '<': 32, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3289153', 'n_tokens_mistral': 2844, 'n_tokens_neox': 2775, 'n_words': 655}