-
Notifications
You must be signed in to change notification settings - Fork 0
/
shellOps.c
227 lines (184 loc) · 5.42 KB
/
shellOps.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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/*
* Original Author: Jonathan Hyry
* Date Originally Written: 2/1/2012
*/
#include "shellTUIHdr.h"
/*
* Function getTildeHomePath allows users of Shellac to
* jump to their home directory, as defined by the
* environment variable HOME.
*
* Usage pertaining to built-in command cd:
*
* - If a user enters "cd ~/", the working directory
* will be changed to the directory defined in the
* HOME environment variable.
*
* - The user may also enter a command such as
* "cd ~/Documents" or any deeper subdirectory in
* the directory tree.
*
* Parameters:
*
* char * fullDirStr, / __in /
*
* - This should be the directory string including
* the tilde char
*
* char * parsedHomeDir, / __out /
*
* - This will be where the parsed directory path
* string will be returned.
*
* int homeSubDirPathLength / __in /
*
* - This is the length of the parsed subdirectory.
* This should be fullDirPathLength - 1.
*/
void getTildeHomePath ( char * fullDirStr, /* __in */
char * parsedHomeDir, /* __out */
int homeSubDirPathLength /* __in */ ) {
// Temp string for holding the subdir path
char *tempStr =
(char *)malloc(INPUT_ARG_SIZE*sizeof(char));
// Clean up the newly allocated memory
memset (tempStr,
(int)NULL,
strlen(fullDirStr)*sizeof(char));
// If tilde, go to home dir.
strncpy(tempStr,
++fullDirStr,
homeSubDirPathLength);
#ifdef DEBUG
// DEBUG HOME path stuff
printf("HOME path length: %d\n", homeSubDirPathLength);
printf("Home SubStr address: 0x%x\n", (unsigned int)fullDirStr);
printf("Temp string: %s\n", tempStr);
#endif
strcpy(parsedHomeDir, getenv("HOME"));
strcat(parsedHomeDir, tempStr);
#ifdef DEBUG
// DEBUG After the dir is processed
printf("After HOME processing: %s\n", parsedHomeDir);
#endif
// Cleaning
free(tempStr);
// End function getTildeHomePath
return;
}
/*
* Opens the file "filePath" and reads a batch
* of commands from the open stream.
*/
void runShellacCommandBatch ( char * filePath ) {
//Place to store forked process ID
pid_t tempPID = 0;
// Use fopen with read-only permissions,
// as Shellac has no reason to modify
// the batch file.
FILE *script = fopen(++filePath, "r");
if ( script == NULL ) {
char * fOpenErr = getError();
printf("An error occurred while opening the");
printf(" file at %s.\n Error %d: %s",
filePath, errno, fOpenErr );
// Make sure to free up the space
// used by the error string
free(fOpenErr);
}
else {
// Get the commands from the file
// specified by filePath
for ( j = 0;
// Get command string j from the file.
fgets ( commandBatch[j],
INPUT_ARG_SIZE,
script ) != NULL;) { // End for loop header
#ifdef DEBUG
printf("\nCurrent index: %d\nCurrentCommand: %s\n",
j,
commandBatch[j]);
#endif
// Fork a new process to run the scripted
// command.
tempPID = fork();
//Execute the command
tempPID =
executeCommand( tempPID, commandBatch[j] );
// Wait for the child process to finish
// execution
waitForChildProc( tempPID );
// If the batch array is too small to
// hold all of the commands, we need to
// reallocate the array to fit more stuff.
// Otherwise continue reading.
if ( ++j < (timesResized*BATCH_SIZE) + BATCH_SIZE ) continue;
else reallocateCommandBatchBuffer();
}
}
}
/*
* If the commandBatch script buffer is full,
* yet there are still more commands to read,
* we need to resize the buffer to accomadate
* the rest of the commands.
*/
void reallocateCommandBatchBuffer ( void ) {
// Calculate the new size of the
// command batch buffer...
int newSize =
( (++timesResized) * BATCH_SIZE ) + BATCH_SIZE;
#ifdef DEBUG
printf("\nResizing batch command buffer to %d\n", newSize);
#endif
// Reallocate the outer array that holds
// the head pointer for each string.
commandBatch =
(char **)realloc( commandBatch, newSize * sizeof(char *));
// Allocate more space for new strings
for ( i = newSize - BATCH_SIZE; i < newSize; i++ ) {
commandBatch[i] = (char *)malloc(INPUT_ARG_SIZE * sizeof(char));
memset(commandBatch[i], (int)NULL, INPUT_ARG_SIZE * sizeof(char));
}
}
/*
* Executes a command.
*/
pid_t executeCommand ( pid_t forkedPID, char * command ) {
#ifdef DEBUG
printf("Current process ID is %d", forkedPID);
#endif
// Execute the command
if ( forkedPID == 0 )
execl ( SH_PATH,
SH_NAME,
SH_OPT,
command,
(char *)NULL );
// Or figure out what happened
// if something went wrong
else if ( forkedPID < 0 ) {
// Store the error message
char * forkError = getError();
printf("Fork not completed.\nError %d: %s",
errno,
forkError);
// Deallocate error string.....
free(forkError);
}
return forkedPID;
}
/*
* Takes a pid_t as an argument and returns
* the exit status of the process in stat.
*/
void waitForChildProc ( pid_t childPID ) {
// Wait for the process to finish its
// execution cycle.
while( wait ( &stat ) != childPID );
#ifdef DEBUG
// DEBUG Prints process ID and PID
// childProc exit status via stat.
printf("\nProcess %d ended with status %d.\n", childPID, stat);
#endif
}