|
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 |
}
|