executing commands in own shell - C - c

I have troubles with creating my own shell in C. Here is the code I have so far
#include "interpreter.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <syslog.h>
void readconfig(int *timeout, char *file){
FILE * fp;
char * line = NULL;
size_t len = 0;
char * token;
fp = fopen(CONFIG, "r");
if (fp == NULL)
{
*timeout = DEFAULTTIME;
}
else
{
while ((getline(&line, &len, fp)) != -1){
token = strtok(line, TOKEN);
if ((strcmp(token,TIME_PERIOD) == 0)){
*timeout = atoi(strtok(NULL, TOKEN));
}
if ((strcmp(token,HISTORY)==0)){
strcpy(file,trim_command(strtok(NULL, TOKEN)));
}
}
}
}
int waitPeriod(pid_t pid){
if(pid) {
int stat_val;
pid_t child_pid;
int time = 0;
while(time < TIME_PERIOD){
child_pid = waitpid(pid, &stat_val, WNOHANG);
if (child_pid == pid){
break;
} else if (child_pid == 0) {
time++;
sleep(1);
}
}
if (time == TIME_PERIOD){
printf("Process ended. Execution time was over. \n");
kill(pid, SIGINT);
if (kill(pid, 0) == 0){
kill(pid, SIGKILL);
}
}
if(WIFEXITED(stat_val)) {
return WEXITSTATUS(stat_val);
}
return 0;
} else {
return -1;
}
}
void splitCommand(char ** parameters, char * command, int count){
char * cm = strtok(command, " ");
int i = 0;
while (cm != NULL){
parameters[i] = malloc(strlen(cm) * sizeof(char *));
parameters[i] = cm;
i++;
cm = strtok (NULL, " ");
}
i++;
parameters[i] = NULL;
}
int getParamsCount(char command[]){
int i;
int count = 1;
int com_length = strlen(command);
for(i=0; i<com_length; i++){
if (command[i] == ' '){
count++;
}
}
return count;
}
void getHistory(FILE * history_file, char ** history_commands){
char line[MAX_INPUT];
int i = 0;
int j;
rewind(history_file);
while (fgets(line, MAX_INPUT, history_file)!= NULL){
history_commands[i] = malloc(strlen(line) * sizeof(char *));
history_commands[i] = strdup(line);
for(j=0; j<MAX_INPUT; j++){
if (history_commands[i][j] == '\n'){
history_commands[i][j] = '\0';
break;
}
}
i++;
}
}
int getNumberOfRows(FILE * history_file){
rewind(history_file);
int lines = 0;
char ch;
while(!feof(history_file)){
ch = fgetc(history_file);
if(ch == '\n'){
lines++;
}
}
return lines;
}
void printCommands(char ** history_commands, int lines){
int i = 0;
int j = 0;
for(j = i; j < lines; j++){
printf("[%d] %s\n", j, history_commands[j]);
}
}
int runCommand(pid_t pid, char * command, char ** parameters, int child){
int count = 0;
switch(pid) {
case -1 :
return -1;
case 0 :
count = getParamsCount(command);
parameters = malloc((count+1) * sizeof(char *));
splitCommand(parameters, command, count);
if (strncmp("cd", parameters[0], 2) == 0){
chdir(parameters[1]);
} else {
execvp(parameters[0], parameters[0]);
}
free(parameters);
return 0;
default :
child = waitPeriod(pid);
printf("Child status: %d\n", child);
command[0] = 0;
free(command);
return 0;
}
}
char * trim_command(char * string){
int l = strlen(string);
int i;
for (i = 0; i<l; i++){
if (string[i] == '\n'){
string[i] = '\0';
}
}
return string;
}
int main(){
char * command;
FILE * history;
char cwd[MAX_INPUT];
pid_t pid = 0;
int child = 0;
int number_of_rows = 0;
int count = 0;
char ** history_commands;
char ** parameters[10];
printf(" Safe comand line interpreter \n");
printf(" Type \"quit\" to cancel interpreter or command \n");
printf(" Type \"history\" to show full command history \n");
printf(" Type \"history number\" to execute command from history \n");
printf("________________________________________________________________________________________\n");
sleep(1);
history = fopen(HISTORY, "a+");
if (history == NULL){
printf("Could not open history file\n");
return -1;
}
while(1){
getcwd(cwd, sizeof(cwd));
printf("Command: [%d]%s : ", child, cwd);
command = malloc(MAX_INPUT * sizeof(char *));
fgets(command, MAX_INPUT, stdin);
trim_command(command);
if (strncmp(QUIT, command, 4) == 0) {
fclose(history);
return EXIT_SUCCESS;
} else if (strncmp("history", command, 7) == 0) {
number_of_rows = getNumberOfRows(history);
history_commands = malloc(number_of_rows * sizeof(char *));
getHistory(history, history_commands);
count = getParamsCount(command);
if (strcmp("history", command) == 0){
printf("HISTORY OF COMMANDS\n");
printCommands(history_commands, number_of_rows);
} else {
char * cm = strtok(command, " ");
cm = strtok(NULL, " ");
int x;
x = atoi(cm);
if (x >= number_of_rows){
printf("Command does not exist\n");
continue;
}
command = strdup(history_commands[x]);
count = getParamsCount(command);
trim_command(command);
fprintf(history, "%s\n", command);
pid = fork();
runCommand(pid, command, parameters, child);
}
} else if (command[0] != 0){
fprintf(history, "%s\n", command);
pid = fork();
runCommand(pid, command, parameters, child);
}
}
fclose(history);
return 0;
}
The problem is, it doesn't execute cd command. When I comment malloc and free lines in runCommand method, cd command starts working, but every other command without parameter is not working...
could somebody help me with this?

Related

C program that executes command fails with sleep

I wrote a program that read a bash file line by line and execute its command written inside.
It seems to execute standard command normally (albeit there is not output on the terminal), but when it reads the sleep command, there is an error:
sleep 3: missing operand
Try 'sleep 3 --help' for more information.
char** string_separator(char* string, const char a_delim)
{
char** result = 0;
size_t count = 0;
char* tmp = string;
char* last_dot = 0;
char delimiter[2];
delimiter[0] = a_delim;
delimiter[1] = 0;
while (*tmp)
{
if (a_delim == *tmp)
{
count++;
last_dot = tmp;
}
tmp++;
}
count += last_dot < (string + strlen(string) - 1);
count++;
result = malloc(sizeof(char*) * count);
if (result)
{
size_t idx = 0;
char* token = strtok(string,delimiter);
while (token)
{
assert(idx < count);
*(result + idx++) = strdup(token);
token = strtok(0, delimiter);
}
assert(idx == count - 1);
*(result + idx) = 0;
}
return result;
}
int main(int argc, char *argv[]) {
for (int i = 1; i < argc; i++) {
FILE * fp;
fp = fopen(argv[i], "r");
char buf[100];
int bytes_read = 0;
char * inputCopy = malloc(255 * sizeof(char));
const char delim[] = " ";
while (fgets(buf, sizeof buf, fp) != NULL) {
if (strstr(buffer, "#!/")) {
} else {
char ** strtoken = string_separator(buf, '\n');
char * firstWord = getFirstWord(buf, inputCopy, delim);
pid_t pid;
pid = fork();
if (pid == 0) {
execvpe(firstWord, strtoken, NULL);
exit(1);
} else {
int status;
waitpid(pid, & status, 0);
}
}
}
}
return 0;
}
Why is the program not working with the sleep command?
EDIT: Made the modification in the code such as function definition and indentation, I think the problem might be with the string_separator function, it might not separate the string into char array as expected.

C program runs fine locally, but segfaults on remote server

I have a command line game I wrote that runs properly locally, but segfaults on a remote server. I haven't been able to find out why this is the case.
Local:
Remote:
There clearly is an issue somewhere around where POSSIBLE CONNECTIONS are gathered/displayed.
Here's the full program. This issue may be happening around line 190, as that's where the POSSIBLE CONNECTIONS logic is. I have a feeling it's a problem with my strncpy line, as there is very specific memory manipulation going on there, but I could be wrong.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
struct stat st = {0};
const char * ROOM_NAMES[] = {"Water", "Fire", "Wind", "Earth", "Plasma", "DarkMatter", "Air", "Ice", "Rock", "Lava"};
int i,j;
char directory[20];
char *rooms[7];
int connections[7][7] = {0};
int totalMoves = 0;
char roomChoice[20];
char *movesRecord[100];
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void getRoomChoice() {
fflush(stdin);
scanf("%s", roomChoice);
fflush(stdin);
fflush(stdout);
}
void * getTime(void *arg) {
pthread_mutex_lock(&mutex);
FILE *file = fopen("currentTime.txt", "w");
time_t curtime;
struct tm *loc_time;
curtime = time (NULL);
loc_time = localtime (&curtime);
fprintf(file, "%s\n", asctime (loc_time));
// printf("\n%s\n", asctime (loc_time));
fclose(file);
pthread_mutex_unlock(&mutex);
}
void * createRooms() {
// Create directory
int pid = getpid();
char prefix[] = "eldridgt.";
sprintf(directory, "%s%d", prefix, pid);
if (stat(directory, &st) == -1) {
mkdir(directory, 0700);
}
// Create room files
for(i=0; i<7; i++) {
int random;
char filePath[100];
int connectionArr[10];
memset(connectionArr, 0, sizeof connectionArr);
random = rand() % 10; // Random number 0-9
if (connectionArr[random] == 0) { // If room not used
sprintf(filePath,"%s/%s", directory, ROOM_NAMES[random]);
FILE *file = fopen(filePath, "ab+");
fprintf(file, "ROOM NAME: %s\n", ROOM_NAMES[random]); // Add room name
fclose(file);
rooms[i] = ROOM_NAMES[random];
connectionArr[random] = 1; // Room has been used
}
}
return rooms;
}
void * createConnections() {
for(i=0; i<7; i++) {
int connectionCount = rand() % 4 + 3; // Random number 3-6
int currentCount = 0;
for(j=0; j<7; j++) {
currentCount = currentCount + connections[i][j];
}
while (currentCount < connectionCount+1) {
int random = rand() % 7;
while (random == i) {
random = rand() % 7; // If random == current, reset random
}
// Set connections between both rooms
connections[i][random] = 1;
connections[random][i] = 1;
currentCount++;
}
}
}
void * connectionsToFiles() {
for(i=0; i<7; i++) {
int connectionCount = 1;
for(j=0; j<7; j++) {
if(connections[i][j] == 1) {
char filePath[100];
sprintf(filePath,"%s/%s", directory, rooms[i]);
FILE *file = fopen(filePath, "ab+");
fprintf(file, "CONNECTION %d: %s\n", connectionCount, rooms[j]);
fclose(file);
connectionCount++;
}
}
}
}
void * roomTypesToFiles() {
for(i=0; i<7; i++) {
char filePath[100];
sprintf(filePath,"%s/%s", directory, rooms[i]);
FILE *file = fopen(filePath, "a");
switch(i) {
case 0 :
fprintf(file, "ROOM TYPE: START_ROOM\n");
break;
case 6 :
fprintf(file, "ROOM TYPE: END_ROOM\n");
break;
default :
fprintf(file, "ROOM TYPE: MID_ROOM\n");
}
fclose(file);
}
}
isEndRoom(idx) {
movesRecord[totalMoves - 1] = rooms[idx];
char filePath[100];
sprintf(filePath,"%s/%s", directory, rooms[idx]);
char roomType[20];
int lineNumber = 1;
FILE *file = fopen(filePath, "r");
int totaLines = 0;
char line[256];
while(fgets(line, sizeof line, file) != NULL) {
totaLines++; // Line count of room file
}
fclose(file);
file = fopen(filePath, "r");
while(fgets(line, sizeof line, file) != NULL) {
if(lineNumber == totaLines) {
int length = strlen(line) - 11;
strcpy(roomType, line+11);
roomType[length-1] = '\0';
}
lineNumber++;
}
// Check if this is the end room
if(strncmp(roomType, "END", 3) == 0) {
printf("YOU HAVE FOUND THE END ROOM. CONGRATULATIONS!\n");
printf("YOU TOOK %d STEPS. YOUR PATH TO VICTORY WAS:\n", totalMoves - 1);
for(i=1; i<totalMoves; i++) {
printf("%s\n", movesRecord[i]);
}
return 1; // End was reached
} else {
return 0; // End was not reached
}
}
void * playGame(idx) {
totalMoves++;
printf("\n");
if(isEndRoom(idx)) {
exit(0);
}
while(1) {
char filePath[100];
sprintf(filePath,"%s/%s", directory, rooms[idx]);
FILE *file = fopen(filePath, "r");
int totaLines = 0;
char line[100];
while(fgets(line, sizeof line, file) != NULL) {
totaLines++; // Line count of room file
}
fclose(file);
file = fopen(filePath, "r");
int lineNumber = 0;
char *roomChoices[6][20];
while(fgets(line, sizeof line, file) != NULL) { // Current room name
if(lineNumber == 0) {
char roomName[20];
int length = strlen(line) - 11;
strcpy(roomName, line+11);
roomName[length-1] = '\0';
printf("CURRENT LOCATION: %s\n", roomName);
}
else if(lineNumber == 1) { // First room choice option
printf("POSSIBLE CONNECTIONS: ");
fflush(stdout);
char roomName[20];
int length = strlen(line) - 14;
strcpy(roomName, line+14);
roomName[length-1] = '\0';
printf("%s", roomName);
strcpy(roomChoices[lineNumber - 1], roomName);
}
else if(lineNumber > 1 && lineNumber < totaLines - 1) { // Subsequent room choice options
printf(", ");
fflush(stdout);
char roomName[20];
int length = strlen(line) - 14;
strcpy(roomName, line+14);
roomName[length-1] = '\0';
printf("%s", roomName);
fflush(stdout);
strcpy(roomChoices[lineNumber - 1], roomName);
}
else {
printf(".");
fflush(stdout);
}
lineNumber++;
}
fclose(file);
printf("\nWHERE TO? >");
getRoomChoice(); // Get next room choice
if (strcmp(roomChoice, "time") == 0) {
pthread_t thread;
int rc = pthread_create(&thread, NULL, &getTime, NULL);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
pthread_mutex_lock(&mutex);
sleep(1);
FILE *file = fopen("currentTime.txt", "r");
char currentTime[25];
fgets(currentTime, sizeof currentTime, file);
printf("\n%s\n\n", currentTime);
pthread_mutex_unlock(&mutex);
} else {
for(i=0; i<totaLines-2; i++) {
if(strcmp(roomChoices[i], roomChoice) == 0) {
for(j=0; j<7; j++) {
if(strcmp(rooms[j], roomChoice) == 0) { // If the room is equal to roomChoice
playGame(j); // Make playGame call for new room
}
}
}
}
printf("\nHUH? I DON’T UNDERSTAND THAT ROOM. TRY AGAIN.\n\n");
fflush(stdout);
fflush(stdin);
}
}
}
int main() {
createRooms();
createConnections();
connectionsToFiles();
roomTypesToFiles();
playGame(0);
return 0;
}
I too got segfault and tried to fix the code. Now it did run after some changes.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
#include <memory.h>
struct stat st = {0};
char *ROOM_NAMES[] = {"Water", "Fire", "Wind", "Earth", "Plasma", "DarkMatter", "Air", "Ice", "Rock", "Lava"};
int i, j;
char directory[20];
char *rooms[7];
int connections[7][7] = {0};
int totalMoves = 0;
char roomChoice[20];
char *movesRecord[100];
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void getRoomChoice() {
fflush(stdin);
scanf("%s", roomChoice);
fflush(stdin);
fflush(stdout);
}
void *getTime(void *arg) {
pthread_mutex_lock(&mutex);
FILE *file = fopen("currentTime.txt", "w");
time_t curtime;
struct tm *loc_time;
curtime = time(NULL);
loc_time = localtime(&curtime);
fprintf(file, "%s\n", asctime(loc_time));
// printf("\n%s\n", asctime (loc_time));
fclose(file);
pthread_mutex_unlock(&mutex);
}
void *createRooms() {
// Create directory
int pid = getpid();
char prefix[] = "eldridgt.";
sprintf(directory, "%s%d", prefix, pid);
if (stat(directory, &st) == -1) {
mkdir(directory, 0700);
}
// Create room files
for (i = 0; i < 7; i++) {
int random;
char filePath[100];
int connectionArr[10];
memset(connectionArr, 0, sizeof connectionArr);
random = rand() % 10; // Random number 0-9
if (connectionArr[random] == 0) { // If room not used
sprintf(filePath, "%s/%s", directory, ROOM_NAMES[random]);
FILE *file = fopen(filePath, "ab+");
fprintf(file, "ROOM NAME: %s\n", ROOM_NAMES[random]); // Add room name
fclose(file);
rooms[i] = ROOM_NAMES[random];
connectionArr[random] = 1; // Room has been used
}
}
return rooms;
}
void *createConnections() {
for (i = 0; i < 7; i++) {
int connectionCount = rand() % 4 + 3; // Random number 3-6
int currentCount = 0;
for (j = 0; j < 7; j++) {
currentCount = currentCount + connections[i][j];
}
while (currentCount < connectionCount + 1) {
int random = rand() % 7;
while (random == i) {
random = rand() % 7; // If random == current, reset random
}
// Set connections between both rooms
connections[i][random] = 1;
connections[random][i] = 1;
currentCount++;
}
}
}
void *connectionsToFiles() {
for (i = 0; i < 7; i++) {
int connectionCount = 1;
for (j = 0; j < 7; j++) {
if (connections[i][j] == 1) {
char filePath[100];
sprintf(filePath, "%s/%s", directory, rooms[i]);
FILE *file = fopen(filePath, "ab+");
fprintf(file, "CONNECTION %d: %s\n", connectionCount, rooms[j]);
fclose(file);
connectionCount++;
}
}
}
}
void *roomTypesToFiles() {
for (i = 0; i < 7; i++) {
char filePath[100];
sprintf(filePath, "%s/%s", directory, rooms[i]);
FILE *file = fopen(filePath, "a");
switch (i) {
case 0 :
fprintf(file, "ROOM TYPE: START_ROOM\n");
break;
case 6 :
fprintf(file, "ROOM TYPE: END_ROOM\n");
break;
default :
fprintf(file, "ROOM TYPE: MID_ROOM\n");
}
fclose(file);
}
}
int isEndRoom(int idx) {
movesRecord[totalMoves - 1] = rooms[idx];
char filePath[100];
sprintf(filePath, "%s/%s", directory, rooms[idx]);
char roomType[20];
int lineNumber = 1;
FILE *file = fopen(filePath, "r");
int totaLines = 0;
char line[256];
while (fgets(line, sizeof line, file) != NULL) {
totaLines++; // Line count of room file
}
fclose(file);
file = fopen(filePath, "r");
while (fgets(line, sizeof line, file) != NULL) {
if (lineNumber == totaLines) {
int length = strlen(line) - 11;
strcpy(roomType, line + 11);
roomType[length - 1] = '\0';
}
lineNumber++;
}
// Check if this is the end room
if (strncmp(roomType, "END", 3) == 0) {
printf("YOU HAVE FOUND THE END ROOM. CONGRATULATIONS!\n");
printf("YOU TOOK %d STEPS. YOUR PATH TO VICTORY WAS:\n", totalMoves - 1);
for (i = 1; i < totalMoves; i++) {
printf("%s\n", movesRecord[i]);
}
return 1; // End was reached
} else {
return 0; // End was not reached
}
}
void *playGame(int idx) {
totalMoves++;
printf("\n");
if (isEndRoom(idx)) {
exit(0);
}
while (1) {
char filePath[100];
sprintf(filePath, "%s/%s", directory, rooms[idx]);
FILE *file = fopen(filePath, "r");
int totaLines = 0;
char line[100];
while (fgets(line, sizeof line, file) != NULL) {
totaLines++; // Line count of room file
}
fclose(file);
file = fopen(filePath, "r");
int lineNumber = 0;
char roomChoices[6][20];
while (fgets(line, sizeof line, file) != NULL) { // Current room name
if (lineNumber == 0) {
char roomName[20];
int length = strlen(line) - 11;
strcpy(roomName, line + 11);
roomName[length - 1] = '\0';
printf("CURRENT LOCATION: %s\n", roomName);
} else if (lineNumber == 1) { // First room choice option
printf("POSSIBLE CONNECTIONS: ");
fflush(stdout);
char roomName[20];
int length = strlen(line) - 14;
strcpy(roomName, line + 14);
roomName[length - 1] = '\0';
printf("%s", roomName);
strcpy(roomChoices[lineNumber - 1], roomName);
} else if (lineNumber > 1 && lineNumber < totaLines - 1) { // Subsequent room choice options
printf(", ");
fflush(stdout);
char roomName[20];
int length = strlen(line) - 14;
strcpy(roomName, line + 14);
roomName[length - 1] = '\0';
printf("%s", roomName);
fflush(stdout);
strcpy(roomChoices[lineNumber - 1], roomName);
} else {
printf(".");
fflush(stdout);
}
lineNumber++;
}
fclose(file);
printf("\nWHERE TO? >");
getRoomChoice(); // Get next room choice
if (strcmp(roomChoice, "time") == 0) {
pthread_t thread;
int rc = pthread_create(&thread, NULL, &getTime, NULL);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
pthread_mutex_lock(&mutex);
sleep(1);
FILE *file = fopen("currentTime.txt", "r");
char currentTime[25];
fgets(currentTime, sizeof currentTime, file);
printf("\n%s\n\n", currentTime);
pthread_mutex_unlock(&mutex);
} else {
for (i = 0; i < totaLines - 2; i++) {
if (strcmp(roomChoices[i], roomChoice) == 0) {
for (j = 0; j < 7; j++) {
if (strcmp(rooms[j], roomChoice) == 0) { // If the room is equal to roomChoice
playGame(j); // Make playGame call for new room
}
}
}
}
printf("\nHUH? I DON’T UNDERSTAND THAT ROOM. TRY AGAIN.\n\n");
fflush(stdout);
fflush(stdin);
}
}
}
int main() {
createRooms();
createConnections();
connectionsToFiles();
roomTypesToFiles();
playGame(0);
return 0;
}
Test
rooms
CURRENT LOCATION: Earth
POSSIBLE CONNECTIONS: th, Air, Ice, DarkMatter, Earth, DarkMatter, Earth, Air, DarkMatter, DarkMatter, RT_ROOM.
WHERE TO? >Air
YOU HAVE FOUND THE END ROOM. CONGRATULATIONS!
YOU TOOK 1 STEPS. YOUR PATH TO VICTORY WAS:
Air
Process finished with exit code 0

How to implement history function?

I am new to C programming and currently learning this into a course. I'm facing an issues while trying to practice the below history function.
I'm able to display the shell commands. However, when I type history, the past shell commands are not getting saved into the history buffer.
Can anyone help me to find where I went wrong?
Here is my code:
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#define BUFSIZE 20
#define MAX_WORD_IN_LINE 20
int tokenize(char *str, char **args)
{
int i, argc = 0;
char *token;
token = strtok(str," \t\n");
for(i=0; token!=NULL;i++)
{
args[i] = token;
printf("args[%d] = %s\n", i, args[i]);
token = strtok(NULL, " \t\n");
argc++;
}
return argc;
}
void display_strings(char **p)
{
if (p == NULL) return;
while(*p != NULL){
printf("%s\n",*p);
p++;
}
}
int history(char *hist[], int current){
int i = current;
int hist_num = 1;
do {
if (hist[i]) {
printf("%4d %s\n", hist_num, hist[i]);
hist_num++;
}
i = (i + 1) % BUFSIZE;
} while (i != current);
return 0;
}
int main(void){
char *args[MAX_WORD_IN_LINE];
char buffer[BUFSIZE];
char *hist[BUFSIZE];
int i,current=0;
pid_t pid;
int argc;
for(i=0;i<BUFSIZE;i++)
hist[i]= NULL;
while(1) {
memset(args,0,MAX_WORD_IN_LINE);
printf("osh> ");
fgets(buffer, BUFSIZE, stdin);
argc = tokenize(buffer, args);
//display_strings(args);
// skip on empty command
if (argc == 0) continue;
if (strcmp(args[0],"quit") == 0) break;
else if (strcmp(args[0], "hello") == 0) printf("Hello there. How are you?\n");
else if (strcmp(args[0],"history")==0) history(hist,current);
else {
pid = fork();
if (pid == 0) {
hist[current]=strdup(args[0]);
current++;
execvp(args[0], args);
return 0;
}
You need to make a copy of the string that args[0] points to when you save it in hist. Currently, you're just assigning the pointer to the current args[0], and it will be overwritten by the next command. When you print the history, you'll just get the last command repeatedly. So use:
hist[current] = strdup(args[0]);

WC in C with different child processes [duplicate]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Here is the final result i got so far for a simulator of wc linux command. I have to accomplish an output like this
This is child process 0, the number of lines is x
This is child process 1, the number of words is y
This is child process 2, the number of lines is z
The code i wrote is this one:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
char* concat(char *s1, char *s2)
{
char *result = malloc(strlen(s1)+strlen(s2)+1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
int countLines(FILE *f){
int count = 0;
char ch;
while ((ch = fgetc(f)) != EOF){
if (ch == '\n')
count++;
}
return count;
}
int countWords(FILE *f){
int countW = 0;
char ch;
while ((ch = fgetc(f)) != EOF){
if (ch == ' ')
countW++;
}
return countW;
}
int countChars(FILE *f){
int chars = 0;
char ch;
while ((ch = fgetc(f)) != EOF){
chars++;
}
return chars;
}
int main(int argc, char** argv)
{
int lineCount = 0;
int wordCount = 0;
int charCount = 0;
int n = 3;
int i,status;
int pids[3];
char *theprogram = argv[0];
char *thefile = argv[1];
if ( argc !=2 )
{
printf( "Help: %s filename\n", argv[0]);
}
else{
FILE *file = fopen( argv[1], "r");
if(file == 0){
char *sub = concat(theprogram, ": ");
char *middle = concat(sub, thefile);
perror(middle);
}
else{
for (i = 0; i < n; i++) {
pids[i] = fork();
if ( pids[i] < 0) {
perror("fork");
exit(-1);
} else if (pids[i] == 0) {
if (i==0){
lineCount += countLines(file);
printf("This is child proccess %d, and the number of lines is %d\n", i+1, lineCount);
exit(0);
}
else if (i==1){
wordCount += countWords(file);
printf("This is child proccess %d, and the number of words is %d\n", i+1, wordCount);
exit(0);
}
else {
charCount += countChars(file);
printf("This is child proccess %d, and the number of characters is %d\n", i+1, charCount);
exit(0);
}
}
}
return 0;
}
}
}
This is the actual output i am getting:
% ./a.out mywc.c
This is child proccess 2, and the number of words is 0
This is child proccess 1, and the number of lines is 64
This is child proccess 3, and the number of characters is 0
This is child proccess 3, and the number of characters is 0
This is child proccess 2, and the number of words is 0
This is child proccess 3, and the number of characters is 0
This is child proccess 3, and the number of characters is 0
What am I doing Wrong here? I am very new to C programming so not sure what i am missing.
Thanks.
EDIT
Exited the exit codes but can not get the word count and the character count right now.
The right code for my problem is here:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
char* concat(char *s1, char *s2)
{
char *result = malloc(strlen(s1)+strlen(s2)+1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
int countLines(char *f){
FILE *file = fopen(f, "r");
int count = 0;
char ch;
while ((ch = fgetc(file)) != EOF){
if (ch == '\n')
count++;
}
return count;
}
int countWords(char *f){
char buffer[1];
FILE *file = fopen(f, "r");
int countW = 0;
enum states { WSP, WRD };
int state = WSP;
char last = ' ';
while (read(fileno(file),buffer,1) == 1 )
{
if ( buffer[0]== ' ' || buffer[0] == '\t' || buffer[0]=='\n' )
{
state = WSP;
}
else
{
if ( state == WSP )
{
countW++;
}
state = WRD;
}
last = buffer[0];
}
return countW;
}
int countChars(char *f){
FILE *file = fopen(f, "r");
int chars = 0;
char ch;
while ((ch = fgetc(file))){
if (ch == EOF) break;
chars++;
}
return chars;
}
int main(int argc, char** argv)
{
int lineCount = 0;
int wordCount = 0;
int charCount = 0;
int n = 3;
int i,status;
int pids[3];
char *theprogram = argv[0];
char *thefile = argv[1];
if ( argc !=2 )
{
printf( "Help: %s filename\n", argv[0]);
}
else{
FILE *file = fopen( argv[1], "r");
if(file == 0){
char *sub = concat(theprogram, ": ");
char *middle = concat(sub, thefile);
perror(middle);
}
else{
for (i = 0; i < n; i++) {
pids[i] = fork();
if ( pids[i] < 0) {
perror("fork");
exit(-1);
} else if (pids[i] == 0) {
if (i==0){
lineCount = countLines(argv[1]);
printf("This is child proccess %d, and the number of lines is %d\n", i+1, lineCount);
exit(0);
}
else if (i==1){
wordCount = countWords(argv[1]);
printf("This is child proccess %d, and the number of words is %d\n", i+1, wordCount);
exit(0);
}
else {
charCount += countChars(argv[1]);
printf("This is child proccess %d, and the number of characters is %d\n", i+1, charCount);
exit(0);
}
}
}
return 0;
}
}
}

Char ** function not quite working outside of function

So I have created a char** variable called myargv which should act like an array that stores strings at each index. I have a function that returns a char** to the myargv and the function seems to work fine when I print everything out from within, but when I try to print out stuff from the myargv from main, it doesn't work anymore.... Can anyone help me?
char **findArgs(char *line)
{
int i = 0;
char **temp, *tokTemp;
char **myargv;
tokTemp = strtok(line, " ");
myargv = malloc(sizeof(*myargv));
while (tokTemp != NULL)
{
if (strcmp(tokTemp, ">") == 0 || strcmp(tokTemp, "<") == 0 || strcmp(tokTemp, ">>") == 0)
{
break;
}
else
{
myargv[i] = malloc(strlen(tokTemp) + 1);
//myargv[i] = malloc(sizeof(char)*strlen(tokTemp));
strcpy(myargv[i], tokTemp);
//printf("myargv[%d] = %s \n", i, myargv[i]);
temp = realloc(myargv, (i+2)*sizeof(*myargv));
if (temp != NULL)
{
myargv = temp;
}
tokTemp = strtok(NULL, " ");
i++;
}
}
myargv[i] = NULL;
//printf("myargv[0] = %s\n", myargv[0]);
return myargv;
}
int main(int argc, char *argv[], char *env[])
{
int cmdInt, pid, status, i = 0, ioNumber = 0;
char input[64], lineBUFFER[64], lineBUFFER2[64], lineBUFFER3[64], lineBUFFER4[64], homePath[64], fileName[64], cmdPathFINAL[64];
char *cmd;
char **myargv, **cmdPath;
int myFile;
while(1)
{
printf("command: ");
gets(input);
strcpy(lineBUFFER, input);
strcpy(lineBUFFER2, input);
strcpy(lineBUFFER3, input);
strcpy(lineBUFFER4, input);
cmd = strtok(lineBUFFER3, " ");
cmdInt = findCommand(lineBUFFER2);
ioNumber = ioCheck(lineBUFFER4, fileName);
//printf("ioCheck = %d \n", ioNumber);
//printf("Filename: %s \n", fileName);
myargv = findArgs(lineBUFFER);
//printf("myargv[0] = %s\n", myargv[0]);
findHome(env, homePath);
//printf("Home path = %s\n", homePath);
switch(cmdInt)
{
case 0 :
if (myargv[1] == NULL)
{
chdir(homePath);
}
else
{
//printf("1st argument: %s, 2nd argument: %s, 3rd argument: %s \n", myargv[1], myargv[2], myargv[3]);
chdir(myargv[1]);
}
break;
case 1 :
exit(1);
break;
default :
pid = fork();
if (pid == 0)
{
//printf("Parent %d waits for child %d to die. \n", getpid(), pid);
pid = wait(&status);
printf("dead child = %d, how = %04x \n", pid, status);
exit(100);
}
else
{
ioNumber = ioCheck(lineBUFFER4, fileName);
//printf("ioCheck = %d \n", ioNumber);
//printf("Filename: %s \n", fileName);
cmdPath = getPath2(env);
//printf("cmdPath[0] = %s\n", cmdPath[0]);
findPath(cmd, cmdPath, cmdPathFINAL);
printf("Command Path = %s\n", cmdPathFINAL);
if (ioNumber == 1)
{
close(0);
myFile = open(fileName, O_RDONLY);
}
else if (ioNumber == 2)
{
close(1);
myFile = open(fileName, O_WRONLY|O_CREAT, 0644);
}
else if (ioNumber == 3)
{
close(1);
myFile = open(fileName, O_WRONLY|O_APPEND);
}
execve(cmdPathFINAL, myargv, env);
//printf("child %d dies by exit () \n", getpid());
exit(100);
}
break;
}
}
if (ioNumber == 1 || ioNumber == 2 || ioNumber == 3)
{
close(myFile);
}
return 0;
}
The following works on both Window and SuSE linux 10.4 x86_64 kernel 2.6.16. There are two versions of the parser: getArgs and getArgs2. Didn't give the code a thorough review, but hopefully it will help you.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int getArgs(const char *line, char *args[], int argc)
{
int len, i = 0;
const char* delims = " ";
char *ltok = strdup(line);
char *tok = strtok(ltok, delims);
for (; tok != NULL; i++) {
if (strchr("><|", *tok) != NULL) /* not sure why this test is needed for CLI */
break;
if (args != NULL && i < argc) {
args[i] = strdup(tok);
}
tok = strtok(NULL, delims);
}
free(ltok);
return i;
}
int getArgs2(const char *line, char **args, int argc)
{
int len, i = 0;
const char *p, *q;
const char *delims = " ";
p = line;
while (strchr(delims, *p) != NULL && *p != '\0')
p++;
q = p;
while (strchr(delims, *q) == NULL && *q != '\0')
q++;
for (; q > p; i++) {
if (strchr("><|", *p) != NULL) /* not sure why this test is needed for CLI */
break;
len = q-p;
if (args != NULL && i < argc) {
args[i] = (char *)malloc(len + 1);
strncpy(args[i], p, len)[len] = '\0';
}
p = q;
while (strchr(delims, *p) != NULL && *p != '\0')
p++;
q = p;
while (strchr(delims, *q) == NULL && *q != '\0')
q++;
}
return i;
}
int main(int argc, char *argv[])
{
char line[256], *q;
char **args;
int count, n;
for(;;) {
printf("command: ");
if (fgets(line, sizeof(line)/sizeof(line[0]), stdin) == NULL)
break;
q = line;
while (isspace(*q))
q++;
if (*q == '\0')
break;
while (*q != '\0' && *q != '\n' && *q != '\r')
q++;
*q = '\0';
for(count = 0, q = line; *q != '\0'; q++)
if (*q == ' ')
count++;
printf("Input command: %d character(s), %d space(s) for \"%s\"\n", strlen(line), count, line);
count = getArgs(line, NULL, 0);
if (count > 0) {
args = (char **)malloc(sizeof(char *)*count);
count = getArgs(line, args, count);
} else {
args = NULL;
}
printf("Parsed %d arg(s) from line\n", count);
printf("--------------------------------------\n");
for (n = 0; n < count; n++) {
printf("%d: %s\n", n+1, args[n]);
free(args[n]);
}
free(args);
}
return 0;
}

Resources