1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
/*
* Copyright (C) 2006-2009 Andre Noll <maan@systemlinux.org>
*
* Licensed under the GPL v2. For licencing details see COPYING.
*/
/** \file stdin.c Functions that deal with reading from stdin. */
#include <dirent.h> /* readdir() */
#include <assert.h>
#include "para.h"
#include "string.h"
#include "list.h"
#include "sched.h"
#include "fd.h"
#include "error.h"
#include "stdin.h"
/**
* The pre_select function of the stdin task.
*
* \param s The scheduler this task was registered to.
* \param t The task structure of the stdin task.
*
* This function is always successful. If there is space left in the
* buffer of the stdin task, it adds \p STDIN_FILENO to the read fd set
* of \a s.
*/
static void stdin_pre_select(struct sched *s, struct task *t)
{
struct stdin_task *sit = container_of(t, struct stdin_task, task);
if (sit->output_error && *sit->output_error < 0) {
t->error = *sit->output_error;
return;
}
t->error = 0;
sit->check_fd = 0;
if (sit->loaded >= sit->bufsize)
return;
sit->check_fd = 1;
para_fd_set(STDIN_FILENO, &s->rfds, &s->max_fileno);
}
/**
* The post select function of the stdin task.
*
* \param s The scheduler this task was registered to.
* \param t The task structure of the stdin task.
*
* This function checks if \p STDIN_FILENO was included by in the read fd set
* of \a s during the previous pre_select call. If yes, and \p STDIN_FILENO
* appears to be readable, data is read from stdin into the buffer of the
* stdin task.
*/
static void stdin_post_select(struct sched *s, struct task *t)
{
struct stdin_task *sit = container_of(t, struct stdin_task, task);
ssize_t ret;
if (sit->output_error && *sit->output_error < 0) {
t->error = *sit->output_error;
return;
}
t->error = 0;
if (!sit->check_fd)
return;
if (!FD_ISSET(STDIN_FILENO, &s->rfds))
return;
ret = read(STDIN_FILENO, sit->buf + sit->loaded, sit->bufsize - sit->loaded);
if (ret < 0)
t->error = -ERRNO_TO_PARA_ERROR(errno);
else if (ret > 0)
sit->loaded += ret;
else
t->error = -E_STDIN_EOF;
}
/**
* Initialize a stdin task structure with default values.
*
* \param sit The stdin task structure.
*
* This fills in the pre/post select function pointers of the task structure
* given by \a sit. Moreover, the stdin file desctiptor is set to nonblocking
* mode and \a bufsize is initialized to 16 KB (but no buffer is allocated).
*/
void stdin_set_defaults(struct stdin_task *sit)
{
int ret;
sit->bufsize = 32 * 1024,
sit->task.pre_select = stdin_pre_select;
sit->task.post_select = stdin_post_select;
sprintf(sit->task.status, "stdin reader");
ret = mark_fd_nonblocking(STDIN_FILENO);
if (ret >= 0)
return;
sit->output_error = NULL;
PARA_EMERG_LOG("%s\n", para_strerror(-ret));
exit(EXIT_FAILURE);
}
|