- Joined
- Jul 22, 2015
- Messages
- 3,485
[C] Program Hangs
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 !
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, ¤tChar, 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, ¤tChar, 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, ¤tChar, 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, ¤tChar, 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, ¤tChar, 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, ¤tChar, 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: