Giter Club home page Giter Club logo

42-school-exam-rank-04's Introduction

Exam Question

This exam has 1 question, microshell:

if you can make this code shorter, but readable, let me know!


Excepted Files

  • microshell.c

Subject Text

Allowed functions:

malloc, free, write, close, fork, waitpid, signal, kill, exit, chdir, execve, dup, dup2, pipe, strcmp, strncmp

The Program

Write a program that will behave like executing a shell command

  • The command line to execute will be the arguments of this program

  • Executable's path will be absolute or relative but your program must not build a path (from the PATH variable for example)

  • You must implement "|" and ";" like in bash

    • we will never try a "|" immediately followed or preceded by nothing or "|" or ";"
  • Your program must implement the built-in command cd only with a path as argument (no '-' or without parameters)

    • if cd has the wrong number of argument your program should print in STDERR "error: cd: bad arguments" followed by a '\n'
    • if cd failed your program should print in STDERR "error: cd: cannot change directory to path_to_change" followed by a '\n' with path_to_change replaced by the argument to cd
    • a cd command will never be immediately followed or preceded by a "|"
  • You don't need to manage any type of wildcards (*, ~ etc...)

  • You don't need to manage environment variables ($BLA ...)

  • If a system call, except execve and chdir, returns an error your program should immediatly print "error: fatal" in STDERR followed by a '\n' and the program should exit

  • If execve failed you should print "error: cannot execute executable_that_failed" in STDERR followed by a '\n' with executable_that_failed replaced with the path of the failed executable (It should be the first argument of execve)

  • Your program should be able to manage more than hundreds of "|" even if we limit the number of "open files" to less than 30.

Example

for example this should work:

$>./microshell /bin/ls "|" /usr/bin/grep microshell ";" /bin/echo i love my microshell
microshell
i love my microshell
$>

>./microshell 

Hints

  • Don't forget to pass the environment variable to execve
  • Do not leak file descriptors!

Commented Code

#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>

// Function to write an error message to stderr
int err(char *str)
{
    // Loop through each character in the string and write it to stderr
    while (*str)
        write(2, str++, 1);
}

// Function to change the current working directory
int cd(char **argv, int i)
{
    // If the number of arguments is not 2, print error and exit
    if (i != 2)
        return err("error: cd: bad arguments\n"), 1;
    // If changing the directory fails, print error and exit
    if (chdir(argv[1]) == -1)
        return err("error: cd: cannot change directory to "), err(argv[1]), err("\n"), 1;
    return 0;
}

// Function to set pipe
// end == 1 sets stdout to act as write end of our pipe
// end == 0 sets stdin to act as read end of our pipe
void set_pipe(int has_pipe, int *fd, int end)
{
	if (has_pipe && (dup2(fd[end], end) == -1 || close(fd[0]) == -1 || close(fd[1]) == -1))
		err("error: fatal\n"), exit(1);
}

// Function to execute a command
int exec(char **argv, int i, char **envp)
{
    int has_pipe, fd[2], pid, status;

    // Check if the command includes a pipe
    has_pipe = argv[i] && !strcmp(argv[i], "|");

    // If the command is 'cd', execute it
    if (!has_pipe && !strcmp(*argv, "cd"))
        return cd(argv, i);

    // If the command includes a pipe and creating the pipe fails, print error and exit
    if (has_pipe && pipe(fd) == -1)
        err("error: fatal\n"), exit(1);

    // Fork the process
    pid = fork();
    if (!pid)
    {
        argv[i] = 0;
        // If the command includes a pipe, set write end of pipe, if it fail print error and exit
        set_pipe(has_pipe, fd, 1);
        // If the command is 'cd', execute it
        if (!strcmp(*argv, "cd"))
            return cd(argv, i);
        // Execute the command
        execve(*argv, argv, envp);
        // If executing the command fails, print error and exit
        err("error: cannot execute "), err(*argv), err("\n"), exit(1);
    }

    // Wait for the child process to finish
    waitpid(pid, &status, 0);
    // If the command includes a pipe, set write end of pipe, if it fail print error and exit
    set_pipe(has_pipe, fd, 0);
    // Return the exit status of the child process
    return WIFEXITED(status) && WEXITSTATUS(status);
}

int main(int, char **argv, char **envp)
{
    int    i = 1, status = 0;

    // Skip first arg and loop through each following argument
    while (argv[i])
    {
        // Move the pointer to the next argument
    	argv += i;
    	i = 0;
        // Loop through each argument until a pipe or semicolon is found
    	while (argv[i] && strcmp(argv[i], "|") && strcmp(argv[i], ";"))
			i++;
        // If there are arguments, execute them
    	if (i)
			status = exec(argv, i, envp);
        // If not at the end of argv increment i
		i += (argv[i] != NULL);
    }
    return status;
}

Exam Practice Tool

Practice the exam just like you would in the real exam - https://github.com/JCluzet/42_EXAM

42-school-exam-rank-04's People

Contributors

0bvim avatar cosmic3d avatar cozy-hn avatar dolmalin avatar laendrun avatar lucasopoka avatar maitreverge avatar martinthonon avatar merlot-dev avatar multitudes avatar nargin avatar pasqualerossi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

42-school-exam-rank-04's Issues

can't use pipe

You deleted implementation about pipe in this commit.
So the current program on master branch don't allow us to use pipe for example $>./microshell /bin/ls "|" /usr/bin/grep microshell ";" /bin/echo i love my microshell

Using the `__environ` variable.

it is reported that using the __environ is not allowed in the test.
In general, it's recommended to use environ rather than __environ, because environ is standardized by POSIX and is more portable across different systems. The __environ variable is not standardized and might not be available on all systems.
I would advise to use:

extern char **environ;

which is not a global and it is posix compliant.

Review

A lot of big mistakes in this code, it s odd that the moulinette allowed this to pass :

  • STDIN and STDOUT are not restored at the end of a pipeline, args like ./microshell "/bin/echo" "a" "|" "/bin/cat" "-e" "|" "/bin/wc" "-l" ";" "/bin/cat" will not work correctly (the last cat should read on STDIN).

  • Commands in a pipeline do not work simultaneously, args like ./microshell "/bin/yes" "|" "head" "-n" "20" will result in an infinite loop because the 'head' command will never start and cant sigpipe the first command. You must launch each command of the pipeline before waiting with waitpid.

It's disappointing to promote this kind of program even though the moulinette won't KO it.

Shorter code?

I haven't tried yet, but I think that the line
if (argc > 1)
in main can be omitted. If argc==1 argv[++i] should be null, isn't it?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.