-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcalendar.c
More file actions
203 lines (171 loc) · 6.46 KB
/
calendar.c
File metadata and controls
203 lines (171 loc) · 6.46 KB
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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "lists.h"
#define INPUT_BUFFER_SIZE 256
#define INPUT_ARG_MAX_NUM 8
#define DELIM " \n"
#define MAX_SIZE 256
/*
* Print a formatted error message to stderr.
*/
void error(char *msg) {
fprintf(stderr, "Error: %s\n", msg);
}
/*
* Return a calendar time representation of the time specified
* in local_args.
* local_argv[0] must contain hour.
* local_argv[1] may contain day, otherwise use current day
* local_argv[2] may contain month, otherwise use current month
* local_argv[3] may contain day, otherwise use current year
*/
time_t convert_time(int local_argc, char** local_argv) {
time_t rawtime;
struct tm * info;
// Instead of expicitly setting the time, use the current time and then
// change some parts of it.
time(&rawtime); // get the time_t represention of the current time
info = localtime(&rawtime);
// The user must set the hour.
info->tm_hour = atof(local_argv[0]);
// We don't want the current minute or second.
info->tm_min = 0;
info->tm_sec = 0;
if (local_argc > 1) {
info->tm_mday = atof(local_argv[1]);
}
if (local_argc > 2) {
// months are represented counting from 0 but most people count from 1
info->tm_mon = atof(local_argv[2])-1;
}
if (local_argc > 3) {
// tm_year is the number of years after the epoch but users enter the year AD
info->tm_year = atof(local_argv[3])-1900;
}
// start off by assuming we won't be in daylight savings time
info->tm_isdst = 0;
mktime(info);
// need to correct if we guessed daylight savings time incorrect since
// mktime changes info as well as returning a value. Check it out in gdb.
if (info->tm_isdst == 1) {
// this means we guessed wrong about daylight savings time so correct the hour
info->tm_hour--;
}
return mktime(info);
}
/*
* Read and process calendar commands
* Return: -1 for quit command
* 0 otherwise
*/
int process_args(int cmd_argc, char **cmd_argv, Calendar **calendar_list_ptr, User **user_list_ptr) {
Calendar *calendar_list = *calendar_list_ptr;
User *user_list = *user_list_ptr;
char * buf;
if (cmd_argc <= 0) {
return 0;
} else if (strcmp(cmd_argv[0], "quit") == 0 && cmd_argc == 1) {
return -1;
} else if (strcmp(cmd_argv[0], "add_calendar") == 0 && cmd_argc == 2) {
if (add_calendar(calendar_list_ptr, cmd_argv[1]) == -1) {
error("Calendar by this name already exists");
}
} else if (strcmp(cmd_argv[0], "list_calendars") == 0 && cmd_argc == 1) {
//set buf to the value returned by the list_calendars function
buf = list_calendars(calendar_list);
printf("%s", buf);
} else if (strcmp(cmd_argv[0], "add_event") == 0 && cmd_argc >= 4) {
// Parameters for convert_time are the values in the array
// cmd_argv but starting at cmd_argv[3]. The first 3 are not
// part of the time.
// So subtract these 3 from the count and pass the pointer
// to element 3 (where the first is element 0).
time_t time = convert_time(cmd_argc-3, &cmd_argv[3]);
if (add_event(calendar_list, cmd_argv[1], cmd_argv[2], time) == -1) {
error("Calendar by this name does not exist");
}
} else if (strcmp(cmd_argv[0], "list_events") == 0 && cmd_argc == 2) {
//set buf to the value returned by the list_events function
buf = list_events(calendar_list, cmd_argv[1]);
if (strcmp(buf, "-1") == 0) {
error("Calendar by this name does not exist");
}
else {
printf("%s", buf);
}
} else if (strcmp(cmd_argv[0], "add_user") == 0 && cmd_argc == 2) {
if (add_user(user_list_ptr, cmd_argv[1]) == -1) {
error("User by this name already exists");
}
} else if (strcmp(cmd_argv[0], "list_users") == 0 && cmd_argc == 1) {
//set buf to the value returned by the list_users function
buf = list_users(user_list);
printf(" %s", buf);
} else if (strcmp(cmd_argv[0], "subscribe") == 0 && cmd_argc == 3) {
int return_code = subscribe(user_list, calendar_list, cmd_argv[1], cmd_argv[2]);
if (return_code == -1) {
error("User by this name does not exist");
} else if (return_code == -2) {
error("Calendar by this name does not exist");
} else if (return_code == -3) {
error("This user is already subscribed to this calendar");
}
} else {
error("Incorrect syntax");
}
return 0;
}
int main(int argc, char* argv[]) {
int batch_mode = (argc == 2);
char input[INPUT_BUFFER_SIZE];
FILE *input_stream;
// for holding arguments to individual commands passed to sub-procedure
char *cmd_argv[INPUT_ARG_MAX_NUM];
int cmd_argc;
// Create the heads of the two empty data-structures
Calendar *calendar_list = NULL;
User *user_list = NULL;
if (batch_mode) {
input_stream = fopen(argv[1], "r");
if (input_stream == NULL) {
perror("Error opening file");
exit(1);
}
} else {
// interactive mode
input_stream = stdin;
}
printf("Welcome to Calendar!\nPlease type a command:\n>");
while (fgets(input, INPUT_BUFFER_SIZE, input_stream) != NULL) {
// only echo the line in batch mode since in interactive mode the user
// just typed the line
if (batch_mode) {
printf("%s", input);
}
// tokenize arguments
// Notice that this tokenizing is not sophisticated enough to handle quoted arguments
// with spaces so calendar names, event descriptions, usernames etc. can not have spaces.
char *next_token = strtok(input, DELIM);
cmd_argc = 0;
while (next_token != NULL) {
if (cmd_argc >= INPUT_ARG_MAX_NUM - 1) {
error("Too many arguments!");
cmd_argc = 0;
break;
}
cmd_argv[cmd_argc] = next_token;
cmd_argc++;
next_token = strtok(NULL, DELIM);
}
if (cmd_argc > 0 && process_args(cmd_argc, cmd_argv, &calendar_list, &user_list) == -1) {
break; // can only reach if quit command was entered
}
printf(">");
}
if (batch_mode) {
fclose(input_stream);
}
return 0;
}