Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3485720
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 18, 20262026-05-18T10:56:29+00:00 2026-05-18T10:56:29+00:00

My homework assignment is to create a shell (done) with a history function (done)

  • 0

My homework assignment is to create a shell (done) with a history function (done) and then write the history to a file (this is where I am having problems) so that it can be loaded on the next run.

I’m normally a Java person, so I need to look up almost every c function. Anyways, I’m having issues write my string array to the file. For some reason I keep getting weird symbols depending on which encoding I use.
For example, if I run the program and quit immediately, the history file contains:

??_?

If I run ls then quit, the history file contains:

ls
_?

I removed the procedures that aren’t related. Thanks in advance for any pointers. This is day 3 of hairpulling. I’m at my wits end.

#include 
/*Had to use \ so that the includes would show here. */
#include \stdlib.h>
#include \signal.h>
#include \sys/types.h>
#include \unistd.h>
#include \string.h>
#include \errno.h>
/*
* Constant Declarations
*/
#define MAX_LINE 80
#define BUFFER_SIZE 50
#define HIST_SIZE 10

static char buffer[BUFFER_SIZE];
char history[HIST_SIZE][BUFFER_SIZE];
int count = 0;
int caught = 0;
char historyFileLoc[] = "./name.history";

void loadHistory() {
    int i;
    char histCommand[BUFFER_SIZE];

    i = 0;
    FILE *hisFile = fopen(historyFileLoc, "r");

    if( hisFile ) {
        /*If a user edits the history file, only the first ten entries will be loaded */
        while(!feof(hisFile)) {
            if(fscanf(hisFile, "%s\n", histCommand) == 1){
                strcpy(history[i], histCommand);
                i++;
                count++;
            }
        }
    }

    if(hisFile != NULL){
        if(fclose(hisFile) != 0) {
            perror("History file (r) was not closed correctly");
        }
    }
}

void saveHistory() {
    int i;
    char buffer[MAX_LINE];

    FILE *hisFile = fopen(historyFileLoc, "w");

    for(i=0; i < HIST_SIZE; i++){
        if(history[i] != '\0') {
            strcpy(buffer, history[i]);
        /*fwrite(history[i], 1, strlen(history[i]), hisFile);*/
        /*  fputs(history[i], hisFile);*/
            if(buffer != NULL) {
                fprintf(hisFile,"%s\n", buffer);
            }
        }
    }
    if(fclose(hisFile) != 0) {
    perror("History file was not closed correctly");
    }
}


/*
* The main() function presents the prompt "sh>" and then invokes setup(), which waits for the
*  user to enter a command. The contents of the command entered by the user are loaded into the
*  args array. For example, if the user enters ls Ðl at the COMMAND-> prompt, args[0] will be set
*  to the string ls and args[1] will be set to the string Ðl. (By ÒstringÓ, we mean a
*  null-terminated, C-style string variable.)
*/
int main(void) {
    char inputBuffer[MAX_LINE]; /* buffer to hold the command entered */
    int background, status; /* equals 1 if a command is followed by '&' */
    char *args[MAX_LINE / 2 + 1]; /* command line arguments */
    pid_t pid; /* the process's id */
...
}

Dump of history[][]:

./660_Lab04.c.out 

sh ->ls
660_Lab03_Tests.txt             Lab 03 Documentation.docx
660_Lab04.c                 buffer.h
660_Lab04.c.out                 name.history
660__Lab01.c                    main.c
660__Lab03.c                    main_not_mine.c
CSE_660Lab01Documentation.doc

This is where the dump begins minus sh->
sh ->ls
ls
_?
??_?

The rest of my code. loadHistory and saveHistory are before this:


void printHistory() {
    int i;
    int j = 0;
    int histcount = count;

    printf("\n");
    for (i=0; i < HIST_SIZE; i++) {
        printf("%d.   ",histcount); /* Used to print the correct hitory number */
        while (history[i][j] != '\n' && history[i][j] != '\0') {
            printf("%c",history[i][j]);
            j++;
        }
        printf("\n");
        j=0;

        histcount--;
        if(histcount == 0) {
            break;
        }
    }
    printf("\n");
    printf("sh -> ");
}

/* the signal handler function */
void handle_SIGINT() {
    write(STDOUT_FILENO,buffer,strlen(buffer));
    printHistory();
    caught = 1;
}

void setup(char inputBuffer[], char *args[], int *background) {
    int length, /* # of characters in the command line */
        i, /* loop index for accessing inputBuffer array */
        start, /* index where beginning of next command parameter is */
        ct, /* index of where to place the next parameter into args[] */
        k; /* Generic counter */

    ct = 0;

/* read what the user enters on the command line */
    length = read(STDIN_FILENO, inputBuffer, MAX_LINE);

    if(caught == 1) {
        length = read(STDIN_FILENO, inputBuffer, MAX_LINE);
        caught = 0;
    }

/* checks to see if the command is a history retrieval command. If it isn't then add it to the history */
    if((strcmp(inputBuffer, "r\n\0") != 0) && (strncmp(inputBuffer, "r x", 2) != 0) ) {
        for(i= (HIST_SIZE - 1); i>0; i--) {
            strcpy(history[i], history[i-1]);
        }
        strcpy(history[0], inputBuffer);
        count++;
    }
    start = -1;
    if (length == 0) {
        saveHistory();
        exit(0); /* ^d was entered, end of user command stream */
    } else if ((length < 0) && (errno != EINTR)) {
        perror("error reading the command");
        saveHistory();
        exit(-1); /* terminate with error code of -1 */
    }

/* Checks to see if r was entered. If so, it copies the command most recently in the input buffer */
    if(strcmp(inputBuffer, "r\n\0") == 0) {
        strcpy(inputBuffer,history[0]);
        /* Checks to see if r x was entered. If so then it searches for the most recent command that begins with x */   
        } else if(strncmp(inputBuffer, "r x", 2) == 0) {
            for(k=0; k < 10; k++){
                if(inputBuffer[2] == history[k][0]) {
                    strcpy(inputBuffer,history[k]);
                    break;
                }
            }
        }

        length = strlen(inputBuffer);

/* examine every character in the inputBuffer */
        for (i = 0; i < length; i++) {
            switch (inputBuffer[i]) {
                case ' ':
                case '\t': /* argument separators */
                if (start != -1) {
                    args[ct] = &inputBuffer[start]; /* set up pointer */
                    ct++;
                }
                inputBuffer[i] = '\0';
                start = -1;
                break;

                case '\n': /* should be the final char examined */
                if (start != -1) {
                    args[ct] = &inputBuffer[start];
                    ct++;
                }
                inputBuffer[i] = '\0';
                args[ct] = NULL; /* no more arguments to this command */
                break;
                case '&':
                *background = 1;
                inputBuffer[i] = '\0';
                break;

                default: /* some other character */
                if (start == -1) {
                    start = i;
                }
            }
            args[ct] = NULL; /* just in case the input line was > 80 */
        }
    }


/* The main() function presents the prompt "sh->" and then invokes setup(), which waits for the user to enter a command. The contents of the command entered by the user are loaded into the args array. For example, if the user enters ls -l at the COMMAND-> prompt, args[0] will be set to the string ls and args[1] will be set to the string -l. (By string, we mean a null-terminated, C-style string variable.) */
int main(void) {
    char inputBuffer[MAX_LINE]; /* buffer to hold the command entered */
    int background, status; /* equals 1 if a command is followed by '&' */
    char *args[MAX_LINE / 2 + 1]; /* command line arguments */
    pid_t pid; /* the process's id */

/* set up the signal handler */
    struct sigaction handler;
    handler.sa_handler = handle_SIGINT;
    sigaction(SIGINT, &handler, NULL);

    loadHistory();

    while (1) {
        background = 0;

        printf("\nsh ->");
        fflush(0);
        setup(inputBuffer, args, &background); /* get next command */
        fflush(0);
        pid = fork(); /* assign the process id */
        if (pid < 0) {
            fprintf(stderr, "ERROR: Could not properly fork.");
            saveHistory();
            exit(-1); /* unsucessful exit because the fork could not be created */
        } else if (pid == 0) { /* PID was forked successfully */
            status = execvp(*args, args); /* execute the command */
            if (status < 0) {
                fprintf(stderr, "ERROR: Could not execute %s", args[0]);
                saveHistory();
                exit(1);
            }
        } else if (background == 0) { /* if the fork is run in the foreground */
            wait(NULL);
        }
    }

    return EXIT_SUCCESS;
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-18T10:56:30+00:00Added an answer on May 18, 2026 at 10:56 am

    The problem could be that your are not initialising the memory in history before use. Unlike Java, C does not initialise memory when you declare it so the history pointer will be pointing to garbage, not an array of zeroes.

    C has a very different memory model to Java so there are likely to be similar gotchas in the rest of your code. I’d recommend that you read up on how to manage memory in C.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I need to write a function that can read a file, and add all
For a homework assignment, we were required to create a function that took in
As part of a homework assignment, we are supposed to create an array that
I'm working on a homework assignment that asks me to create a calculator that
This is a homework assignment, just for all that want to know. I'm writing
I have a homework assignment that asks to create an order form. The order
Working on a homework assignment and am stuck with this task: Create a loop
This is a homework assignment. I just need a nudge. I'm trying to create
I have two questions about this homework assignment: Write an assembly language program in
My kiddo had a homework assignment to write Blackjack in Java. I helped him

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.