├── Makefile ├── LICENSE ├── README.md ├── src ├── command.h └── hw0.cpp └── test └── exec.script /Makefile: -------------------------------------------------------------------------------- 1 | COMPILER = g++ 2 | CFLAGS = -ansi -pedantic -Wall -Werror 3 | RESULT = ./bin/rshell 4 | DIRECTORY = ./src/hw0.cpp 5 | all: 6 | mkdir -p ./bin 7 | $(COMPILER) $(CFLAGS) $(DIRECTORY) -o $(RESULT) 8 | 9 | rshell: 10 | mkdir -p ./bin 11 | $(COMPILER) $(CFLAGS) $(DIRECTORY) -o $(RESULT) 12 | clean: 13 | rm -rf ./bin 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | copyright (c) 2015, zxie003 2 | All rights reserved. 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | * Redistributions of source code must retain the above copyright notice, this 6 | list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright notice, 8 | this list of conditions and the following disclaimer in the documentation 9 | and/or other materials provided with the distribution. 10 | * Neither the name of rshell nor the names of its 11 | contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rshell 2 | 3 | rshell is a program I wrote that functions alomost the same sa BASH terminal. 4 | it can run commands, and use seperators such as `;` , `||` ,and `&&`. 5 | it also take in comments, which is indicated after the sign `#`. everything after `#` in a command line is a comment, and will not execute with the commands. 6 | 7 | each command can take in arguments using space to seperate each term. 8 | 9 | inputing `true` in the command line means "command" executed. 10 | inputing `false` in the command line means "command" did not executed. 11 | 12 | to exit the program, simply type `exit` as a command. 13 | 14 | 15 | ##EDGE CASES: 16 | 1. seperator comes in pair: having `&&&` will consider having a seperator `&&` and a 17 | command `&`, which will return false. the same apply for `|||`. 18 | 2. however, having `;;;` will means nothing, and the program does nothing. 19 | 3. having single command with connector, for example `&& ls;`, the command ls will be 20 | executed, so as in the case of `ls &&;`. the same apply to seperator `||`. 21 | 4. however, having a space before or after the connector will result in false, such 22 | as ` && ls;` or `ls && ;`. 23 | 24 | #How to run rshell 25 | 26 | ``` 27 | $git clone https://github.com/sandiexie/rshell.git 28 | $cd rshell 29 | $git checkout hw0 30 | $make 31 | $bin/rshell 32 | ``` 33 | 34 | #Bugs 35 | 1. quotation marks will not work as expected.for example `echo "hi" ` will output `"hi"`. 36 | 2. spaces and tab by itself wont be ignored. and be run as error command. 37 | 3. comment by is self will report as error command. 38 | -------------------------------------------------------------------------------- /src/command.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | class command 7 | { 8 | private: 9 | string call; 10 | bool next; 11 | char sperator; 12 | char* arg[100]; 13 | vector copy; 14 | public: 15 | void set_copy( vector ); 16 | void reset(); 17 | command(); 18 | command(string,char); 19 | void set_next(bool); 20 | void set_sperator(char); 21 | void printc(); 22 | void set_call(string, char); 23 | char get_sperator(); 24 | string get_call(); 25 | char** get_arr(); 26 | }; 27 | 28 | void command :: set_copy( vector a ) 29 | { 30 | for (unsigned int e=0; e < a.size(); e++ ) 31 | { 32 | copy.push_back(a.at(e)); 33 | } 34 | } 35 | 36 | char** command :: get_arr() 37 | { 38 | return arg; 39 | } 40 | 41 | char command :: get_sperator() 42 | { 43 | return sperator; 44 | } 45 | void command :: reset() 46 | { 47 | unsigned int keep; 48 | for (unsigned int t=0; t 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "command.h" 11 | 12 | using namespace std; 13 | 14 | void user() 15 | { 16 | char* user_name = getlogin(); 17 | if (!getlogin()) 18 | { 19 | perror("getlogin"); 20 | } 21 | 22 | char name [1000]; 23 | if ( gethostname(name, 1000) == -1 ) 24 | { 25 | perror("gethostname"); 26 | } 27 | 28 | cout << user_name << "@" << name << ":" << "$"; 29 | } 30 | 31 | bool execute ( char*argu[]) 32 | { 33 | int pass = 0; 34 | 35 | if( *argu == NULL ) 36 | { 37 | return false; 38 | } 39 | 40 | pid_t pid = fork(); 41 | 42 | if (pid == -1) 43 | { 44 | perror ("fork"); 45 | exit (1); 46 | // iperror 47 | } 48 | 49 | if (pid == 0) 50 | { 51 | pass = execvp (argu[0], argu); 52 | 53 | if( pass < 0) 54 | { 55 | perror ("exec"); 56 | exit(1); 57 | } 58 | // in child 59 | } 60 | if (pid > 0) 61 | { 62 | pid_t wait = waitpid(pid, &pass, 0); 63 | 64 | if (wait < 0 ) 65 | { 66 | perror("wait"); 67 | } 68 | 69 | if (pass > 0) 70 | { 71 | return false; 72 | } 73 | else 74 | { 75 | return true; 76 | } 77 | //in parent 78 | } 79 | 80 | return true; 81 | } 82 | 83 | int main(int argc, char* argv[]) 84 | { 85 | while(1) 86 | { 87 | user(); 88 | 89 | string input; 90 | getline(cin,input); 91 | 92 | size_t found =-1; 93 | found = input.find("#"); 94 | 95 | if (found > 0) 96 | { 97 | input = input.substr(0, found); 98 | } 99 | 100 | char* temp_input = (char*) input.c_str(); 101 | char* token; 102 | 103 | vector < vector > syscalls; 104 | vector inner; 105 | 106 | token = strtok (temp_input,";"); 107 | 108 | // sperate command by ; 109 | 110 | command holder; 111 | 112 | if (token!=NULL) 113 | { 114 | holder.set_call (token,';'); 115 | inner.push_back(holder); 116 | 117 | syscalls.push_back(inner); 118 | } 119 | inner.clear(); 120 | 121 | while (token != NULL) 122 | { 123 | token = strtok (NULL, ";"); 124 | 125 | if (token != NULL) 126 | { 127 | holder.set_call(token,';'); 128 | inner.push_back(holder); 129 | syscalls.push_back (inner); 130 | } 131 | inner.clear(); 132 | } 133 | 134 | // sperate command by & ============================================================== 135 | 136 | if (syscalls.size() > 0) 137 | { 138 | command holder1; 139 | 140 | for (unsigned int i = 0; i < syscalls.size(); ++i ) 141 | { 142 | 143 | string whole1 = syscalls.at(i).at(0).get_call(); 144 | string wholecopy1 = whole1; 145 | 146 | size_t found1 = whole1.find("&&"); 147 | string call1; 148 | 149 | while ( found1 != string::npos) 150 | { 151 | call1 = wholecopy1.substr(0,found1); 152 | 153 | holder1.set_call ( call1, '&' ); 154 | syscalls.at(i).push_back(holder1); 155 | 156 | whole1 = whole1.substr(found1+2,whole1.size()); 157 | wholecopy1 = whole1; 158 | 159 | found1 = whole1.find("&&"); 160 | } 161 | 162 | if(whole1.length() != 0) 163 | { 164 | holder1.set_call (whole1, ';'); 165 | syscalls.at(i).push_back(holder1); 166 | } 167 | 168 | } 169 | 170 | for (unsigned int u=0; u 0) 197 | { 198 | holder2.set_call (call2, '|'); 199 | syscalls.at(i).push_back(holder2); 200 | } 201 | whole2 = whole2.substr(found2+2, whole2.size()); 202 | wholecopy2 = whole2; 203 | 204 | found2 = whole2.find("||"); 205 | } 206 | 207 | if(whole2.length() != 0) 208 | { 209 | holder2.set_call (whole2, '&'); 210 | syscalls.at(i).push_back(holder2); 211 | } 212 | 213 | newsize = syscalls.at(i).size(); 214 | } 215 | 216 | 217 | syscalls.at(i).at(newsize-1).set_call(syscalls.at(i).at(newsize-1).get_call(), ';'); 218 | 219 | for (unsigned int y =0 ; y < size; y++) 220 | { 221 | syscalls.at(i).erase( syscalls.at(i).begin() ); 222 | } 223 | } 224 | 225 | //cout << "seperate by || success" <0) 232 | { 233 | for (unsigned int i=0; i 0 ) 237 | { 238 | 239 | for (unsigned int j=0; j tempA; 242 | 243 | 244 | char* whole_cell = (char*) (syscalls.at(i).at(j).get_call()).c_str(); 245 | char* command1; 246 | 247 | command1 = strtok(whole_cell, " \t"); 248 | if (command1 != NULL) 249 | { 250 | tempA.push_back(command1); 251 | } 252 | 253 | while(command1 != NULL) 254 | { 255 | command1 = strtok (NULL, " "); 256 | if (command1 != NULL) 257 | { 258 | tempA.push_back(command1); 259 | } 260 | } 261 | if (tempA.size() > 0) 262 | { 263 | 264 | syscalls.at(i).at(j).set_copy ( tempA ); 265 | syscalls.at(i).at(j).reset(); 266 | } 267 | } 268 | } 269 | } 270 | // codes to test whats in char** arr[]================================================ 271 | // executing ========================================================================== 272 | 273 | if (syscalls.size()>0) 274 | { 275 | for (unsigned int i=0; i <= syscalls.size()-1; i++) 276 | { 277 | bool e_or = false; 278 | bool e_and = true; 279 | 280 | if (syscalls.at(i).size() >0) 281 | { 282 | for (unsigned int j=0; j <= syscalls.at(i).size()-1; j++) 283 | { 284 | //cout << j << " <- " << *(syscalls.at(i).at(0).get_arr( )) << endl; 285 | 286 | if ( j==0 ) 287 | { 288 | // doing with the first one of each vector 289 | // will ALWAYS run exec 290 | //cout << "the first one: " << *(syscalls.at(i).at(0).get_arr( )) << endl; 291 | 292 | string aaa = *(syscalls.at(i).at(0).get_arr()); 293 | 294 | if ( aaa == "exit" ) 295 | { 296 | exit(1); 297 | } 298 | if ( execute(syscalls.at(i).at(0).get_arr()) == true ) 299 | { 300 | e_or = true; 301 | e_and = true; 302 | } 303 | else 304 | { 305 | e_or = false; 306 | e_and = false; 307 | } 308 | } 309 | //------------------------------------------------------------- 310 | //============================================================ 311 | else 312 | { 313 | string bbb = *(syscalls.at(i).at(j).get_arr()); 314 | if ( bbb == "exit" ) 315 | { 316 | exit(1); 317 | } 318 | // not the first one 319 | if ( syscalls.at(i).at(j-1).get_sperator() == '&') 320 | { 321 | // if following a && 322 | if ( e_and == true ) 323 | { 324 | if ( execute(syscalls.at(i).at(j).get_arr()) == true ) 325 | { 326 | e_and = true; 327 | } 328 | else 329 | { 330 | e_and = false; 331 | } 332 | } 333 | else 334 | { 335 | // do nothing 336 | } 337 | 338 | //---------------------------------------------- 339 | 340 | if ( syscalls.at(i).at(j).get_sperator() == '|' ) 341 | { 342 | e_or = e_and; 343 | } 344 | else 345 | { 346 | // do nothing 347 | } 348 | 349 | } 350 | //============================================================== 351 | else if ( syscalls.at(i).at(j-1).get_sperator() == '|') 352 | { 353 | // if following a || 354 | if ( e_or == false ) 355 | { 356 | if ( execute(syscalls.at(i).at(j).get_arr()) == true ) 357 | { 358 | e_or = true; 359 | } 360 | else 361 | { 362 | e_or = false; 363 | } 364 | } 365 | else if ( e_or == true) 366 | { 367 | // do nothing 368 | } 369 | 370 | 371 | //----------------------------------------------- 372 | 373 | if ( syscalls.at(i).at(j).get_sperator() == '&' ) 374 | { 375 | e_and = e_or ; 376 | } 377 | else 378 | { 379 | // do nothing 380 | } 381 | } 382 | } 383 | 384 | 385 | 386 | 387 | } 388 | } 389 | } 390 | } 391 | } 392 | // codes to test whats in char** arr[]================================================ 393 | 394 | } 395 | 396 | } 397 | 398 | 399 | 400 | 401 | 402 | --------------------------------------------------------------------------------