• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Program Hangs

Status
Not open for further replies.
Level 37
Joined
Jul 22, 2015
Messages
3,485
[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 77
Joined
Oct 6, 2004
Messages
10,096
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,651
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