C language + UNIX

profiledkim4741
HW2.zip

cmdfile.txt

sleep 5 ls -latr sleep 3 pwd sleep 1 wc /etc/passwd

CommandNode.c

#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "CommandNode.h" /** *CommandNode.c *The function bodies for a linked list of commands **/ /** Example of linked list initialization in code: //First command node (head of list) headCommand = (CommandNode*)malloc(sizeof(CommandNode)); CreateCommandNode(headCommand, command, index, NULL); index = 1; ..... //Later command nodes while ((linesize = getline(&line, &len, fp)) >= 0) { ... index++; nextCommand1 = (CommandNode*)malloc(sizeof(CommandNode)); CreateCommandNode(nextCommand1, command, index, NULL); InsertCommandAfter(headCommand, nextCommand1); } **/ //create a new command node. usually nextCmd can be NULL and function InsertCommandAfter can be called to insert after head node. void CreateCommandNode(CommandNode* thisNode, char cmd[20][20], int ind, CommandNode* nextCmd) { //this is useful if you store a string (char *): strcpy(thisNode->command, cmd); for (int i = 0; i < 20; i++) for (int j = 0; j < 20; j++) thisNode->command[i][j] = cmd[i][j]; thisNode->index = ind; thisNode->nextCommandPtr = nextCmd; return; } //insert node newNode after thisNode void InsertCommandAfter(CommandNode* thisNode, CommandNode* newNode) { CommandNode* tmpNext = NULL; tmpNext = thisNode->nextCommandPtr; thisNode->nextCommandPtr = newNode; newNode->nextCommandPtr = tmpNext; return; } //get next command node in linked list CommandNode* GetNextCommand(CommandNode* thisNode) { return thisNode->nextCommandPtr; } //find a command based on the pid CommandNode* FindCommand(CommandNode* cmd, int pid) { CommandNode* tmpNext = cmd; while (tmpNext != NULL) { if (tmpNext->PID == pid) { return tmpNext; } tmpNext = tmpNext->nextCommandPtr; } return NULL; }

CommandNode.h

/** *CommandNode.h *The struct for a Command Node and function prototypes for a linked list of commands **/ typedef struct command_struct { char command[20][20]; int index; int PID; int starttime; struct command_struct* nextCommandPtr; } CommandNode; void CreateCommandNode(CommandNode* thisNode, char cmd[20][20], int ind, CommandNode* nextCmd); void InsertCommandAfter(CommandNode* thisNode, CommandNode* newNode); CommandNode* GetNextCommand(CommandNode* thisNode); CommandNode* FindCommand(CommandNode* cmd, int pid);

HWdetails&helperFile/HW_details1.jpg

HWdetails&helperFile/HW_details1_1.jpg

HWdetails&helperFile/read_parse_file.c

#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { FILE * fp; char * line = NULL; size_t len = 0; ssize_t read; char newString[20][20]; int i,j,ctr; fp = fopen("commands.txt", "r"); if (fp == NULL) exit(EXIT_FAILURE); while ((read = getline(&line, &len, fp)) != -1) { printf("---------------------------------------\n"); printf("\n\n Split string by space into words :\n"); printf("Retrieved line of length %zu:\n", read); printf("%s", line); for (int i=0; i<20; i++) for (int j=0; j<20; j++) newString[i][j]=0; j=0; ctr=0; for(i=0;i<=(strlen(line));i++) { // if space or NULL found, assign NULL into newString[ctr] if(line[i]==' '||line[i]=='\0') { newString[ctr][j]='\0'; ctr++; //for next word j=0; //for next word, init index to 0 } else { newString[ctr][j]=line[i]; j++; } } printf("\n Strings or words after split by space are :\n"); for(i=0;i < ctr;i++) printf(" %s\n",newString[i]); } fclose(fp); if (line) free(line); exit(EXIT_SUCCESS); }

HWdetails&helperFile/SampleOutput.jpg

HWdetails&helperFile/shell1_execvp.c

#include "apue.h" #include <sys/wait.h> int main(void) { pid_t pid; int status; char buf[1][5]; char *buf2[6]; buf[0][0] = '.'; buf[0][1] = '.'; buf[0][2] = 0; buf2[0] = "ls"; buf2[1] = "-latr"; buf2[2] = "/etc/passwd"; buf2[3] = (char *)&buf[0][0]; buf2[4] = (char *)0; buf2[5] = (char *)0; if ((pid = fork()) < 0) { err_sys("fork error"); } else if (pid == 0) { /* child */ execvp(buf2[0], buf2); err_ret("couldn't execute: %s", buf2[0]); exit(127); } /* parent */ if ((pid = waitpid(pid, &status, 0)) < 0) err_sys("waitpid error"); printf("DONE "); exit(0); }

HWdetails&helperFile/skeleton_solution.c

//--------------------------- //fork the commands and record the start times CommandNode *headNode; /** This is the beginning of your linked list of CommandNodes **/ .... CommandNode *tmpNode; tmpNode = headNode; while (tmpNode != NULL) { //save the startime! // tmpNode.starttime = starttime pid = fork(); if (pid < 0) { fprintf(stderr, "error forking"); exit(2); } else if (pid == 0) { /*child */ //See shell1_execvp.c for execvp usage execvp(....tmpNode.command); /*executes the command in the specific node */ } else if (pid > 0) { /* parent goes to the next node */ tmpNode.pid = pid; int fdout = open("%d.out", tmpNode.index); int fderr = open("%d.err", tmpNode.index); fprintf(fdout, "Starting command INDEX %d: child PID %d of parent PPID %d.\n", tmpNode.index, pid, getpid() ); tmpNode = tmpNode->nextCommandPtr; } } /*end of while loop */ //--------------------------- //Final while loop: waits until anything has completed, //this will exit (wait returns -1) //when there is no more child process. Then your parent process exits. while((pid = wait(&status)) >= 0) { if(pid > 0) { //finishtime = get the finish time //search your linked list for the node that corresponds to pid //The function FindNode was provided //node=FindNode(pid) //signal handling int fdout = open("%d.out", node.index); int fderr = open("%d.err", node.index); fprintf(stderr, "Process with PID %d terminated.\n", pid); if (WIFEXITED(status)) { fprintf(fderr, "Child %d terminated normally with exit code: %d\n", pid, WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { fprintf(fderr, "Child %d terminated abnormally with signal number: %d\n", pid, WTERMSIG(status)); } // //to compute the elapsed time you subtract //elapsedtime = finishtime - node.start_time //decide if you will restart //if (elapsedtime > 2) { //record the new starttime // node.starttime = new starttime // pid = fork(); // if (pid < 0) //error // else if (pid == 0) { //child //See shell1_execvp.c for execvp usage // execvp(node.cmd); // } else if (pid > 0) { // node.pid = pid; // } } }

time_demo.c

/* Program to demonstrate time taken by function fun() */ #include <stdio.h> #include <time.h> // A function that terminates when enter key is pressed void fun() { printf("fun() starts \n"); printf("Press enter to stop fun \n"); while(1) { if (getchar()) break; } printf("fun() ends \n"); } // The main program calls fun() and measures time taken by fun() int main() { // Calculate the time taken by fun() struct timespec start, finish; double elapsed; clock_t t; t = clock(); clock_gettime(CLOCK_MONOTONIC, &start); printf("start %ld\n", start.tv_sec); fun(); clock_gettime(CLOCK_MONOTONIC, &finish); printf("finish %ld\n", finish.tv_sec); //printf("CLOCKSPERSEC %ld\n", CLOCKS_PER_SEC); //double time_taken = ((double)t)*1000.0/CLOCKS_PER_SEC; // in seconds elapsed = (finish.tv_sec - start.tv_sec); //Alternative with more precision: //elapsed += (finish.tv_nsec - start.tv_nsec) / 1000000000.0; printf("fun() took %f seconds to execute \n", elapsed); return 0; }