Advertisement
Guest User

Untitled

a guest
Feb 18th, 2019
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.54 KB | None | 0 0
  1. #include <iostream>
  2. #include <iomanip>
  3. #include <unistd.h>
  4. #include <cstdlib>
  5. #include <cstdio>
  6. #include <cstring>
  7. #include <sys/types.h>
  8. #include <sys/wait.h>
  9.  
  10. using namespace std;
  11.  
  12. // Declare constant values for program
  13. const unsigned BUFFER_SIZE = 1024;
  14. const unsigned MAX_ARGUMENT_COUNT = 64;
  15.  
  16. const char *SHELL_TITLE = "480SHELL> ";
  17. const char *QUIT_PROMPT = "quit";
  18. const char *QUIT_PROMPT2 = "q";
  19. const char *PIPE_PROMPT = "||";
  20.  
  21. /****************************************************************
  22.    FILE:      main.cpp
  23.    AUTHOR:    Kevin Miyata
  24.    LOGON ID:  Z1771936
  25.    DUE DATE:  18 February 2019
  26.    PURPOSE:   This file simulates a shell with commands. It allows input from one
  27.               file to be outputted to another file using an operator and file arguments.
  28. ****************************************************************/
  29. int main() {
  30.  
  31.     // Read and write pipes
  32.     int pipeFileDescriptor[2];
  33.  
  34.     // Fork and exec statuses
  35.     int processId;
  36.     int status;
  37.  
  38.     // Input buffer
  39.     char buffer[BUFFER_SIZE];
  40.  
  41.     // Set argument count to maximum
  42.     int argumentCount = MAX_ARGUMENT_COUNT;
  43.  
  44.     // Print shell name to prompt for commands
  45.     cerr << SHELL_TITLE;
  46.  
  47.     // Cycle through stdin and feed to buffer to get commands and arguments
  48.     while (fgets(buffer, BUFFER_SIZE, stdin) != nullptr) {
  49.  
  50.         // Replace final character with null terminator
  51.         buffer[strlen(buffer) - 1] = '\0';
  52.  
  53.         // Create array for incoming arguments
  54.         char *arguments[argumentCount];
  55.  
  56.         // Check for argument separation with spacing
  57.         arguments[0] = strtok(buffer, " ");
  58.  
  59.         // Cycle through arguments to create argument array
  60.         for (int i = 1; arguments[i] != nullptr; i++) {
  61.             arguments[i] = strtok(nullptr, " ");
  62.         }
  63.  
  64.         // Look for exit command
  65.         if (strcmp(arguments[0], QUIT_PROMPT) == 0 or strcmp(arguments[0], QUIT_PROMPT2) == 0) {
  66.             // Exit if quit prompt was matched to input
  67.             exit(1);
  68.         }
  69.  
  70.         // Check for pipe index
  71.         int pipeLocation = -1;
  72.  
  73.         // Scan through all arguments
  74.         for (int i = 1; i < argumentCount; i++) {
  75.             if (arguments[i] != nullptr) {
  76.                 if (strcmp(arguments[i], PIPE_PROMPT) == 0) {
  77.                     pipeLocation = i;
  78.                     arguments[i] = nullptr;
  79.                 }
  80.             } else {
  81.                 break;
  82.             }
  83.         }
  84.  
  85.         // Check for pipe command
  86.         if (pipeLocation > 0) {
  87.  
  88.             // Check for pipe errors
  89.             if (pipe(pipeFileDescriptor) < 0) {
  90.                 fprintf(stderr, "ERROR: Could not pipe!");
  91.                 return -5;
  92.             }
  93.  
  94.             // Fork parent process
  95.             processId = fork();
  96.  
  97.             // Check fork status for failure
  98.             if (processId < 0) {
  99.                 fprintf(stderr, "ERROR: Could not fork process!");
  100.             } else if (processId == 0) {
  101.  
  102.                 // Close unused pipes
  103.                 close(1);
  104.                 close(pipeFileDescriptor[0]);
  105.  
  106.                 // Dup writing pipe
  107.                 dup2(pipeFileDescriptor[1], 1);
  108.  
  109.                 // Execute command with arguments
  110.                 execvp(arguments[0], arguments);
  111.             } else {
  112.                 wait(nullptr);
  113.             }
  114.  
  115.             // Fork child process
  116.             processId = fork();
  117.  
  118.             if (processId < 0) {
  119.                 fprintf(stderr, "ERROR: Could not fork!");
  120.             } else if (processId == 0) {
  121.                 // Close unused pipes
  122.                 close(1);
  123.                 close(0);
  124.                 close(pipeFileDescriptor[0]);
  125.  
  126.                 // Dup write pipe
  127.                 dup(pipeFileDescriptor[1]);
  128.  
  129.                 // Run secondary commands
  130.                 execvp(arguments[0], &arguments[pipeLocation + 1]);
  131.             } else {
  132.                 wait(nullptr);
  133.             }
  134.  
  135.             // Close parent pipes
  136.             close(pipeFileDescriptor[1]);
  137.         } else {
  138.             // Open write pipe, check for error
  139.             if (pipe(pipeFileDescriptor) < 0) {
  140.                 fprintf(stderr, "Could not pipe!");
  141.                 return -5;
  142.             }
  143.  
  144.             // Fork process again
  145.             processId = fork();
  146.  
  147.             // Check for fork error
  148.             if (processId < 0) {
  149.                 fprintf(stderr, "Could not fork process!");
  150.             } else if (processId == 0) {
  151.                 // This is the child process!
  152.  
  153.                 // Close unused pipes
  154.                 close(1);
  155.                 close(pipeFileDescriptor[0]);
  156.  
  157.                 // Duplicate and write to pipe
  158.                 dup(pipeFileDescriptor[1]);
  159.                 execvp(arguments[0], arguments);
  160.             }
  161.  
  162.             // Close the parent pipe
  163.             close(pipeFileDescriptor[1]);
  164.         }
  165.  
  166.         // Wait for parent process
  167.         processId = waitpid(processId, &status, 0);
  168.  
  169.         // Check for error when waiting for other process
  170.         if (processId < 0) {
  171.             fprintf(stderr, "Wait for process with id %d failed!", processId);
  172.         }
  173.  
  174.         // Create output buffer, set final character to null terminator
  175.         char output[2];
  176.         output[1] = '\0';
  177.  
  178.         // Scan through the read pipe and print out the buffer
  179.         while (read(pipeFileDescriptor[0], output, 1) not_eq 0) {
  180.             fprintf(stderr, output);
  181.         }
  182.  
  183.         // Print out shell title again
  184.         fprintf(stderr, "\n%s", SHELL_TITLE);
  185.     }
  186.  
  187.     return 0;
  188. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement