• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • It's time for the first HD Modeling Contest of 2025. Join the theme discussion for Hive's HD Modeling Contest #7! Click here to post your idea!

Program Hangs

Status
Not open for further replies.
[C] Program Hangs

PHP:
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
 
#define MAXLINELENGTH 100
#define NUMWORDS 16
#define MAXWORDLENGTH 64
 
extern char **environ;
char line[2][MAXLINELENGTH + 1];
char *words[2][NUMWORDS];
char path[MAXWORDLENGTH];
char *argv[NUMWORDS+1];
int verbose_opt = 0;
int pipe_opt    = 0;
int pfd[2];
int n_words[2];
int status;
 
int getLine(void);
int parse(void);
int excecOk(void);
void execute(void);
 
int
main(int argc, char *argv[])
{
    char *msg;
 
    verbose_opt = 0;
    /* This takes care of the verbose output */
    while(argc > 1 && argv[1][0] == '-') {
        if (!strcmp(argv[1], "-v")) {
            verbose_opt = 1;
            argc--;
            argv++;
            continue;
        }
 
        msg = "Error: unknown option(";
        write(2, msg, strlen(msg));
        write(2, argv[1], strlen(argv[1]));
        msg = ")\n";
        write(2, msg, strlen(msg));
        _exit(1);
    }
 
    /* This takes care of running with not enough arguments */
    if(argc != 1) {
        msg = "Error: too many argument(s)\n";
        write(2, msg, strlen(msg));
        _exit(1);
    }
 
    while(getLine()) {
        if (!parse()) {
            continue;
        }
        else if (pipe_opt) {
            status = pipe(pfd);
            if (status == -1) {
                perror("Failed Piping");
                continue;
            }
        }
        execute();
        pipe_opt = 0;
    }
    write(1, "\n", 1);
    return 0;
}
 
int
getLine(void)
{
    int n, length, gotnb;
    char currentChar;
    int isTerm;
    char *msg;
 
    isTerm = isatty(0);
 
    /* Display the prompt line and read input */
    while(1) {
        if (isTerm) {
            /* Write the prompt character */
            write(1, "# ", 2);
        }
        /* Prepare for new line */
        gotnb = length = 0;
 
        /* Until newline, keep reading characters for the new line. */
        while(1) {
            n = read(0, &currentChar, 1);
 
            /* Check read call result */
            switch (n) {
                case 0: /* EOF */
                    return 0;
                    break;
                case -1: /* Error */
                    perror("Error reading command line");
                    _exit(1);
           }
 
           if(!isTerm) {
               /* If it wasn't from the terminal, write to the screen */
               write(1, &currentChar, 1);
           }
 
           if (currentChar == '\n') {
               break;
           }
 
           if (length >= MAXLINELENGTH) {
               length++;
               continue;
           }
 
           if (currentChar != ' ' && currentChar != '\t') {
               gotnb = 1;
           }
 
           if (currentChar == '|') {
                line[pipe_opt][length - 1] = '\0';
                pipe_opt = 1;
                length = 0;
                n = read(0, &currentChar, 1);
                continue;
            }
            else {
                line[pipe_opt][length++] = currentChar;
            }
        }
 
       if(length >= MAXLINELENGTH) {
           msg = "Input line is too long.\n";
           write(2, msg, strlen(msg));
           continue;
       }
 
       if (gotnb == 0) {
           continue;
       }
 
       line[pipe_opt][length] = '\0';
       return 1;
    }
}
 
int
parse(void)
{
    char *p;
    char *msg;
    int num_commands = (pipe_opt) ? 2 : 1;
 
    for (int i = 0; i < num_commands; i++) {
        n_words[i] = 0;
        // p = strtok(line[i], " \t");
        p = strtok(line[i], " ");
 
        while(p != NULL) {
            if (n_words[i] == NUMWORDS) {
                msg = "Error: too many words.\n";
                write(2, msg, strlen(msg));
                return 0;
            }
 
            if(strlen(p) >= MAXWORDLENGTH) {
                msg = "Error: Word too long.\n";
                write(2, msg, strlen(msg));
                return 0;
            }
 
            // printf("%s\n", p);
            words[i][n_words[i]] = p;
            n_words[i]++;
            p = strtok(NULL, " ");
        }
    }
    return 1;
}
 
int
execOk(int command)
{
    char *p;
    char *pathenv;
 
    if(strchr(words[command][0], '/') != NULL) {
        strcpy(path, words[command][0]);
        return access(path, X_OK);
    }
 
    pathenv = strdup(getenv("PATH"));
    p = strtok(pathenv,":");
 
    while(p != NULL) {
        strcpy(path, p);
        strcat(path, "/");
        strcat(path, words[command][0]);
 
        if(access(path, X_OK) == 0) {
            free(pathenv);
            return 0;
        }
 
        p = strtok(NULL, ":");
    }
 
    free(pathenv);
    return -1;
}
 
void
execute(void)
{
    int status, status2;
    char *msg;
    pid_t child_pid, child_pid2;
 
    if(execOk(0) == 0) {
        switch(status = fork()) {
            printf("%d\n", status);
            case -1:
                perror("Fork #1");
                exit(1);
 
            case 0:
                words[0][n_words[0]] = NULL;
 
                // for (size_t j = 0; j < n_words[0]; j++) {
                //     printf("%s\n", words[0][j]);
                // }
 
                if (pipe_opt) {
                    close(pfd[0]);
                    dup2(pfd[1], STDOUT_FILENO);
                    close(pfd[1]);
                }
 
                status = execve(path, words[0], environ);
                perror("execve");
                _exit(0);
 
            default:
                child_pid = wait(&status);
 
                if (pipe_opt && execOk(1) == 0) {
                    switch (status2 = fork()) {
                        case -1:
                            perror("Fork #2");
                            return;
 
                        case 0:
                            dup2(pfd[0], 0);
                            close(pfd[0]);
                            // close(pfd[1]);
 
                            words[1][n_words[1]] = NULL;
 
                            // for (size_t j = 0; j < n_words[0]; j++) {
                            //     printf("%s\n", words[0][j]);
                            // }
                            status2 = execve(path, words[1], environ);
                            perror("execve2");
                            _exit(0);
 
                        default:
                            child_pid2 = wait(&status2);
                    }
                }
        }
 
 
        if(verbose_opt) {
            char emsg[100];
 
            if(WIFEXITED(status)) {
                sprintf(emsg, "Child process %u exited with status %d.\n", child_pid, WEXITSTATUS(status));
            }
            else {
                sprintf(emsg, "Child process %u did not exit normally.\n", child_pid);
            }
            write(1, emsg, strlen(emsg));
        }
    }
    else {
        msg = "Error: '";
        write(2, msg, strlen(msg));
        write(2, words[0][0], strlen(words[0][0]));
        msg = "' cannot be executed.\n";
        write(2, msg, strlen(msg));
    }
}

PHP:
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
 
#define MAXLINELENGTH 100
#define NUMWORDS 16
#define MAXWORDLENGTH 64
 
extern char **environ;
char line[2][MAXLINELENGTH + 1];
char *words[2][NUMWORDS];
char path[MAXWORDLENGTH];
char *argv[NUMWORDS+1];
int verbose_opt = 0;
int pipe_opt    = 0;
int pfd[2];
int n_words[2];
int status;
 
int getLine(void);
int parse(void);
int excecOk(void);
void execute(void);
 
int
main(int argc, char *argv[])
{
    char *msg;
 
    verbose_opt = 0;
    /* This takes care of the verbose output */
    while(argc > 1 && argv[1][0] == '-') {
        if (!strcmp(argv[1], "-v")) {
            verbose_opt = 1;
            argc--;
            argv++;
            continue;
        }
 
        msg = "Error: unknown option(";
        write(2, msg, strlen(msg));
        write(2, argv[1], strlen(argv[1]));
        msg = ")\n";
        write(2, msg, strlen(msg));
        _exit(1);
    }
 
    /* This takes care of running with not enough arguments */
    if(argc != 1) {
        msg = "Error: too many argument(s)\n";
        write(2, msg, strlen(msg));
        _exit(1);
    }
 
    while(getLine()) {
        if (!parse()) {
            continue;
        }
        else if (pipe_opt) {
            status = pipe(pfd);
            if (status == -1) {
                perror("Failed Piping");
                continue;
            }
        }
        execute();
        pipe_opt = 0;
    }
    write(1, "\n", 1);
    return 0;
}
 
int
getLine(void)
{
    int n, length, gotnb;
    char currentChar;
    int isTerm;
    char *msg;
 
    isTerm = isatty(0);
 
    /* Display the prompt line and read input */
    while(1) {
        if (isTerm) {
            /* Write the prompt character */
            write(1, "# ", 2);
        }
        /* Prepare for new line */
        gotnb = length = 0;
 
        /* Until newline, keep reading characters for the new line. */
        while(1) {
            n = read(0, &currentChar, 1);
 
            /* Check read call result */
            switch (n) {
                case 0: /* EOF */
                    return 0;
                    break;
                case -1: /* Error */
                    perror("Error reading command line");
                    _exit(1);
           }
 
           if(!isTerm) {
               /* If it wasn't from the terminal, write to the screen */
               write(1, &currentChar, 1);
           }
 
           if (currentChar == '\n') {
               break;
           }
 
           if (length >= MAXLINELENGTH) {
               length++;
               continue;
           }
 
           if (currentChar != ' ' && currentChar != '\t') {
               gotnb = 1;
           }
 
           if (currentChar == '|') {
                line[pipe_opt][length - 1] = '\0';
                pipe_opt = 1;
                length = 0;
                n = read(0, &currentChar, 1);
                continue;
            }
            else {
                line[pipe_opt][length++] = currentChar;
            }
        }
 
       if(length >= MAXLINELENGTH) {
           msg = "Input line is too long.\n";
           write(2, msg, strlen(msg));
           continue;
       }
 
       if (gotnb == 0) {
           continue;
       }
 
       line[pipe_opt][length] = '\0';
       return 1;
    }
}
 
int
parse(void)
{
    char *p;
    char *msg;
    int num_commands = (pipe_opt) ? 2 : 1;
 
    for (int i = 0; i < num_commands; i++) {
        n_words[i] = 0;
        // p = strtok(line[i], " \t");
        p = strtok(line[i], " ");
 
        while(p != NULL) {
            if (n_words[i] == NUMWORDS) {
                msg = "Error: too many words.\n";
                write(2, msg, strlen(msg));
                return 0;
            }
 
            if(strlen(p) >= MAXWORDLENGTH) {
                msg = "Error: Word too long.\n";
                write(2, msg, strlen(msg));
                return 0;
            }
 
            // printf("%s\n", p);
            words[i][n_words[i]] = p;
            n_words[i]++;
            p = strtok(NULL, " ");
        }
    }
    return 1;
}
 
int
execOk(int command)
{
    char *p;
    char *pathenv;
 
    if(strchr(words[command][0], '/') != NULL) {
        strcpy(path, words[command][0]);
        return access(path, X_OK);
    }
 
    pathenv = strdup(getenv("PATH"));
    p = strtok(pathenv,":");
 
    while(p != NULL) {
        strcpy(path, p);
        strcat(path, "/");
        strcat(path, words[command][0]);
 
        if(access(path, X_OK) == 0) {
            free(pathenv);
            return 0;
        }
 
        p = strtok(NULL, ":");
    }
 
    free(pathenv);
    return -1;
}
 
void
execute(void)
{
    int status, status2;
    char *msg;
    pid_t child_pid, child_pid2;
 
    if(execOk(0) == 0) {
        switch(status = fork()) {
            printf("%d\n", status);
            case -1:
                perror("Fork #1");
                exit(1);
 
            case 0:
                words[0][n_words[0]] = NULL;
 
                // for (size_t j = 0; j < n_words[0]; j++) {
                //     printf("%s\n", words[0][j]);
                // }
 
                if (pipe_opt) {
                    close(pfd[0]);
                    dup2(pfd[1], STDOUT_FILENO);
                    close(pfd[1]);
                }
 
                status = execve(path, words[0], environ);
                perror("execve");
                _exit(0);
 
            default:
 
                if (pipe_opt && execOk(1) == 0) {
                    switch (status2 = fork()) {
                        case -1:
                            perror("Fork #2");
                            return;
 
                        case 0:
                            dup2(pfd[0], 0);
                            close(pfd[0]);
                             close(pfd[1]);
 
                            words[1][n_words[1]] = NULL;
 
                            status2 = execve(path, words[1], environ);
                            perror("execve2");
                            _exit(0);
 
                    }
                }
        }
        child_pid = wait(&status);
        if(pipe_opt) {
            close(pfd[0]);
            close(pfd[1]);
            child_pid2 = wait(&status2);
        }
 
 
        if(verbose_opt) {
            char emsg[100];
 
            if(WIFEXITED(status)) {
                sprintf(emsg, "Child process %u exited with status %d.\n", child_pid, WEXITSTATUS(status));
            }
            else {
                sprintf(emsg, "Child process %u did not exit normally.\n", child_pid);
            }
            write(1, emsg, strlen(emsg));
 
            if(pipe_opt) {
                if(WIFEXITED(status2)) {
                    sprintf(emsg, "Child process %u exited with status %d.\n", child_pid2, WEXITSTATUS(status));
                }
                else {
                    sprintf(emsg, "Child process %u did not exit normally.\n", child_pid2);
                }
                write(1, emsg, strlen(emsg));
            }
        }
    }
    else {
        msg = "Error: '";
        write(2, msg, strlen(msg));
        write(2, words[0][0], strlen(words[0][0]));
        msg = "' cannot be executed.\n";
        write(2, msg, strlen(msg));
    }
}


Edit: Program was hanging because I forgot to close the file descriptors in main :) program runs fine now !

Edit2: Sorry about just editing everything out and not putting down the solution I found. I never thought about other people who could have had the same problem as me :X Fixed the post to include code and solution !
 
Last edited:

Ralle

Owner
Level 79
Joined
Oct 6, 2004
Messages
10,195
When you make a thread to get help, the existence of the thread is not only for the benefit of yourself. By removing the contents of your first post, you invalidated the entire existence of the thread.

When finding the solution, you should have posted that one too. This way, when people have the same problem, they can find your solution and not need to make a new thread.
 
Level 25
Joined
May 11, 2007
Messages
4,650
Yep, nothing worse than googling for a problem, finding an old thread explaining the problem, reading the posts and then seeing someone:
"Thanks guys I fixed it!"
or
"PM me and I'll give you the answer." :)
 
Status
Not open for further replies.
Top