All pastes #1470642 Raw Edit

Mine

public text v1 · immutable
#1470642 ·published 2009-06-23 02:21 UTC
rendered paste body
// author OBLiQUE
// copyleft 2009
// simple unix shell skeleton
// p0wnbox.com
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <signal.h>
#include <sys/utsname.h>
#include <sys/wait.h>

#define MAX_STRING 0xfff
#define MAX_ARGS 30

const char *shell_commands[] = {"cd","exit","\0"};

void print_prompt();
int chk_sh_cmds(char *str, char **tok);
void sig_int(const int sig_num);

int main(int argc, char *arg[])
{
    char *tok, buf[MAX_STRING], *args[MAX_ARGS+1];
    int readlen, sh_cmd_num, arg_num, status;
    pid_t pid;

    // register SIGINT signal handler to disable ctrl+c
    if (signal(SIGINT,sig_int)==SIG_ERR)
        fprintf(stderr,"Error! cannot register signal handler!\n");

    print_prompt();

    while (readlen=read(STDIN_FILENO,buf,MAX_STRING)) { // read the line and return the length
        buf[readlen-1]='\0'; // remove \n from the end
        if (sh_cmd_num=chk_sh_cmds(buf,&tok)) { // check if its a shell command
            switch (sh_cmd_num) {
                case 1: // cd
                    chdir(tok); // change directory
                    break;
                case 2: // exit
                    printf("exit\n");
                    exit(EXIT_SUCCESS);
            }
        } else { // if it's not a shell command
            tok=strtok(buf," "); // replace the first space with '\0' and take the tokken
            arg_num=0; // initiliaze the arg_num
            while (tok!=NULL && arg_num<MAX_ARGS) { // repeat until the end of string or until the MAX_ARGS
                args[arg_num]=tok; // put the tokken to the array
                arg_num++; // increase the arg_num
                tok=strtok(NULL," "); // replace the next space with '\0' and take the tokken
            }
            args[arg_num]=NULL; // fill with NULL the last empty argument
            
            if (args[0]!=NULL) { // i there is a command to execute
                if ((pid=fork())<0) { // fork a child and check if it's forked
                    fprintf(stderr,"Error! cannot fork child!\n");
                    exit(EXIT_FAILURE);
                } else if (pid==0) { // if i'm the child
                    execvp(args[0],args); // execute the command
                    // the exec replace its memory with command that executes
                    // so if i get this error means that exec failed
                    fprintf(stderr,"Error! cannot execvp command: %s\n",args[0]);
                    exit(EXIT_FAILURE); // child exit
                }
                // i'm the parent
                if ((pid=waitpid(pid,&status,0)<0)) // wait the child to exit
                    fprintf(stderr,"Error! cannot wait for child!\n");
            }
        }
        print_prompt();
    } // end of while
}

void sig_int(const int sig_num)
{
    printf("\n");
    print_prompt();
}

void print_prompt()
{
    struct utsname s_uname; // uname structure
    char path[PATH_MAX], symbol, *login_name, *dir_name;

    if (getuid()) symbol='$'; // if uid!=0 the symbol is $
    else symbol='#'; // otherwise is #
    uname(&s_uname); // retrieve system information
    login_name=getlogin(); // retrieve login username
    getcwd(path,PATH_MAX); // retrieve path
    dir_name=strrchr(path,'/'); // find the directory name
    printf("%s@%s %s/ %c ",login_name,s_uname.nodename,++dir_name,symbol);
    fflush(stdout); // force to write the buffered data to stdout
}

// this function returns 0 if the command is not a shell command
// otherwise returns the index of the shell command
int chk_sh_cmds(char *str, char **tok)
{
    if (str[0]=='\0') return 0; // if the string is null return 0
    strtok_r(str," ",tok); // find the first space and replace it with '\0'
    int i;
    for (i=0; shell_commands[i][0]!='\0'; i++) // loop until the end of array
        if (!strcmp(str,shell_commands[i])) return i+1; // i is a shell command return i+1
    if (*((*tok)-1)=='\0') *((*tok)-1)=' '; // restore the space
    return 0;
}