-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinput.c
210 lines (176 loc) · 6.75 KB
/
input.c
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#include "input.h"
//*********************************************************************
//NOTE: We will overwrite this file, so whatever changes you put here
// WILL NOT persist
//*********************************************************************
/* getline implementation is copied from glibc. */
#ifndef SIZE_MAX
#define SIZE_MAX ((size_t) -1)
#endif
#ifndef SSIZE_MAX
#define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
#endif
ssize_t getline(char **lineptr, size_t *n, FILE *fp)
{
ssize_t result;
size_t cur_len = 0;
if (lineptr == NULL || n == NULL || fp == NULL) {
return -1;
}
if (*lineptr == NULL || *n == 0) {
*n = 120;
*lineptr = (char *) malloc(*n);
if (*lineptr == NULL) {
result = -1;
goto end;
}
}
for (;;) {
int i;
i = getc(fp);
if (i == EOF) {
result = -1;
break;
}
/* Make enough space for len+1 (for final NUL) bytes. */
if (cur_len + 1 >= *n) {
size_t needed_max =
SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
size_t needed = 2 * *n + 1; /* Be generous. */
char *new_lineptr;
if (needed_max < needed) {
needed = needed_max;
}
if (cur_len + 1 >= needed) {
result = -1;
goto end;
}
new_lineptr = (char *) realloc(*lineptr, needed);
if (new_lineptr == NULL) {
result = -1;
goto end;
}
*lineptr = new_lineptr;
*n = needed;
}
(*lineptr)[cur_len] = i;
cur_len++;
if (i == '\n') {
break;
}
}
(*lineptr)[cur_len] = '\0';
result = cur_len ? (ssize_t) cur_len : result;
end:
return result;
}
void *run_stdinthread(void *threadid)
{
fd_set read_fds, master_fds;
int fd_max;
int select_res;
int sender_id;
int receiver_id;
int sscanf_res;
size_t input_buffer_size = (size_t) DEFAULT_INPUT_BUFFER_SIZE;
char *input_buffer;
char *input_message;
int input_bytes_read;
char input_command[MAX_COMMAND_LENGTH];
Sender *sender;
//Zero out fd_sets
FD_ZERO(&read_fds);
FD_ZERO(&master_fds);
//Add standard input to the fd_set
FD_SET(STDIN_FILENO, &master_fds);
fd_max = STDIN_FILENO;
while (1) {
//Copy the master set to avoid permanently altering the master set
read_fds = master_fds;
if ((select_res = select(fd_max + 1,
&read_fds,
NULL,
NULL,
NULL)) == -1) {
perror("Select failed - exiting program");
pthread_exit(NULL);
}
//User inputted a string, read in input and prepare to send
if (FD_ISSET(STDIN_FILENO, &read_fds)) {
input_buffer = (char *) malloc(input_buffer_size * sizeof(char));
//NULL set the entire input buffer
memset(input_buffer,
0,
input_buffer_size * sizeof(char));
//Read in the command line into the input buffer
input_bytes_read = getline(&input_buffer, &input_buffer_size, stdin);
//Zero out the readin buffers for the command
memset(input_command,
0,
MAX_COMMAND_LENGTH * sizeof(char));
//Zero out the memory for the message to communicate
input_message = (char *) malloc((input_bytes_read + 1) * sizeof(char));
memset(input_message,
0,
(input_bytes_read + 1) * sizeof(char));
//Scan the input for the arguments
sscanf_res = sscanf(input_buffer,
"%s %d %d %[^\n]",
input_command,
&sender_id,
&receiver_id,
input_message);
//Number of parsed objects is less than expected
if (sscanf_res < 4) {
if (strcmp(input_command, "exit") == 0) {
free(input_message);
free(input_buffer);
return 0;
} else {
fprintf(stderr, "Command is ill-formatted\n");
}
} else {
if (strcmp(input_command, "msg") == 0) {
//Check to ensure that the sender and receiver ids are in the right range
if (sender_id >= glb_senders_array_length ||
sender_id < 0) {
fprintf(stderr, "Sender id is invalid\n");
}
if (receiver_id >= glb_receivers_array_length ||
receiver_id < 0) {
fprintf(stderr, "Receiver id is invalid\n");
}
//Only add if valid
if (sender_id < glb_senders_array_length &&
receiver_id < glb_receivers_array_length &&
sender_id >= 0 &&
receiver_id >= 0) {
//Add the message to the receive buffer for the appropriate thread
Cmd *outgoing_cmd = (Cmd *) malloc(sizeof(Cmd));
char *outgoing_msg = (char *) malloc(sizeof(char) * (strlen(input_message) + 1));
//Copy out the input message into the outgoing command object
strcpy(outgoing_msg,
input_message);
outgoing_cmd->src_id = sender_id;
outgoing_cmd->dst_id = receiver_id;
outgoing_cmd->message = outgoing_msg;
//Add it to the appropriate input buffer
sender = &glb_senders_array[sender_id];
//Lock the buffer, add to the input list, and signal the thread
pthread_mutex_lock(&sender->buffer_mutex);
ll_append_node(&sender->input_cmdlist_head,
(void *) outgoing_cmd);
pthread_cond_signal(&sender->buffer_cv);
pthread_mutex_unlock(&sender->buffer_mutex);
}
} else {
fprintf(stderr, "Unknown command:%s\n", input_buffer);
}
}
//Lastly, free the input_buffer and the input_message
free(input_buffer);
free(input_message);
}
}
pthread_exit(NULL);
}