-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.c
More file actions
171 lines (149 loc) · 5.27 KB
/
Copy pathmain.c
File metadata and controls
171 lines (149 loc) · 5.27 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
#include <stdio.h>
#include <string.h>
// custom header file to link all others
#include "shell/shell.h"
#include "source/source.h"
#include "parser/parser.h"
#include "executor/executor.h"
#include <stdlib.h>
#include <errno.h>
#define true 1
int main(int argc, char *argv[])
{
char *cla;
do
{
// print the dollar sign to indicate the user to type something
// use pointer to read command line argument as input
print_prompt1();
cla = read_cla();
// possibilities in reading input and corresponding responses
// if error in reading input, exit
if (!cla)
{
exit(EXIT_SUCCESS);
}
// if first character is NULL or the user has pressed enter at any point
if (cla[0] == '\0' || strcmp(cla, "\n") == 0)
{
free(cla);
continue;
}
// if pointer reads exit from command line, exit
if (strcmp(cla, "exit\n") == 0)
{
free(cla);
break;
}
// print whatever the input argument was
struct source_s src;
src.buffer = cla;
src.buffersize = strlen(cla);
src.currentpos = INIT_SRC_POS;
parse_and_execute(&src);
free(cla);
} while (true);
exit(EXIT_SUCCESS);
}
char *read_cla()
{
// to read input in chunks of 1024 bytes
char buf[1024];
char *ptr = NULL;
int ptrlen = 0;
/* use a while loop to execute code til input is available
* fgets is used to read input from the standard input i.e keyboard
*/
while (fgets(buf, 1024, stdin))
{
/* reclare a variable to allocate and reallocate memory on the system
based on the size of input
*/
// bufferlen does not count null character at the end of buf
int bufferlen = strlen(buf);
if (!ptr)
{
ptr = malloc(bufferlen + 1);
}
else
{
/* if the ptr is already pointing towards some previous input, then
* create a new pointer which allocates ptr additional memory
*/
char *ptr2 = realloc(ptr, ptrlen + bufferlen + 1);
/*
* next step is to redirect pointer ptr towards the direction ptr2
* before that we need to make sure that ptr2 is pointing towards
something and isn't a null pointer or maybe a victim of some error*/
/*
*if(ptr2) means that realloc successfully allocated a memory block
* and returned a pointer to that block by the name of ptr2
*/
if (ptr2)
{
ptr = ptr2;
}
else
{
free(ptr);
ptr = NULL;
}
}
/* pointer ptr2 has a short life, long enough to reallocate memory to ptr
*, ptr has a long life, and it has to be pointing towards a memory block all
* the time (when there is no error), if the ptr is not pointing towards a
* memory block then either it is the first input (we have already dealt with
* that scenario with the malloc function), or there was some error in
* reallocating the memory; in this case we need to give out an error to
* inform the user what has happened
*/
if (!ptr)
{
fprintf(stderr, "memory reallocation failed with error: %s\n", strerror(errno));
return NULL;
}
// till now we have taken all the measures to make sure that the ptr is working correctly, without any errors, now we can copy the input from the buffer to allocated memory
strcpy(ptr + ptrlen, buf);
if (buf[bufferlen - 1] == '\n')
{
if (buf[bufferlen - 2] != '\\' || bufferlen == 1)
{
return ptr;
}
// bufferlen is the length of the new input
// ptrlen is the length of the already stored input (i.e previous input)
// the next line of code tells the compiler to shift the null character 2 places advance, this way we remove the backslash(\) and newline character(\n) and cont.
ptr[ptrlen + bufferlen - 2] = '\0';
// next line reduces the length of the new input by two, since we are not considering the backslash and newline, they were only meant to be indicators
bufferlen = bufferlen - 2;
print_prompt2();
}
/*we check to see if the input we’ve got in the buffer ends with \n and, if so, if the \n is escaped by a backslash
* character \\. If the last \n is not escaped, the input line is complete and we return it to the main() function.
* Otherwise, we remove the two characters (\\ and \n), print out PS2, and continue reading input.
*/
ptrlen += bufferlen;
}
return ptr;
}
int parse_and_execute(struct source_s *src)
{
skip_white_spaces(src);
struct token_s *tok = tokenize(src);
if (tok == &eof_token)
{
return 0;
}
while (tok && tok != &eof_token)
{
struct node_s *cmd = parse_simple_command(tok);
if (!cmd)
{
break;
}
do_simple_command(cmd);
free_node_tree(cmd);
tok = tokenize(src);
}
return 1;
}