Blame packet/command_unix.c

Packit b802ec
/*
Packit b802ec
    mtr  --  a network diagnostic tool
Packit b802ec
    Copyright (C) 2016  Matt Kimball
Packit b802ec
Packit b802ec
    This program is free software; you can redistribute it and/or modify
Packit b802ec
    it under the terms of the GNU General Public License version 2 as
Packit b802ec
    published by the Free Software Foundation.
Packit b802ec
Packit b802ec
    This program is distributed in the hope that it will be useful,
Packit b802ec
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit b802ec
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit b802ec
    GNU General Public License for more details.
Packit b802ec
Packit b802ec
    You should have received a copy of the GNU General Public License
Packit b802ec
    along with this program; if not, write to the Free Software
Packit b802ec
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Packit b802ec
*/
Packit b802ec
Packit b802ec
#include "command.h"
Packit b802ec
Packit b802ec
#include <errno.h>
Packit b802ec
#include <fcntl.h>
Packit b802ec
#include <string.h>
Packit b802ec
#include <stdio.h>
Packit b802ec
#include <stdlib.h>
Packit b802ec
#include <unistd.h>
Packit b802ec
Packit b802ec
/*
Packit b802ec
    Initialize the command buffer and put the command stream in
Packit b802ec
    non-blocking mode.
Packit b802ec
*/
Packit b802ec
void init_command_buffer(
Packit b802ec
    struct command_buffer_t *command_buffer,
Packit b802ec
    int command_stream)
Packit b802ec
{
Packit b802ec
    int flags;
Packit b802ec
Packit b802ec
    memset(command_buffer, 0, sizeof(struct command_buffer_t));
Packit b802ec
    command_buffer->command_stream = command_stream;
Packit b802ec
Packit b802ec
    /*  Get the current command stream flags  */
Packit b802ec
    flags = fcntl(command_stream, F_GETFL, 0);
Packit b802ec
    if (flags == -1) {
Packit b802ec
        perror("Unexpected command stream error");
Packit b802ec
        exit(EXIT_FAILURE);
Packit b802ec
    }
Packit b802ec
Packit b802ec
    /*  Set the O_NONBLOCK bit  */
Packit b802ec
    if (fcntl(command_stream, F_SETFL, flags | O_NONBLOCK)) {
Packit b802ec
        perror("Unexpected command stream error");
Packit b802ec
        exit(EXIT_FAILURE);
Packit b802ec
    }
Packit b802ec
}
Packit b802ec
Packit b802ec
/*  Read currently available data from the command stream  */
Packit b802ec
int read_commands(
Packit b802ec
    struct command_buffer_t *buffer)
Packit b802ec
{
Packit b802ec
    int space_remaining =
Packit b802ec
        COMMAND_BUFFER_SIZE - buffer->incoming_read_position - 1;
Packit b802ec
    char *read_position =
Packit b802ec
        &buffer->incoming_buffer[buffer->incoming_read_position];
Packit b802ec
    int read_count;
Packit b802ec
    int command_stream = buffer->command_stream;
Packit b802ec
Packit b802ec
    read_count = read(command_stream, read_position, space_remaining);
Packit b802ec
Packit b802ec
    /*  If the command stream has been closed, read will return zero.  */
Packit b802ec
    if (read_count == 0) {
Packit b802ec
        errno = EPIPE;
Packit b802ec
        return -1;
Packit b802ec
    }
Packit b802ec
Packit b802ec
    if (read_count > 0) {
Packit b802ec
        /*  Account for the newly read data  */
Packit b802ec
        buffer->incoming_read_position += read_count;
Packit b802ec
    }
Packit b802ec
Packit b802ec
    if (read_count < 0) {
Packit b802ec
        /*  EAGAIN simply means there is no available data to read  */
Packit b802ec
        /*  EINTR indicates we received a signal during read  */
Packit b802ec
        if (errno != EINTR && errno != EAGAIN) {
Packit b802ec
            perror("Unexpected command buffer read error");
Packit b802ec
            exit(EXIT_FAILURE);
Packit b802ec
        }
Packit b802ec
    }
Packit b802ec
Packit b802ec
    return 0;
Packit b802ec
}