From 865c69914c57b5a167509ab5bf13ac2f70c85db2 Mon Sep 17 00:00:00 2001 From: pmazdin Date: Tue, 1 Sep 2015 10:14:18 +0200 Subject: [PATCH 1/8] new version of ash.c --- shell/ash.c | 746 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 640 insertions(+), 106 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index c5ad96909..a6d5b666c 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -38,14 +38,17 @@ #define JOBS ENABLE_ASH_JOB_CONTROL #include +#include +#include #include #include #include #include /* for setting $HOSTNAME */ - #include "busybox.h" /* for applet_names */ #include "unicode.h" - +#include +#include +#include #include "shell_common.h" #if ENABLE_SH_MATH_SUPPORT # include "math.h" @@ -371,6 +374,18 @@ extern struct globals_misc *const ash_ptr_to_globals_misc; trap_ptr = trap; \ } while (0) +// CernVM Time Measurement + + +#define CVM_DEBUG_TURNON + +#ifdef CVM_DEBUG_TURNON +#define CVMDEBUG(...) printf(__VA_ARGS__) +#else +#define CVMDEBUG(...) +#endif + + /* ============ DEBUG */ #if DEBUG @@ -438,6 +453,7 @@ static void raise_exception(int e) { #if DEBUG + if (exception_handler == NULL) abort(); #endif @@ -801,6 +817,8 @@ freefunc(struct funcnode *f) } + + /* ============ Debugging output */ #if DEBUG @@ -1220,6 +1238,7 @@ static void ash_vmsg_and_raise(int cond, const char *msg, va_list ap) { #if DEBUG + if (msg) { TRACE(("ash_vmsg_and_raise(%d, \"", cond)); TRACEV((msg, ap)); @@ -1450,6 +1469,7 @@ static void stunalloc(void *p) { #if DEBUG + if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) { write(STDERR_FILENO, "stunalloc\n", 10); abort(); @@ -3388,6 +3408,309 @@ static smallint doing_jobctl; //references:8 static void setjobctl(int); #endif + + +struct heterogeneous_list +{ + int type; // 0 =pid1, 1 = pid2, 2 = start, 3 = end, 4 = string, + void *item; + struct heterogeneous_list *next; +}; + +struct heterogeneous_list *head = NULL; +struct heterogeneous_list *curr = NULL; + +struct heterogeneous_list* create_het_list(int type, int valInt, char *valChar) +{ + struct heterogeneous_list *het_list = (struct heterogeneous_list*)malloc(sizeof(struct heterogeneous_list)); + if(NULL == het_list) + { + return NULL; + } + switch(type) { + case 0: + het_list->type = type; + het_list->item = valInt; + break; + case 1: + het_list->type = type; + het_list->item = valInt; + break; + case 2: + het_list->type = type; + het_list->item = valInt; + break; + case 3: + het_list->type = type; + het_list->item = valInt; + break; + case 4: + het_list->type = type; + het_list->item = valChar; + break; + } + + het_list->next = NULL; + + head = curr = het_list; + return het_list; +} + + + +struct heterogeneous_list* store_het_list(int type, long int valInt, char *valChar) +{ + if(NULL == head) + { + return (create_het_list(type,valInt,valChar)); + } + + struct heterogeneous_list *het_list = (struct heterogeneous_list*)malloc(sizeof(struct heterogeneous_list)); + if(NULL == het_list) + { + return NULL; + } + + switch(type) { + + case 0: + het_list->type = type; + het_list->item = valInt; + break; + case 1: + het_list->type = type; + het_list->item = valInt; + break; + case 2: + het_list->type = type; + het_list->item = valInt; + break; + case 3: + het_list->type = type; + het_list->item = valInt; + break; + case 4: + het_list->type = type; + het_list->item = valChar; + break; + } + + + het_list->next = NULL; + + + curr->next = het_list; + curr = het_list; + + return het_list; +} + + + + +// int delete_from_list(int val) +// { +// struct test_struct *prev = NULL; +// struct test_struct *del = NULL; + +// printf("\n Deleting value [%d] from list\n",val); + +// del = search_in_list(val,&prev); +// if(del == NULL) +// { +// return -1; +// } +// else +// { +// if(prev != NULL) +// prev->next = del->next; + +// if(del == curr) +// { +// curr = prev; +// } +// else if(del == head) +// { +// head = del->next; +// } +// } + +// free(del); +// del = NULL; + +// return 0; +// } + + + + +// struct heterogeneous_list* analize_het_list(void) { + +// struct heterogeneous_list* het_list = head; + +// while(het_list != NULL) +// { + +// if(het_list->type != 4 && het_list->item == -1) { + +// het_list = delete_from_list() + +// } +// else het_list = het_list->next; + + +// } + +// return het_list; +// } + + + + + + + // int findMin(int current, int new) { + + // if (new >= current && current != -2 && current != -1 || new == -1) return current; + // else return new; + + // } + + +void print_het_list(void) +{ + struct heterogeneous_list* het_list = head; + + //printf("enter print\n"); + while(het_list != NULL) + { + //printf("type: %d\n", het_list->type); + //printf("enter while print\n"); + switch(het_list->type) { + case 0: + //printf("enter int print\n"); + //CVMDEBUG("\n %d \n",het_list->item); + het_list = het_list->next; + break; + case 1: + //CVMDEBUG("\n %d \n",het_list->item); + het_list = het_list->next; + break; + case 2: + //printf("enter int print\n"); + //CVMDEBUG("\n %d \n",het_list->item); + het_list = het_list->next; + break; + case 3: + //CVMDEBUG("\n %d \n",het_list->item); + het_list = het_list->next; + break; + case 4: + //printf("enter int print\n"); + //CVMDEBUG("\n %s \n",het_list->item); + het_list = het_list->next; + break; + + } + + } + return; + +} + + +int hetListLength(void) +{ + struct heterogeneous_list* het_list = head; + int size = 0; + + while (het_list != NULL) + { + ++size; + het_list = het_list->next; + } + + return size; +} + + + +void create_marks_csv(FILE *fp){ + + struct heterogeneous_list *het_list = head; + //int valueInt[4] = {0}; + long int valueInt; + char *command; + //CVMDEBUG(" yeeeeeeeeeeeeeeeeeees"); + // printf(" problem \n"); + fprintf(fp,"command!start!pid!end\n");// + // if (retval < 1) + // abort(); + + //fprintf(fp, "Dumping marks PID %d ptr %x\n", getpid(), ptr); + + //int i = 0; + //int j = 0; + + while (het_list != NULL) + { + + switch(het_list->type) { + + case 0: + valueInt = het_list->item; + het_list = het_list->next; + if (valueInt == NULL) valueInt = 0; + fprintf(fp,"!%ld\n", valueInt); + break; + case 1: + valueInt = het_list->item; + het_list = het_list->next; + if (valueInt == NULL) valueInt = 0; + fprintf(fp,"!!%ld", valueInt); + break; + case 2: + valueInt = het_list->item; + het_list = het_list->next; + if (valueInt == NULL) valueInt = 0; + fprintf(fp,"!%ld", valueInt); + break; + case 3: + valueInt = het_list->item; + het_list = het_list->next; + if (valueInt == NULL) valueInt = 0; + fprintf(fp,"!%ld\n", valueInt); + break; + + case 4: + //command = malloc(strlen(het_list->item) + 2 + 1); + //command[0] = 0; + //command = strcat(command, "\""); + //command = strcat(command, het_list->item); + //command = strcat(command, "\""); + command = het_list->item; + het_list = het_list->next; + //i+=1; + if (command == NULL) command = ""; + fprintf(fp,"%s", command); + + break; + } + + //if(i==5) + //{ + + //fprintf(fp, "\n%d!%s!%d", valueInt[1], command, valueInt[0]); // + //fprintf(fp, "\n%d!!!%d", valueInt[2],valueInt[3]); + //i = 0; + //j = 0; + + //} + + } + } + + /* * Ignore a signal. */ @@ -3447,9 +3770,11 @@ setsignal(int signo) new_act = S_CATCH; break; case SIGQUIT: -#if DEBUG - if (debug) +#if DEBUG + if (debug) { + break; + } #endif /* man bash: * "In all cases, bash ignores SIGQUIT. Non-builtin @@ -3969,7 +4294,9 @@ dowait(int wait_flags, struct job *job) * NB: _not_ safe_waitpid, we need to detect EINTR */ if (doing_jobctl) wait_flags |= WUNTRACED; + pid = waitpid(-1, &status, wait_flags); + TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", pid, status, errno, strerror(errno))); if (pid <= 0) @@ -4043,6 +4370,10 @@ dowait(int wait_flags, struct job *job) out2str(s); } } + + //add_to_list(pid, true); + //printf("store pid\n"); + //store_het_list(0,pid, ""); return pid; } @@ -4508,6 +4839,7 @@ cmdtxt(union node *n) switch (n->type) { default: #if DEBUG + abort(); #endif case NPIPE: @@ -4714,6 +5046,7 @@ forkchild(struct job *jp, union node *n, int mode) oldlvl = shlvl; shlvl++; + /* man bash: "Non-builtin commands run by bash have signal handlers * set to the values inherited by the shell from its parent". * Do we do it correctly? */ @@ -4771,6 +5104,7 @@ forkchild(struct job *jp, union node *n, int mode) /* do job control only in root shell */ doing_jobctl = 0; if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) { + pid_t pgrp; if (jp->nprocs == 0) @@ -4834,14 +5168,19 @@ forkchild(struct job *jp, union node *n, int mode) static void forkparent(struct job *jp, union node *n, int mode, pid_t pid) { + TRACE(("In parent shell: child = %d\n", pid)); + if (!jp) { while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0) + continue; jobless++; + return; } -#if JOBS +#if JOBS + if (mode != FORK_NOJOB && jp->jobctl) { int pgrp; @@ -4851,6 +5190,7 @@ forkparent(struct job *jp, union node *n, int mode, pid_t pid) pgrp = jp->ps[0].ps_pid; /* This can fail because we are doing it in the child also */ setpgid(pid, pgrp); + } #endif if (mode == FORK_BG) { @@ -4863,7 +5203,8 @@ forkparent(struct job *jp, union node *n, int mode, pid_t pid) ps->ps_status = -1; ps->ps_cmd = nullstr; #if JOBS - if (doing_jobctl && n) + //if (doing_jobctl && n) + if (n) ps->ps_cmd = commandtext(n); #endif } @@ -4876,104 +5217,33 @@ forkshell(struct job *jp, union node *n, int mode) TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode)); pid = fork(); + if (pid < 0) { TRACE(("Fork failed, errno=%d", errno)); if (jp) freejob(jp); ash_msg_and_raise_error("can't fork"); + } if (pid == 0) { CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */ forkchild(jp, n, mode); + } else { forkparent(jp, n, mode, pid); + } return pid; } -/* - * Wait for job to finish. - * - * Under job control we have the problem that while a child process - * is running interrupts generated by the user are sent to the child - * but not to the shell. This means that an infinite loop started by - * an interactive user may be hard to kill. With job control turned off, - * an interactive user may place an interactive program inside a loop. - * If the interactive program catches interrupts, the user doesn't want - * these interrupts to also abort the loop. The approach we take here - * is to have the shell ignore interrupt signals while waiting for a - * foreground process to terminate, and then send itself an interrupt - * signal if the child process was terminated by an interrupt signal. - * Unfortunately, some programs want to do a bit of cleanup and then - * exit on interrupt; unless these processes terminate themselves by - * sending a signal to themselves (instead of calling exit) they will - * confuse this approach. - * - * Called with interrupts off. - */ -static int -waitforjob(struct job *jp) -{ - int st; - TRACE(("waitforjob(%%%d) called\n", jobno(jp))); - INT_OFF; - while (jp->state == JOBRUNNING) { - /* In non-interactive shells, we _can_ get - * a keyboard signal here and be EINTRed, - * but we just loop back, waiting for command to complete. - * - * man bash: - * "If bash is waiting for a command to complete and receives - * a signal for which a trap has been set, the trap - * will not be executed until the command completes." - * - * Reality is that even if trap is not set, bash - * will not act on the signal until command completes. - * Try this. sleep5intoff.c: - * #include - * #include - * int main() { - * sigset_t set; - * sigemptyset(&set); - * sigaddset(&set, SIGINT); - * sigaddset(&set, SIGQUIT); - * sigprocmask(SIG_BLOCK, &set, NULL); - * sleep(5); - * return 0; - * } - * $ bash -c './sleep5intoff; echo hi' - * ^C^C^C^C <--- pressing ^C once a second - * $ _ - * $ bash -c './sleep5intoff; echo hi' - * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT) - * $ _ - */ - dowait(DOWAIT_BLOCK, jp); - } - INT_ON; - st = getstatus(jp); -#if JOBS - if (jp->jobctl) { - xtcsetpgrp(ttyfd, rootpid); - /* - * This is truly gross. - * If we're doing job control, then we did a TIOCSPGRP which - * caused us (the shell) to no longer be in the controlling - * session -- so we wouldn't have seen any ^C/SIGINT. So, we - * intuit from the subprocess exit status whether a SIGINT - * occurred, and if so interrupt ourselves. Yuck. - mycroft - */ - if (jp->sigint) /* TODO: do the same with all signals */ - raise(SIGINT); /* ... by raise(jp->sig) instead? */ - } - if (jp->state == JOBDONE) -#endif - freejob(jp); - return st; -} + + + + + /* * return 1 if there are stopped jobs, otherwise 0 @@ -5152,7 +5422,8 @@ openredirect(union node *redir) goto ecreate; break; default: -#if DEBUG +#if DEBUG + abort(); #endif /* Fall through to eliminate warning. */ @@ -5887,11 +6158,13 @@ evalbackcmd(union node *n, struct backcmd *result) close(pip[1]); result->fd = pip[0]; result->jp = jp; + } herefd = saveherefd; out: TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n", result->fd, result->buf, result->nleft, result->jp)); + } /* @@ -7426,12 +7699,17 @@ static int builtinloc = -1; /* index in path of %builtin, or -1 */ static void tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp) { + #if ENABLE_FEATURE_SH_STANDALONE + if (applet_no >= 0) { + if (APPLET_IS_NOEXEC(applet_no)) { + clearenv(); while (*envp) putenv(*envp++); + run_applet_no_and_exit(applet_no, argv); } /* re-exec ourselves with the new arguments */ @@ -7439,15 +7717,34 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char ** /* If they called chroot or otherwise made the binary no longer * executable, fall through */ } + #endif - repeat: +repeat: + #ifdef SYSV do { + execve(cmd, argv, envp); } while (errno == EINTR); -#else +#else + + //if(strcmp("/bin/dumpstat", cmd) == 0) { + + //char filename[25]; + //snprintf(filename, 25, "/root/busybox/collect_data.py"); + //FILE *fp = fopen(filename, "w+"); + //if (fp == NULL) { + //CVMDEBUG("ERROR CREATING %s %d", filename, errno); + // abort(); + //} + //fprintf(fp,"jojojojo \n"); + //fclose(fp); + //} execve(cmd, argv, envp); + + + #endif if (cmd == (char*) bb_busybox_exec_path) { /* We already visited ENOEXEC branch below, don't do it again */ @@ -7475,20 +7772,29 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char ** char **ap; char **new; - for (ap = argv; *ap; ap++) - continue; + for (ap = argv; *ap; ap++) { + continue; } new = ckmalloc((ap - argv + 2) * sizeof(new[0])); new[0] = (char*) "ash"; new[1] = cmd; ap = new + 2; - while ((*ap++ = *++argv) != NULL) - continue; + while ((*ap++ = *++argv) != NULL) { + continue; } cmd = (char*) bb_busybox_exec_path; - argv = new; + argv = new; goto repeat; } } + + + + + +/* + +*/ + /* * Exec a program. Never returns. If you change this routine, you may * have to change the find_command routine as well. @@ -7516,6 +7822,7 @@ shellexec(char **argv, const char *path, int idx) * Maybe /proc/self/exe doesn't exist? * Try $PATH search. */ + goto try_PATH; } e = errno; @@ -7523,15 +7830,19 @@ shellexec(char **argv, const char *path, int idx) try_PATH: e = ENOENT; while ((cmdname = path_advance(&path, argv[0])) != NULL) { + if (--idx < 0 && pathopt == NULL) { tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp); + if (errno != ENOENT && errno != ENOTDIR) e = errno; - } - stunalloc(cmdname); - } + + + } + stunalloc(cmdname); + } } - + /* Map to POSIX errors */ switch (e) { case EACCES: @@ -7549,6 +7860,8 @@ shellexec(char **argv, const char *path, int idx) argv[0], e, suppress_int)); ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found")); /* NOTREACHED */ + + } static void @@ -7920,6 +8233,7 @@ describe_command(char *command, int describe_command_verbose) } else { do { p = path_advance(&path, command); + stunalloc(p); } while (--j >= 0); } @@ -7956,13 +8270,198 @@ describe_command(char *command, int describe_command_verbose) if (describe_command_verbose) { out1str(": not found\n"); } + return 127; } out: out1str("\n"); + return 0; } + +/* + * Wait for job to finish. + * + * Under job control we have the problem that while a child process + * is running interrupts generated by the user are sent to the child + * but not to the shell. This means that an infinite loop started by + * an interactive user may be hard to kill. With job control turned off, + * an interactive user may place an interactive program inside a loop. + * If the interactive program catches interrupts, the user doesn't want + * these interrupts to also abort the loop. The approach we take here + * is to have the shell ignore interrupt signals while waiting for a + * foreground process to terminate, and then send itself an interrupt + * signal if the child process was terminated by an interrupt signal. + * Unfortunately, some programs want to do a bit of cleanup and then + * exit on interrupt; unless these processes terminate themselves by + * sending a signal to themselves (instead of calling exit) they will + * confuse this approach. + * + * Called with interrupts off. + */ + int counter = 0; +static int +waitforjob(struct job *jp) +{ + int st; + + TRACE(("waitforjob(%%%d) called\n", jobno(jp))); + + INT_OFF; + + while (jp->state == JOBRUNNING) { + /* In non-interactive shells, we _can_ get + * a keyboard signal here and be EINTRed, + * but we just loop back, waiting for command to complete. + * + * man bash: + * "If bash is waiting for a command to complete and receives + * a signal for which a trap has been set, the trap + * will not be executed until the command completes." + * + * Reality is that even if trap is not set, bash + * will not act on the signal until command completes. + * Try this. sleep5intoff.c: + * #include + * #include + * int main() { + * sigset_t set; + * sigemptyset(&set); + * sigaddset(&set, SIGINT); + * sigaddset(&set, SIGQUIT); + * sigprocmask(SIG_BLOCK, &set, NULL); + * sleep(5); + * return 0; + * } + * $ bash -c './sleep5intoff; echo hi' + * ^C^C^C^C <--- pressing ^C once a second + * $ _ + * $ bash -c './sleep5intoff; echo hi' + * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT) + * $ _ + */ + + + // START // + + int n = jp->nprocs; + + // printf("number of processes: %d\n", n); + + for (int j = 0; j < n; j++) { + + //printf("J: %d\n", j); + struct procstat *ps = &jp->ps[j]; + /* Skip non-running and not-stopped members + * (i.e. dead members) of the job + */ + //if (ps->ps_status == -1) + struct timeval time11; + long int intWait; + if (gettimeofday(&time11,NULL)){ + // Handle error + } + //double waitStartTime = (double)time11.tv_sec + (double)time11.tv_usec * .000001; + long int usecWait = time11.tv_sec * 1000000 + time11.tv_usec; + + + if (ps->ps_status == -1) { + intWait = usecWait; + } + else { + intWait = -1; + } + + char *command = ckstrdup(ps->ps_cmd); + store_het_list(4,0,command); + store_het_list(2,intWait, ""); + store_het_list(0,ps->ps_pid, ""); + + //printf("pid: %d, command: %s, status: %d, start: %d\n", ps->ps_pid, ps->ps_cmd, ps->ps_status, intWait); + + //find minim start time depending on pid: store pid, store start time, store command + + } + + + + dowait(DOWAIT_BLOCK, jp); + + // END // + + int m = jp->nprocs; + // int arrayEnd[m][2]; + + // for (int k = 0; k < m; k++) { + // for (int l = 0; l < 2; l++) { + // arrayEnd[k][l] = -2; + // } + // } + + + for (int k = 0; k < m; k++) { + + //printf("K: %d\n", k); + struct procstat *ps = &jp->ps[k]; + /* Skip non-running and not-stopped members + * (i.e. dead members) of the job + */ + //if (ps->ps_status == -1) + long int intDone; + struct timeval time3; + if (gettimeofday(&time3,NULL)){ + // Handle error + } + //int microseconds = time3.tv_sec * 1000000 + time3.tv_usec; + double pidRealEndTime = (double)time3.tv_sec + (double)time3.tv_usec * .000001; + + long int usecDone = time3.tv_sec * 1000000 + time3.tv_usec; + if (ps->ps_status != -1) { + intDone = usecDone; + } + else { + intDone = -1; + } + //printf("pid: %d, command: %s, status: %d, end: %d\n", ps->ps_pid, ps->ps_cmd, ps->ps_status, intDone); + + + store_het_list(1,ps->ps_pid, ""); + store_het_list(3,intDone, ""); + + + //find minim end time depending on pid: store pid, store end time, store command + + } + + + + } + INT_ON; + + st = getstatus(jp); +#if JOBS + if (jp->jobctl) { + xtcsetpgrp(ttyfd, rootpid); + /* + * This is truly gross. + * If we're doing job control, then we did a TIOCSPGRP which + * caused us (the shell) to no longer be in the controlling + * session -- so we wouldn't have seen any ^C/SIGINT. So, we + * intuit from the subprocess exit status whether a SIGINT + * occurred, and if so interrupt ourselves. Yuck. - mycroft + */ + if (jp->sigint) /* TODO: do the same with all signals */ + raise(SIGINT); /* ... by raise(jp->sig) instead? */ + } + if (jp->state == JOBDONE) + +#endif + freejob(jp); + + return st; +} + static int FAST_FUNC typecmd(int argc UNUSED_PARAM, char **argv) { @@ -8663,6 +9162,7 @@ evalsubshell(union node *n, int flags) redirect(n->nredir.redirect, 0); evaltreenr(n->nredir.n, flags); /* never returns */ + //CVMDEBUG("evalsubshell line 8694\n"); } status = 0; if (!backgnd) @@ -8769,6 +9269,7 @@ evalpipe(union node *n, int flags) } if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) { INT_ON; + //CVMDEBUG("evalpipe line 8795\n"); if (pip[1] >= 0) { close(pip[0]); } @@ -8782,6 +9283,8 @@ evalpipe(union node *n, int flags) } evaltreenr(lp->n, flags); /* never returns */ + + } if (prevfd >= 0) close(prevfd); @@ -9426,17 +9929,17 @@ evalcommand(union node *cmd, int flags) INT_OFF; jp = makejob(/*cmd,*/ 1); if (forkshell(jp, cmd, FORK_FG) != 0) { - /* parent */ exitstatus = waitforjob(jp); INT_ON; TRACE(("forked child exited with %d\n", exitstatus)); break; } /* child */ - FORCE_INT_ON; - /* fall through to exec'ing external program */ + FORCE_INT_ON; } + listsetvar(varlist.list, VEXPORT|VSTACK); + shellexec(argv, path, cmdentry.u.index); /* NOTREACHED */ } /* default */ @@ -10348,7 +10851,7 @@ setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) return showvars(nullstr, 0, VUNSET); INT_OFF; - retval = options(/*cmdline:*/ 0); + retval = options(0); /*cmdline:*/ if (retval == 0) { /* if no parse error... */ optschanged(); if (*argptr != NULL) { @@ -11985,6 +12488,7 @@ readtoken(void) { int t; #if DEBUG + smallint alreadyseen = tokpushback; #endif @@ -12037,6 +12541,7 @@ readtoken(void) out: checkkwd = 0; #if DEBUG + if (!alreadyseen) TRACE(("token '%s' %s\n", tokname_array[t] + 1, t == TWORD ? wordtext : "")); else @@ -12215,6 +12720,7 @@ cmdloop(int top) } n = parsecmd(inter); #if DEBUG + if (DEBUG > 2 && debug && (n != NODE_EOF)) showtree(n); #endif @@ -12407,6 +12913,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) switch (cmdp->cmdtype) { default: #if DEBUG + abort(); #endif case CMDNORMAL: @@ -12681,6 +13188,13 @@ exportcmd(int argc UNUSED_PARAM, char **argv) char *name; const char *p; char **aptr; + + + + + + + char opt; int flag; int flag_off; @@ -12986,6 +13500,17 @@ exitshell(void) char *p; int status; + + char filename[25]; + snprintf(filename, 25, "/scores.csv.%d", getpid()); + FILE *fp = fopen(filename, "w+"); + if (fp == NULL) { + //CVMDEBUG("ERROR CREATING %s %d", filename, errno); + abort(); + } + create_marks_csv(fp); + fclose(fp); + #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT save_history(line_input_state); #endif @@ -13043,6 +13568,7 @@ init(void) } setvar2("PPID", utoa(getppid())); + #if ENABLE_ASH_BASH_COMPAT p = lookupvar("SHLVL"); setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT); @@ -13096,7 +13622,7 @@ procargs(char **argv) for (i = 0; i < NOPTS; i++) optlist[i] = 2; argptr = xargv; - if (options(/*cmdline:*/ 1)) { + if (options(1)) { /*cmdline:*/ /* it already printed err message */ raise_exception(EXERROR); } @@ -13203,6 +13729,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) INIT_G_misc(); INIT_G_memstack(); INIT_G_var(); + #if ENABLE_ASH_ALIAS INIT_G_alias(); #endif @@ -13211,7 +13738,6 @@ int ash_main(int argc UNUSED_PARAM, char **argv) #if PROFILE monitor(4, etext, profile_buf, sizeof(profile_buf), 50); #endif - #if ENABLE_FEATURE_EDITING line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP); #endif @@ -13226,9 +13752,11 @@ int ash_main(int argc UNUSED_PARAM, char **argv) if (e == EXERROR) exitstatus = 2; s = state; - if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) { + + if (e == EXEXIT || shlvl || s == 0 || iflag == 0) { exitshell(); } + if (e == EXINT) { outcslow('\n', stderr); } @@ -13245,6 +13773,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) } exception_handler = &jmploc; #if DEBUG + opentrace(); TRACE(("Shell args: ")); trace_puts_args(argv); @@ -13273,6 +13802,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) } state2: state = 3; + if ( #ifndef linux getuid() == geteuid() && getgid() == getegid() && @@ -13296,7 +13826,6 @@ int ash_main(int argc UNUSED_PARAM, char **argv) // in is_hidden_fd() to not be considered "hidden fd" evalstring(minusc, 0); } - if (sflag || minusc == NULL) { #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY if (iflag) { @@ -13318,12 +13847,16 @@ int ash_main(int argc UNUSED_PARAM, char **argv) # endif } #endif + state4: /* XXX ??? - why isn't this before the "if" statement */ + cmdloop(1); } + #if PROFILE monitor(0); #endif + #ifdef GPROF { extern void _mcleanup(void); @@ -13333,6 +13866,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) TRACE(("End of main reached\n")); exitshell(); /* NOTREACHED */ + } From 6a15c77c74bcf7bb5ba6130dffcf5a5a1244dda3 Mon Sep 17 00:00:00 2001 From: pmazdin Date: Tue, 1 Sep 2015 12:15:24 +0200 Subject: [PATCH 2/8] new version of ash.c --- shell/ash.c | 566 ++++++++++++---------------------------------------- 1 file changed, 123 insertions(+), 443 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index a6d5b666c..53b858d82 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -44,8 +44,10 @@ #include #include #include /* for setting $HOSTNAME */ + #include "busybox.h" /* for applet_names */ #include "unicode.h" + #include #include #include @@ -374,18 +376,6 @@ extern struct globals_misc *const ash_ptr_to_globals_misc; trap_ptr = trap; \ } while (0) -// CernVM Time Measurement - - -#define CVM_DEBUG_TURNON - -#ifdef CVM_DEBUG_TURNON -#define CVMDEBUG(...) printf(__VA_ARGS__) -#else -#define CVMDEBUG(...) -#endif - - /* ============ DEBUG */ #if DEBUG @@ -452,8 +442,7 @@ static void raise_exception(int) NORETURN; static void raise_exception(int e) { -#if DEBUG - +#if DEBUG if (exception_handler == NULL) abort(); #endif @@ -817,8 +806,6 @@ freefunc(struct funcnode *f) } - - /* ============ Debugging output */ #if DEBUG @@ -1237,8 +1224,7 @@ static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN; static void ash_vmsg_and_raise(int cond, const char *msg, va_list ap) { -#if DEBUG - +#if DEBUG if (msg) { TRACE(("ash_vmsg_and_raise(%d, \"", cond)); TRACEV((msg, ap)); @@ -1468,8 +1454,7 @@ stzalloc(size_t nbytes) static void stunalloc(void *p) { -#if DEBUG - +#if DEBUG if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) { write(STDERR_FILENO, "stunalloc\n", 10); abort(); @@ -3408,11 +3393,13 @@ static smallint doing_jobctl; //references:8 static void setjobctl(int); #endif - - +// list of 5 possible items where integer value 'type' +// refers to: 0 = start pid, 1 = end pid, 2 = start time, +// 3 = end time, 4 = command; +// and 'item' pointer whose type is not fixed. struct heterogeneous_list { - int type; // 0 =pid1, 1 = pid2, 2 = start, 3 = end, 4 = string, + int type; void *item; struct heterogeneous_list *next; }; @@ -3420,7 +3407,7 @@ struct heterogeneous_list struct heterogeneous_list *head = NULL; struct heterogeneous_list *curr = NULL; -struct heterogeneous_list* create_het_list(int type, int valInt, char *valChar) +struct heterogeneous_list* create_het_list(int type, long int valInt, char *valChar) { struct heterogeneous_list *het_list = (struct heterogeneous_list*)malloc(sizeof(struct heterogeneous_list)); if(NULL == het_list) @@ -3428,31 +3415,31 @@ struct heterogeneous_list* create_het_list(int type, int valInt, char *valChar) return NULL; } switch(type) { - case 0: + case 0: //start pid, type long integer het_list->type = type; het_list->item = valInt; break; - case 1: + case 1: //end pid, type long integer het_list->type = type; het_list->item = valInt; break; - case 2: + case 2: //start time, type long integer het_list->type = type; het_list->item = valInt; break; - case 3: + case 3: //end time, type long integer het_list->type = type; het_list->item = valInt; break; - case 4: + case 4: //command, type pointer to characters het_list->type = type; het_list->item = valChar; break; } het_list->next = NULL; - head = curr = het_list; + return het_list; } @@ -3495,10 +3482,7 @@ struct heterogeneous_list* store_het_list(int type, long int valInt, char *valCh break; } - - het_list->next = NULL; - - + het_list->next = NULL; curr->next = het_list; curr = het_list; @@ -3506,209 +3490,49 @@ struct heterogeneous_list* store_het_list(int type, long int valInt, char *valCh } - - -// int delete_from_list(int val) -// { -// struct test_struct *prev = NULL; -// struct test_struct *del = NULL; - -// printf("\n Deleting value [%d] from list\n",val); - -// del = search_in_list(val,&prev); -// if(del == NULL) -// { -// return -1; -// } -// else -// { -// if(prev != NULL) -// prev->next = del->next; - -// if(del == curr) -// { -// curr = prev; -// } -// else if(del == head) -// { -// head = del->next; -// } -// } - -// free(del); -// del = NULL; - -// return 0; -// } - - - - -// struct heterogeneous_list* analize_het_list(void) { - -// struct heterogeneous_list* het_list = head; - -// while(het_list != NULL) -// { - -// if(het_list->type != 4 && het_list->item == -1) { - -// het_list = delete_from_list() - -// } -// else het_list = het_list->next; - - -// } - -// return het_list; -// } - - - - - - - // int findMin(int current, int new) { - - // if (new >= current && current != -2 && current != -1 || new == -1) return current; - // else return new; - - // } - - -void print_het_list(void) -{ - struct heterogeneous_list* het_list = head; - - //printf("enter print\n"); - while(het_list != NULL) - { - //printf("type: %d\n", het_list->type); - //printf("enter while print\n"); - switch(het_list->type) { - case 0: - //printf("enter int print\n"); - //CVMDEBUG("\n %d \n",het_list->item); - het_list = het_list->next; - break; - case 1: - //CVMDEBUG("\n %d \n",het_list->item); - het_list = het_list->next; - break; - case 2: - //printf("enter int print\n"); - //CVMDEBUG("\n %d \n",het_list->item); - het_list = het_list->next; - break; - case 3: - //CVMDEBUG("\n %d \n",het_list->item); - het_list = het_list->next; - break; - case 4: - //printf("enter int print\n"); - //CVMDEBUG("\n %s \n",het_list->item); - het_list = het_list->next; - break; - - } - - } - return; - -} - - -int hetListLength(void) -{ - struct heterogeneous_list* het_list = head; - int size = 0; - - while (het_list != NULL) - { - ++size; - het_list = het_list->next; - } - - return size; -} - - - -void create_marks_csv(FILE *fp){ - +void write_to_csv(FILE *fp) +{ struct heterogeneous_list *het_list = head; - //int valueInt[4] = {0}; long int valueInt; char *command; - //CVMDEBUG(" yeeeeeeeeeeeeeeeeeees"); - // printf(" problem \n"); fprintf(fp,"command!start!pid!end\n");// - // if (retval < 1) - // abort(); - - //fprintf(fp, "Dumping marks PID %d ptr %x\n", getpid(), ptr); - - //int i = 0; - //int j = 0; - - while (het_list != NULL) - { - - switch(het_list->type) { - - case 0: - valueInt = het_list->item; - het_list = het_list->next; - if (valueInt == NULL) valueInt = 0; - fprintf(fp,"!%ld\n", valueInt); - break; - case 1: - valueInt = het_list->item; - het_list = het_list->next; - if (valueInt == NULL) valueInt = 0; - fprintf(fp,"!!%ld", valueInt); - break; - case 2: - valueInt = het_list->item; - het_list = het_list->next; - if (valueInt == NULL) valueInt = 0; - fprintf(fp,"!%ld", valueInt); - break; - case 3: - valueInt = het_list->item; - het_list = het_list->next; - if (valueInt == NULL) valueInt = 0; - fprintf(fp,"!%ld\n", valueInt); - break; - - case 4: - //command = malloc(strlen(het_list->item) + 2 + 1); - //command[0] = 0; - //command = strcat(command, "\""); - //command = strcat(command, het_list->item); - //command = strcat(command, "\""); - command = het_list->item; - het_list = het_list->next; - //i+=1; - if (command == NULL) command = ""; - fprintf(fp,"%s", command); - - break; - } - - //if(i==5) - //{ - - //fprintf(fp, "\n%d!%s!%d", valueInt[1], command, valueInt[0]); // - //fprintf(fp, "\n%d!!!%d", valueInt[2],valueInt[3]); - //i = 0; - //j = 0; - - //} - - } + while (het_list != NULL) + { + switch(het_list->type) + { + case 0: + valueInt = het_list->item; + het_list = het_list->next; + if (valueInt == NULL) valueInt = 0; + fprintf(fp,"!%ld\n", valueInt); + break; + case 1: + valueInt = het_list->item; + het_list = het_list->next; + if (valueInt == NULL) valueInt = 0; + fprintf(fp,"!!%ld", valueInt); + break; + case 2: + valueInt = het_list->item; + het_list = het_list->next; + if (valueInt == NULL) valueInt = 0; + fprintf(fp,"!%ld", valueInt); + break; + case 3: + valueInt = het_list->item; + het_list = het_list->next; + if (valueInt == NULL) valueInt = 0; + fprintf(fp,"!%ld\n", valueInt); + break; + case 4: + command = het_list->item; + het_list = het_list->next; + if (command == NULL) command = ""; + fprintf(fp,"%s", command); + break; } + } +} /* @@ -4294,9 +4118,7 @@ dowait(int wait_flags, struct job *job) * NB: _not_ safe_waitpid, we need to detect EINTR */ if (doing_jobctl) wait_flags |= WUNTRACED; - - pid = waitpid(-1, &status, wait_flags); - + pid = waitpid(-1, &status, wait_flags); TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", pid, status, errno, strerror(errno))); if (pid <= 0) @@ -4370,10 +4192,6 @@ dowait(int wait_flags, struct job *job) out2str(s); } } - - //add_to_list(pid, true); - //printf("store pid\n"); - //store_het_list(0,pid, ""); return pid; } @@ -4839,7 +4657,6 @@ cmdtxt(union node *n) switch (n->type) { default: #if DEBUG - abort(); #endif case NPIPE: @@ -5046,7 +4863,6 @@ forkchild(struct job *jp, union node *n, int mode) oldlvl = shlvl; shlvl++; - /* man bash: "Non-builtin commands run by bash have signal handlers * set to the values inherited by the shell from its parent". * Do we do it correctly? */ @@ -5104,7 +4920,6 @@ forkchild(struct job *jp, union node *n, int mode) /* do job control only in root shell */ doing_jobctl = 0; if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) { - pid_t pgrp; if (jp->nprocs == 0) @@ -5167,20 +4982,15 @@ forkchild(struct job *jp, union node *n, int mode) #endif static void forkparent(struct job *jp, union node *n, int mode, pid_t pid) -{ - - TRACE(("In parent shell: child = %d\n", pid)); - +{ + TRACE(("In parent shell: child = %d\n", pid)); if (!jp) { while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0) - continue; jobless++; - return; } #if JOBS - if (mode != FORK_NOJOB && jp->jobctl) { int pgrp; @@ -5189,8 +4999,7 @@ forkparent(struct job *jp, union node *n, int mode, pid_t pid) else pgrp = jp->ps[0].ps_pid; /* This can fail because we are doing it in the child also */ - setpgid(pid, pgrp); - + setpgid(pid, pgrp); } #endif if (mode == FORK_BG) { @@ -5203,7 +5012,6 @@ forkparent(struct job *jp, union node *n, int mode, pid_t pid) ps->ps_status = -1; ps->ps_cmd = nullstr; #if JOBS - //if (doing_jobctl && n) if (n) ps->ps_cmd = commandtext(n); #endif @@ -5217,34 +5025,22 @@ forkshell(struct job *jp, union node *n, int mode) TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode)); pid = fork(); - if (pid < 0) { TRACE(("Fork failed, errno=%d", errno)); if (jp) freejob(jp); - ash_msg_and_raise_error("can't fork"); - + ash_msg_and_raise_error("can't fork"); } if (pid == 0) { CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */ forkchild(jp, n, mode); - } else { forkparent(jp, n, mode, pid); - } return pid; } - - - - - - - - /* * return 1 if there are stopped jobs, otherwise 0 */ @@ -5422,8 +5218,7 @@ openredirect(union node *redir) goto ecreate; break; default: -#if DEBUG - +#if DEBUG abort(); #endif /* Fall through to eliminate warning. */ @@ -6158,13 +5953,11 @@ evalbackcmd(union node *n, struct backcmd *result) close(pip[1]); result->fd = pip[0]; result->jp = jp; - } herefd = saveherefd; out: TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n", result->fd, result->buf, result->nleft, result->jp)); - } /* @@ -7699,17 +7492,12 @@ static int builtinloc = -1; /* index in path of %builtin, or -1 */ static void tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp) { - -#if ENABLE_FEATURE_SH_STANDALONE - - if (applet_no >= 0) { - +#if ENABLE_FEATURE_SH_STANDALONE + if (applet_no >= 0) { if (APPLET_IS_NOEXEC(applet_no)) { - clearenv(); while (*envp) putenv(*envp++); - run_applet_no_and_exit(applet_no, argv); } /* re-exec ourselves with the new arguments */ @@ -7717,34 +7505,15 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char ** /* If they called chroot or otherwise made the binary no longer * executable, fall through */ } - #endif repeat: - #ifdef SYSV do { - execve(cmd, argv, envp); } while (errno == EINTR); #else - - //if(strcmp("/bin/dumpstat", cmd) == 0) { - - //char filename[25]; - //snprintf(filename, 25, "/root/busybox/collect_data.py"); - //FILE *fp = fopen(filename, "w+"); - //if (fp == NULL) { - //CVMDEBUG("ERROR CREATING %s %d", filename, errno); - // abort(); - //} - //fprintf(fp,"jojojojo \n"); - //fclose(fp); - //} execve(cmd, argv, envp); - - - #endif if (cmd == (char*) bb_busybox_exec_path) { /* We already visited ENOEXEC branch below, don't do it again */ @@ -7786,15 +7555,6 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char ** } } - - - - - -/* - -*/ - /* * Exec a program. Never returns. If you change this routine, you may * have to change the find_command routine as well. @@ -7821,8 +7581,7 @@ shellexec(char **argv, const char *path, int idx) /* We tried execing ourself, but it didn't work. * Maybe /proc/self/exe doesn't exist? * Try $PATH search. - */ - + */ goto try_PATH; } e = errno; @@ -7830,14 +7589,10 @@ shellexec(char **argv, const char *path, int idx) try_PATH: e = ENOENT; while ((cmdname = path_advance(&path, argv[0])) != NULL) { - if (--idx < 0 && pathopt == NULL) { - tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp); - + tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp); if (errno != ENOENT && errno != ENOTDIR) - e = errno; - - + e = errno; } stunalloc(cmdname); } @@ -7860,8 +7615,6 @@ shellexec(char **argv, const char *path, int idx) argv[0], e, suppress_int)); ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found")); /* NOTREACHED */ - - } static void @@ -8233,7 +7986,6 @@ describe_command(char *command, int describe_command_verbose) } else { do { p = path_advance(&path, command); - stunalloc(p); } while (--j >= 0); } @@ -8270,12 +8022,10 @@ describe_command(char *command, int describe_command_verbose) if (describe_command_verbose) { out1str(": not found\n"); } - return 127; } out: out1str("\n"); - return 0; } @@ -8310,7 +8060,8 @@ waitforjob(struct job *jp) INT_OFF; - while (jp->state == JOBRUNNING) { + while (jp->state == JOBRUNNING) + { /* In non-interactive shells, we _can_ get * a keyboard signal here and be EINTRed, * but we just loop back, waiting for command to complete. @@ -8344,101 +8095,56 @@ waitforjob(struct job *jp) // START // - int n = jp->nprocs; - - // printf("number of processes: %d\n", n); - - for (int j = 0; j < n; j++) { - - //printf("J: %d\n", j); - struct procstat *ps = &jp->ps[j]; - /* Skip non-running and not-stopped members - * (i.e. dead members) of the job - */ - //if (ps->ps_status == -1) - struct timeval time11; - long int intWait; - if (gettimeofday(&time11,NULL)){ - // Handle error - } - //double waitStartTime = (double)time11.tv_sec + (double)time11.tv_usec * .000001; - long int usecWait = time11.tv_sec * 1000000 + time11.tv_usec; - - - if (ps->ps_status == -1) { - intWait = usecWait; - } - else { - intWait = -1; - } - - char *command = ckstrdup(ps->ps_cmd); - store_het_list(4,0,command); - store_het_list(2,intWait, ""); - store_het_list(0,ps->ps_pid, ""); - - //printf("pid: %d, command: %s, status: %d, start: %d\n", ps->ps_pid, ps->ps_cmd, ps->ps_status, intWait); - - //find minim start time depending on pid: store pid, store start time, store command - + for (int j = 0; j < n; j++) + { + struct procstat *ps = &jp->ps[j]; + /* Skip non-running and not-stopped members + * (i.e. dead members) of the job + */ + struct timeval start; + long int startTime; + long int usecStart = start.tv_sec * 1000000 + start.tv_usec; + if (ps->ps_status == -1) + { + startTime = usecStart; + } + else + { + startTime = -1; + } + char *command = ckstrdup(ps->ps_cmd); + store_het_list(4,0,command); + store_het_list(2,startTime, ""); + store_het_list(0,ps->ps_pid, ""); } - - - + dowait(DOWAIT_BLOCK, jp); // END // - int m = jp->nprocs; - // int arrayEnd[m][2]; - - // for (int k = 0; k < m; k++) { - // for (int l = 0; l < 2; l++) { - // arrayEnd[k][l] = -2; - // } - // } - - - for (int k = 0; k < m; k++) { - - //printf("K: %d\n", k); - struct procstat *ps = &jp->ps[k]; - /* Skip non-running and not-stopped members - * (i.e. dead members) of the job - */ - //if (ps->ps_status == -1) - long int intDone; - struct timeval time3; - if (gettimeofday(&time3,NULL)){ - // Handle error - } - //int microseconds = time3.tv_sec * 1000000 + time3.tv_usec; - double pidRealEndTime = (double)time3.tv_sec + (double)time3.tv_usec * .000001; - - long int usecDone = time3.tv_sec * 1000000 + time3.tv_usec; - if (ps->ps_status != -1) { - intDone = usecDone; - } - else { - intDone = -1; - } - //printf("pid: %d, command: %s, status: %d, end: %d\n", ps->ps_pid, ps->ps_cmd, ps->ps_status, intDone); - - - store_het_list(1,ps->ps_pid, ""); - store_het_list(3,intDone, ""); - - - //find minim end time depending on pid: store pid, store end time, store command - + for (int k = 0; k < m; k++) + { + struct procstat *ps = &jp->ps[k]; + /* Skip non-running and not-stopped members + * (i.e. dead members) of the job + */ + long int endTime; + struct timeval end; + long int usecEnd = time3.tv_sec * 1000000 + time3.tv_usec; + if (ps->ps_status != -1) + { + endTime = usecEnd; + } + else + { + endTime = -1; + } + store_het_list(1,ps->ps_pid, ""); + store_het_list(3,endTime, ""); } - - - } INT_ON; - st = getstatus(jp); #if JOBS if (jp->jobctl) { @@ -8457,8 +8163,7 @@ waitforjob(struct job *jp) if (jp->state == JOBDONE) #endif - freejob(jp); - + freejob(jp); return st; } @@ -9162,7 +8867,6 @@ evalsubshell(union node *n, int flags) redirect(n->nredir.redirect, 0); evaltreenr(n->nredir.n, flags); /* never returns */ - //CVMDEBUG("evalsubshell line 8694\n"); } status = 0; if (!backgnd) @@ -9269,7 +8973,6 @@ evalpipe(union node *n, int flags) } if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) { INT_ON; - //CVMDEBUG("evalpipe line 8795\n"); if (pip[1] >= 0) { close(pip[0]); } @@ -9283,8 +8986,6 @@ evalpipe(union node *n, int flags) } evaltreenr(lp->n, flags); /* never returns */ - - } if (prevfd >= 0) close(prevfd); @@ -9929,17 +9630,17 @@ evalcommand(union node *cmd, int flags) INT_OFF; jp = makejob(/*cmd,*/ 1); if (forkshell(jp, cmd, FORK_FG) != 0) { + /* parent */ exitstatus = waitforjob(jp); INT_ON; TRACE(("forked child exited with %d\n", exitstatus)); break; } /* child */ - FORCE_INT_ON; + FORCE_INT_ON; + /* fall through to exec'ing external program */ } - - listsetvar(varlist.list, VEXPORT|VSTACK); - + listsetvar(varlist.list, VEXPORT|VSTACK); shellexec(argv, path, cmdentry.u.index); /* NOTREACHED */ } /* default */ @@ -12488,7 +12189,6 @@ readtoken(void) { int t; #if DEBUG - smallint alreadyseen = tokpushback; #endif @@ -12541,7 +12241,6 @@ readtoken(void) out: checkkwd = 0; #if DEBUG - if (!alreadyseen) TRACE(("token '%s' %s\n", tokname_array[t] + 1, t == TWORD ? wordtext : "")); else @@ -12719,8 +12418,7 @@ cmdloop(int top) chkmail(); } n = parsecmd(inter); -#if DEBUG - +#if DEBUG if (DEBUG > 2 && debug && (n != NODE_EOF)) showtree(n); #endif @@ -12912,8 +12610,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) switch (cmdp->cmdtype) { default: -#if DEBUG - +#if DEBUG abort(); #endif case CMDNORMAL: @@ -13188,13 +12885,6 @@ exportcmd(int argc UNUSED_PARAM, char **argv) char *name; const char *p; char **aptr; - - - - - - - char opt; int flag; int flag_off; @@ -13505,10 +13195,9 @@ exitshell(void) snprintf(filename, 25, "/scores.csv.%d", getpid()); FILE *fp = fopen(filename, "w+"); if (fp == NULL) { - //CVMDEBUG("ERROR CREATING %s %d", filename, errno); abort(); } - create_marks_csv(fp); + write_to_csv(fp); fclose(fp); #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT @@ -13568,7 +13257,6 @@ init(void) } setvar2("PPID", utoa(getppid())); - #if ENABLE_ASH_BASH_COMPAT p = lookupvar("SHLVL"); setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT); @@ -13622,7 +13310,7 @@ procargs(char **argv) for (i = 0; i < NOPTS; i++) optlist[i] = 2; argptr = xargv; - if (options(1)) { /*cmdline:*/ + if (options(/*cmdline:*/ 1)) { /* it already printed err message */ raise_exception(EXERROR); } @@ -13729,7 +13417,6 @@ int ash_main(int argc UNUSED_PARAM, char **argv) INIT_G_misc(); INIT_G_memstack(); INIT_G_var(); - #if ENABLE_ASH_ALIAS INIT_G_alias(); #endif @@ -13738,6 +13425,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) #if PROFILE monitor(4, etext, profile_buf, sizeof(profile_buf), 50); #endif + #if ENABLE_FEATURE_EDITING line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP); #endif @@ -13752,11 +13440,9 @@ int ash_main(int argc UNUSED_PARAM, char **argv) if (e == EXERROR) exitstatus = 2; s = state; - - if (e == EXEXIT || shlvl || s == 0 || iflag == 0) { + if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) { exitshell(); } - if (e == EXINT) { outcslow('\n', stderr); } @@ -13772,8 +13458,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) goto state4; } exception_handler = &jmploc; -#if DEBUG - +#if DEBUG opentrace(); TRACE(("Shell args: ")); trace_puts_args(argv); @@ -13802,7 +13487,6 @@ int ash_main(int argc UNUSED_PARAM, char **argv) } state2: state = 3; - if ( #ifndef linux getuid() == geteuid() && getgid() == getegid() && @@ -13826,6 +13510,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) // in is_hidden_fd() to not be considered "hidden fd" evalstring(minusc, 0); } + if (sflag || minusc == NULL) { #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY if (iflag) { @@ -13847,16 +13532,12 @@ int ash_main(int argc UNUSED_PARAM, char **argv) # endif } #endif - state4: /* XXX ??? - why isn't this before the "if" statement */ - cmdloop(1); } - #if PROFILE monitor(0); #endif - #ifdef GPROF { extern void _mcleanup(void); @@ -13866,7 +13547,6 @@ int ash_main(int argc UNUSED_PARAM, char **argv) TRACE(("End of main reached\n")); exitshell(); /* NOTREACHED */ - } From c7543d4263adf6035b3ede7608bfcba97268f3b6 Mon Sep 17 00:00:00 2001 From: pmazdin Date: Tue, 1 Sep 2015 15:36:40 +0200 Subject: [PATCH 3/8] new ash.c --- shell/ash.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 53b858d82..67f7ef379 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -32,6 +32,7 @@ #define DEBUG_TIME 0 #define DEBUG_PID 1 #define DEBUG_SIG 1 +#define WRITE_TO_CSV 1 #define PROFILE 0 @@ -8131,7 +8132,7 @@ waitforjob(struct job *jp) */ long int endTime; struct timeval end; - long int usecEnd = time3.tv_sec * 1000000 + time3.tv_usec; + long int usecEnd = end.tv_sec * 1000000 + end.tv_usec; if (ps->ps_status != -1) { endTime = usecEnd; @@ -10552,7 +10553,7 @@ setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) return showvars(nullstr, 0, VUNSET); INT_OFF; - retval = options(0); /*cmdline:*/ + retval = options(/*cmdline:*/ 0); if (retval == 0) { /* if no parse error... */ optschanged(); if (*argptr != NULL) { @@ -13190,15 +13191,17 @@ exitshell(void) char *p; int status; - - char filename[25]; - snprintf(filename, 25, "/scores.csv.%d", getpid()); - FILE *fp = fopen(filename, "w+"); - if (fp == NULL) { - abort(); - } - write_to_csv(fp); - fclose(fp); +//save data to .csv files if needed +#if WRITE_TO_CSV + char filename[25]; + snprintf(filename, 25, "/scores.csv.%d", getpid()); + FILE *fp = fopen(filename, "w+"); + if (fp == NULL) { + abort(); + } + write_to_csv(fp); + fclose(fp); +#endif #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT save_history(line_input_state); From 3e349d90204a3793c86552e360c47b0fe6b60a2d Mon Sep 17 00:00:00 2001 From: pmazdin Date: Thu, 3 Sep 2015 11:51:16 +0200 Subject: [PATCH 4/8] new version of ash.c --- shell/ash.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 67f7ef379..b23d4a681 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -32,7 +32,7 @@ #define DEBUG_TIME 0 #define DEBUG_PID 1 #define DEBUG_SIG 1 -#define WRITE_TO_CSV 1 +#define GET_TIME_CONSUMPTION #define PROFILE 0 @@ -45,7 +45,9 @@ #include #include #include /* for setting $HOSTNAME */ - +#include +#include +#include #include "busybox.h" /* for applet_names */ #include "unicode.h" @@ -3394,6 +3396,8 @@ static smallint doing_jobctl; //references:8 static void setjobctl(int); #endif + +#ifdef GET_TIME_CONSUMPTION // list of 5 possible items where integer value 'type' // refers to: 0 = start pid, 1 = end pid, 2 = start time, // 3 = end time, 4 = command; @@ -3534,7 +3538,7 @@ void write_to_csv(FILE *fp) } } } - +#endif /* * Ignore a signal. @@ -5013,7 +5017,11 @@ forkparent(struct job *jp, union node *n, int mode, pid_t pid) ps->ps_status = -1; ps->ps_cmd = nullstr; #if JOBS +#ifdef GET_TIME_CONSUMPTION if (n) +#else + if (doing_jobctl && n) +#endif ps->ps_cmd = commandtext(n); #endif } @@ -8094,7 +8102,7 @@ waitforjob(struct job *jp) * $ _ */ - +#ifdef GET_TIME_CONSUMPTION // START // int n = jp->nprocs; for (int j = 0; j < n; j++) @@ -8119,9 +8127,11 @@ waitforjob(struct job *jp) store_het_list(2,startTime, ""); store_het_list(0,ps->ps_pid, ""); } - +#endif + dowait(DOWAIT_BLOCK, jp); +#ifdef GET_TIME_CONSUMPTION // END // int m = jp->nprocs; for (int k = 0; k < m; k++) @@ -8144,6 +8154,7 @@ waitforjob(struct job *jp) store_het_list(1,ps->ps_pid, ""); store_het_list(3,endTime, ""); } +#endif } INT_ON; st = getstatus(jp); @@ -13191,8 +13202,12 @@ exitshell(void) char *p; int status; +#ifdef GET_TIME_CONSUMPTION //save data to .csv files if needed -#if WRITE_TO_CSV + struct stat st = {0}; + if (stat("ashTime", &st) == -1) { + mkdir("ashTime", ACCESSPERMS); + } char filename[25]; snprintf(filename, 25, "/scores.csv.%d", getpid()); FILE *fp = fopen(filename, "w+"); From 7ba5610e6921a051cb4f170cb6fb79e5ec63c3c8 Mon Sep 17 00:00:00 2001 From: pmazdin Date: Fri, 4 Sep 2015 11:38:09 +0200 Subject: [PATCH 5/8] modified ash.c --- shell/ash.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index b23d4a681..47198f6db 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -53,7 +53,6 @@ #include #include -#include #include "shell_common.h" #if ENABLE_SH_MATH_SUPPORT # include "math.h" @@ -445,7 +444,7 @@ static void raise_exception(int) NORETURN; static void raise_exception(int e) { -#if DEBUG +#if DEBUG if (exception_handler == NULL) abort(); #endif @@ -8113,6 +8112,9 @@ waitforjob(struct job *jp) */ struct timeval start; long int startTime; + if (gettimeofday(&start,NULL)){ + //Handle error + } long int usecStart = start.tv_sec * 1000000 + start.tv_usec; if (ps->ps_status == -1) { @@ -8142,6 +8144,9 @@ waitforjob(struct job *jp) */ long int endTime; struct timeval end; + if (gettimeofday(&end,NULL)){ + //Handle error + } long int usecEnd = end.tv_sec * 1000000 + end.tv_usec; if (ps->ps_status != -1) { @@ -13208,8 +13213,8 @@ exitshell(void) if (stat("ashTime", &st) == -1) { mkdir("ashTime", ACCESSPERMS); } - char filename[25]; - snprintf(filename, 25, "/scores.csv.%d", getpid()); + char filename[30]; + snprintf(filename, 30, "ashTime/scores.csv.%d", getpid()); FILE *fp = fopen(filename, "w+"); if (fp == NULL) { abort(); From aa0e7dd1f543b87ad114568dfd07c1110ae8393b Mon Sep 17 00:00:00 2001 From: pmazdin Date: Fri, 4 Sep 2015 11:58:35 +0200 Subject: [PATCH 6/8] modified ash.c --- shell/ash.c | 70 ++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 47198f6db..434618912 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -45,6 +45,7 @@ #include #include #include /* for setting $HOSTNAME */ + #include #include #include @@ -1226,7 +1227,7 @@ static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN; static void ash_vmsg_and_raise(int cond, const char *msg, va_list ap) { -#if DEBUG +#if DEBUG if (msg) { TRACE(("ash_vmsg_and_raise(%d, \"", cond)); TRACEV((msg, ap)); @@ -1456,7 +1457,7 @@ stzalloc(size_t nbytes) static void stunalloc(void *p) { -#if DEBUG +#if DEBUG if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) { write(STDERR_FILENO, "stunalloc\n", 10); abort(); @@ -3598,11 +3599,9 @@ setsignal(int signo) new_act = S_CATCH; break; case SIGQUIT: -#if DEBUG - if (debug) { - +#if DEBUG + if (debug) break; - } #endif /* man bash: * "In all cases, bash ignores SIGQUIT. Non-builtin @@ -4122,7 +4121,7 @@ dowait(int wait_flags, struct job *job) * NB: _not_ safe_waitpid, we need to detect EINTR */ if (doing_jobctl) wait_flags |= WUNTRACED; - pid = waitpid(-1, &status, wait_flags); + pid = waitpid(-1, &status, wait_flags); TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", pid, status, errno, strerror(errno))); if (pid <= 0) @@ -4986,15 +4985,15 @@ forkchild(struct job *jp, union node *n, int mode) #endif static void forkparent(struct job *jp, union node *n, int mode, pid_t pid) -{ - TRACE(("In parent shell: child = %d\n", pid)); +{ + TRACE(("In parent shell: child = %d\n", pid)); if (!jp) { while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0) continue; jobless++; return; } -#if JOBS +#if JOBS if (mode != FORK_NOJOB && jp->jobctl) { int pgrp; @@ -5003,7 +5002,7 @@ forkparent(struct job *jp, union node *n, int mode, pid_t pid) else pgrp = jp->ps[0].ps_pid; /* This can fail because we are doing it in the child also */ - setpgid(pid, pgrp); + setpgid(pid, pgrp); } #endif if (mode == FORK_BG) { @@ -5037,7 +5036,7 @@ forkshell(struct job *jp, union node *n, int mode) TRACE(("Fork failed, errno=%d", errno)); if (jp) freejob(jp); - ash_msg_and_raise_error("can't fork"); + ash_msg_and_raise_error("can't fork"); } if (pid == 0) { CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */ @@ -5226,7 +5225,7 @@ openredirect(union node *redir) goto ecreate; break; default: -#if DEBUG +#if DEBUG abort(); #endif /* Fall through to eliminate warning. */ @@ -7500,8 +7499,8 @@ static int builtinloc = -1; /* index in path of %builtin, or -1 */ static void tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp) { -#if ENABLE_FEATURE_SH_STANDALONE - if (applet_no >= 0) { +#if ENABLE_FEATURE_SH_STANDALONE + if (applet_no >= 0) { if (APPLET_IS_NOEXEC(applet_no)) { clearenv(); while (*envp) @@ -7515,12 +7514,12 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char ** } #endif -repeat: + repeat: #ifdef SYSV do { execve(cmd, argv, envp); } while (errno == EINTR); -#else +#else execve(cmd, argv, envp); #endif if (cmd == (char*) bb_busybox_exec_path) { @@ -7549,8 +7548,8 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char ** char **ap; char **new; - for (ap = argv; *ap; ap++) { - continue; } + for (ap = argv; *ap; ap++) + continue; new = ckmalloc((ap - argv + 2) * sizeof(new[0])); new[0] = (char*) "ash"; new[1] = cmd; @@ -7558,7 +7557,7 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char ** while ((*ap++ = *++argv) != NULL) { continue; } cmd = (char*) bb_busybox_exec_path; - argv = new; + argv = new; goto repeat; } } @@ -7589,7 +7588,7 @@ shellexec(char **argv, const char *path, int idx) /* We tried execing ourself, but it didn't work. * Maybe /proc/self/exe doesn't exist? * Try $PATH search. - */ + */ goto try_PATH; } e = errno; @@ -7598,14 +7597,14 @@ shellexec(char **argv, const char *path, int idx) e = ENOENT; while ((cmdname = path_advance(&path, argv[0])) != NULL) { if (--idx < 0 && pathopt == NULL) { - tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp); + tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp); if (errno != ENOENT && errno != ENOTDIR) - e = errno; - } - stunalloc(cmdname); - } + e = errno; + } + stunalloc(cmdname); + } } - + /* Map to POSIX errors */ switch (e) { case EACCES: @@ -8058,7 +8057,6 @@ describe_command(char *command, int describe_command_verbose) * * Called with interrupts off. */ - int counter = 0; static int waitforjob(struct job *jp) { @@ -9647,7 +9645,7 @@ evalcommand(union node *cmd, int flags) INT_OFF; jp = makejob(/*cmd,*/ 1); if (forkshell(jp, cmd, FORK_FG) != 0) { - /* parent */ + /* parent */ exitstatus = waitforjob(jp); INT_ON; TRACE(("forked child exited with %d\n", exitstatus)); @@ -9655,9 +9653,9 @@ evalcommand(union node *cmd, int flags) } /* child */ FORCE_INT_ON; - /* fall through to exec'ing external program */ + /* fall through to exec'ing external program */ } - listsetvar(varlist.list, VEXPORT|VSTACK); + listsetvar(varlist.list, VEXPORT|VSTACK); shellexec(argv, path, cmdentry.u.index); /* NOTREACHED */ } /* default */ @@ -10569,7 +10567,7 @@ setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) return showvars(nullstr, 0, VUNSET); INT_OFF; - retval = options(/*cmdline:*/ 0); + retval = options(/*cmdline:*/ 0); if (retval == 0) { /* if no parse error... */ optschanged(); if (*argptr != NULL) { @@ -12435,7 +12433,7 @@ cmdloop(int top) chkmail(); } n = parsecmd(inter); -#if DEBUG +#if DEBUG if (DEBUG > 2 && debug && (n != NODE_EOF)) showtree(n); #endif @@ -12627,7 +12625,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) switch (cmdp->cmdtype) { default: -#if DEBUG +#if DEBUG abort(); #endif case CMDNORMAL: @@ -13333,7 +13331,7 @@ procargs(char **argv) for (i = 0; i < NOPTS; i++) optlist[i] = 2; argptr = xargv; - if (options(/*cmdline:*/ 1)) { + if (options(/*cmdline:*/ 1)) { /* it already printed err message */ raise_exception(EXERROR); } @@ -13481,7 +13479,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) goto state4; } exception_handler = &jmploc; -#if DEBUG +#if DEBUG opentrace(); TRACE(("Shell args: ")); trace_puts_args(argv); From 2f42751fb4a25df567ee0dbb2a1fc4900abd313c Mon Sep 17 00:00:00 2001 From: pmazdin Date: Mon, 7 Sep 2015 17:56:32 +0200 Subject: [PATCH 7/8] modified ash.c by adding extracted environment variable ASH_SCORES --- shell/ash.c | 290 ++++++++++++++++++++++++++-------------------------- 1 file changed, 145 insertions(+), 145 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 434618912..210af7ecb 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -3402,139 +3402,137 @@ static void setjobctl(int); // refers to: 0 = start pid, 1 = end pid, 2 = start time, // 3 = end time, 4 = command; // and 'item' pointer whose type is not fixed. -struct heterogeneous_list +struct event_list { int type; void *item; - struct heterogeneous_list *next; + struct event_list *next; }; -struct heterogeneous_list *head = NULL; -struct heterogeneous_list *curr = NULL; +struct event_list *head = NULL; +struct event_list *curr = NULL; -struct heterogeneous_list* create_het_list(int type, long int valInt, char *valChar) +struct event_list* create_ev_list(int type, long int valInt, char *valChar) { - struct heterogeneous_list *het_list = (struct heterogeneous_list*)malloc(sizeof(struct heterogeneous_list)); - if(NULL == het_list) + struct event_list *ev_list = (struct event_list*)malloc(sizeof(struct event_list)); + if(NULL == ev_list) { return NULL; } - switch(type) { - case 0: //start pid, type long integer - het_list->type = type; - het_list->item = valInt; + switch(type) + { + case 0: //start pid, type long integer + ev_list->item = valInt; break; case 1: //end pid, type long integer - het_list->type = type; - het_list->item = valInt; + ev_list->item = valInt; break; case 2: //start time, type long integer - het_list->type = type; - het_list->item = valInt; + ev_list->item = valInt; break; case 3: //end time, type long integer - het_list->type = type; - het_list->item = valInt; + ev_list->item = valInt; break; case 4: //command, type pointer to characters - het_list->type = type; - het_list->item = valChar; + ev_list->item = valChar; break; - } - - het_list->next = NULL; - head = curr = het_list; + default: + abort(); + } + ev_list->type = type; + ev_list->next = NULL; + head = curr = ev_list; - return het_list; + return ev_list; } -struct heterogeneous_list* store_het_list(int type, long int valInt, char *valChar) +struct event_list* store_ev_list(int type, long int valInt, char *valChar) { if(NULL == head) { - return (create_het_list(type,valInt,valChar)); + return (create_ev_list(type,valInt,valChar)); } - struct heterogeneous_list *het_list = (struct heterogeneous_list*)malloc(sizeof(struct heterogeneous_list)); - if(NULL == het_list) + struct event_list *ev_list = (struct event_list*)malloc(sizeof(struct event_list)); + if(NULL == ev_list) { - return NULL; + return; } - switch(type) { - + switch(type) + { case 0: - het_list->type = type; - het_list->item = valInt; + ev_list->type = type; + ev_list->item = valInt; break; case 1: - het_list->type = type; - het_list->item = valInt; + ev_list->type = type; + ev_list->item = valInt; break; case 2: - het_list->type = type; - het_list->item = valInt; + ev_list->type = type; + ev_list->item = valInt; break; case 3: - het_list->type = type; - het_list->item = valInt; + ev_list->type = type; + ev_list->item = valInt; break; case 4: - het_list->type = type; - het_list->item = valChar; + ev_list->type = type; + ev_list->item = valChar; break; - } + } - het_list->next = NULL; - curr->next = het_list; - curr = het_list; + ev_list->next = NULL; + curr->next = ev_list; + curr = ev_list; - return het_list; + return ev_list; } void write_to_csv(FILE *fp) -{ - struct heterogeneous_list *het_list = head; +{ + struct event_list *ev_list = head; long int valueInt; char *command; fprintf(fp,"command!start!pid!end\n");// - while (het_list != NULL) - { - switch(het_list->type) - { - case 0: - valueInt = het_list->item; - het_list = het_list->next; - if (valueInt == NULL) valueInt = 0; - fprintf(fp,"!%ld\n", valueInt); - break; - case 1: - valueInt = het_list->item; - het_list = het_list->next; - if (valueInt == NULL) valueInt = 0; - fprintf(fp,"!!%ld", valueInt); - break; - case 2: - valueInt = het_list->item; - het_list = het_list->next; - if (valueInt == NULL) valueInt = 0; - fprintf(fp,"!%ld", valueInt); - break; - case 3: - valueInt = het_list->item; - het_list = het_list->next; - if (valueInt == NULL) valueInt = 0; - fprintf(fp,"!%ld\n", valueInt); - break; - case 4: - command = het_list->item; - het_list = het_list->next; - if (command == NULL) command = ""; - fprintf(fp,"%s", command); - break; + while (ev_list != NULL) + { + switch(ev_list->type) + { + case 0: + valueInt = ev_list->item; + ev_list = ev_list->next; + if (valueInt == NULL) valueInt = 0; + fprintf(fp,"!%ld\n", valueInt); + break; + case 1: + valueInt = ev_list->item; + ev_list = ev_list->next; + if (valueInt == NULL) valueInt = 0; + fprintf(fp,"!!%ld", valueInt); + break; + case 2: + valueInt = ev_list->item; + ev_list = ev_list->next; + if (valueInt == NULL) valueInt = 0; + fprintf(fp,"!%ld", valueInt); + break; + case 3: + valueInt = ev_list->item; + ev_list = ev_list->next; + if (valueInt == NULL) valueInt = 0; + fprintf(fp,"!%ld\n", valueInt); + break; + case 4: + command = ev_list->item; + ev_list = ev_list->next; + if (command == NULL) command = ""; + fprintf(fp,"%s", command); + break; } } } @@ -7554,8 +7552,8 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char ** new[0] = (char*) "ash"; new[1] = cmd; ap = new + 2; - while ((*ap++ = *++argv) != NULL) { - continue; } + while ((*ap++ = *++argv) != NULL) + continue; cmd = (char*) bb_busybox_exec_path; argv = new; goto repeat; @@ -8102,30 +8100,30 @@ waitforjob(struct job *jp) #ifdef GET_TIME_CONSUMPTION // START // int n = jp->nprocs; - for (int j = 0; j < n; j++) - { - struct procstat *ps = &jp->ps[j]; - /* Skip non-running and not-stopped members - * (i.e. dead members) of the job - */ - struct timeval start; - long int startTime; - if (gettimeofday(&start,NULL)){ - //Handle error - } - long int usecStart = start.tv_sec * 1000000 + start.tv_usec; - if (ps->ps_status == -1) - { - startTime = usecStart; - } - else - { - startTime = -1; - } - char *command = ckstrdup(ps->ps_cmd); - store_het_list(4,0,command); - store_het_list(2,startTime, ""); - store_het_list(0,ps->ps_pid, ""); + for (int j = 0; j < n; j++) + { + struct procstat *ps = &jp->ps[j]; + /* Skip non-running and not-stopped members + * (i.e. dead members) of the job + */ + struct timeval start; + long int startTime; + if (gettimeofday(&start,NULL)){ + //Handle error + } + long int usecStart = start.tv_sec * 1000000 + start.tv_usec; + if (ps->ps_status == -1) + { + startTime = usecStart; + } + else + { + startTime = -1; + } + char *command = ckstrdup(ps->ps_cmd); + store_ev_list(4,0,command); + store_ev_list(2,startTime, ""); + store_ev_list(0,ps->ps_pid, ""); } #endif @@ -8134,28 +8132,28 @@ waitforjob(struct job *jp) #ifdef GET_TIME_CONSUMPTION // END // int m = jp->nprocs; - for (int k = 0; k < m; k++) - { - struct procstat *ps = &jp->ps[k]; - /* Skip non-running and not-stopped members - * (i.e. dead members) of the job - */ - long int endTime; - struct timeval end; - if (gettimeofday(&end,NULL)){ - //Handle error - } - long int usecEnd = end.tv_sec * 1000000 + end.tv_usec; - if (ps->ps_status != -1) - { - endTime = usecEnd; - } - else - { - endTime = -1; - } - store_het_list(1,ps->ps_pid, ""); - store_het_list(3,endTime, ""); + for (int k = 0; k < m; k++) + { + struct procstat *ps = &jp->ps[k]; + /* Skip non-running and not-stopped members + * (i.e. dead members) of the job + */ + long int endTime; + struct timeval end; + if (gettimeofday(&end,NULL)){ + //Handle error + } + long int usecEnd = end.tv_sec * 1000000 + end.tv_usec; + if (ps->ps_status != -1) + { + endTime = usecEnd; + } + else + { + endTime = -1; + } + store_ev_list(1,ps->ps_pid, ""); + store_ev_list(3,endTime, ""); } #endif } @@ -9645,7 +9643,7 @@ evalcommand(union node *cmd, int flags) INT_OFF; jp = makejob(/*cmd,*/ 1); if (forkshell(jp, cmd, FORK_FG) != 0) { - /* parent */ + /* parent */ exitstatus = waitforjob(jp); INT_ON; TRACE(("forked child exited with %d\n", exitstatus)); @@ -9653,7 +9651,7 @@ evalcommand(union node *cmd, int flags) } /* child */ FORCE_INT_ON; - /* fall through to exec'ing external program */ + /* fall through to exec'ing external program */ } listsetvar(varlist.list, VEXPORT|VSTACK); shellexec(argv, path, cmdentry.u.index); @@ -13206,19 +13204,21 @@ exitshell(void) int status; #ifdef GET_TIME_CONSUMPTION -//save data to .csv files if needed - struct stat st = {0}; - if (stat("ashTime", &st) == -1) { - mkdir("ashTime", ACCESSPERMS); - } - char filename[30]; - snprintf(filename, 30, "ashTime/scores.csv.%d", getpid()); - FILE *fp = fopen(filename, "w+"); - if (fp == NULL) { - abort(); - } - write_to_csv(fp); - fclose(fp); + //save data to .csv files if needed + char *path_to_scores = lookupvar("ASH_SCORES"); + if(path_to_scores) { + char filename[30]; + snprintf(filename, 30, "/scores.csv.%d", getpid()); + path_to_scores = concat_path_file(path_to_scores, filename); + FILE *fp = fopen(path_to_scores, "w+"); + if (fp == NULL) + { + abort(); + } + write_to_csv(fp); + fclose(fp); + free((char*)path_to_scores); + } #endif #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT From ff6792925c349101839b3d65651d909062fa1ce7 Mon Sep 17 00:00:00 2001 From: pmazdin Date: Mon, 14 Sep 2015 13:26:08 +0200 Subject: [PATCH 8/8] added main.py and collect_data.py to analyze data obtained after running busybox --- collect_data.py | 183 ++++++++++++++++++++++++++++++++++++++++++++++++ main.py | 13 ++++ 2 files changed, 196 insertions(+) create mode 100755 collect_data.py create mode 100755 main.py diff --git a/collect_data.py b/collect_data.py new file mode 100755 index 000000000..97e2c98da --- /dev/null +++ b/collect_data.py @@ -0,0 +1,183 @@ +#!/usr/bin/python + +''' + Python file that loads the data containing time stamps of all commands + executing during booting time of a virtual machine and analyzes them to + get duration of each so it can provide the best part to be optimized + and reduced in a sense of time. +''' + +import os +import numpy as numpy +import fnmatch +from operator import itemgetter + + +if ("ASH_SCORES" in os.environ): + directoryScores = os.environ["ASH_SCORES"] +else: + print("Chosen directory with data from BusyBox ash does not exist.") + exit() + +def loadScores(): + ''' + Method that loads all time stamps related to the specific commands, + removes duplicates and time stamps that were used just as an + orientation (e.g. -1). + Result is written in a text file named "all". + ''' + + mergedFiles = directoryScores + "/all" + fAll = open(mergedFiles, "w") + fAll.write("command!start!pid!end\n") + allWrittenLines = [] + for scorePid in fnmatch.filter(os.listdir(directoryScores), 'scores.csv.*'): + + scoreFile = directoryScores + "/" + scorePid + f = open(scoreFile, "r") + lines = f.readlines() + f.close() + + allShareLines = [] + sharePidLines = [] + listWritten = [] + for line in lines: + flag = False + if (line != "command!start!pid!end\n") : + #set the flag if line contains -1 meaning it takes more time to execute complex commands + for i in range ( len(line.split('!'))): + item = line.split('!')[i] + if ("-1" in item and (len(item) == 2 or item.endswith('\n'))): + flag = True + + #list of repeating pids + if (flag == False and findByPid(line, listWritten) == False and line not in allWrittenLines): + fAll.write(line) + listWritten.append(line) + + for i in range(len(listWritten)): + allWrittenLines.append(listWritten[i]) + + + + fAll.close() + + +def findByPid(line, writtenLines): + ''' + Method that returns true statement if there already exists a time stamp + related to the specific pid, i.e. if that command is already written + in a text file with results. + ''' + + for i in range(len(writtenLines)): + if (len(line.split('!')) == len(writtenLines[i].split('!'))): + countTheSame = 0 + for j in range(len(writtenLines[i].split('!'))): + if (writtenLines[i].split('!')[j] == line.split('!')[j]): + countTheSame += 1 + if (countTheSame == len(writtenLines[i].split('!'))-1): + return True + return False + + + +def hasSamePid(first, second): + ''' + Method that returns true statement if two lines containing the + command, start time stamp and pid, i.e. end time stamp and pid have + the same pid so that duration can be calculated for that specific pid. + ''' + + first = first.split('!')[2] + if first.endswith('\n'): + first = first[:-1] + + if (first == second.split('!')[2]): + return True + return False + + + +def calculateDuration(): + ''' + Given all scores from the file "all", this method needs to group lines + two by two based on its pid to calculate duraion of each process that + is executing. When duration is calculated, results are sorted based + on it value and saved to a new file named "sortedAll". + ''' + + mergedFiles = directoryScores + "/all" + newSorted = directoryScores + "/sortedAll" + fAll = open(mergedFiles, "r") + fSort = open(newSorted, "w") + fSort.write("command ! total ! nbOfTimes ! avgDuration\n") + lines = fAll.readlines() + minStart = float("inf") + maxEnd = 0 + + for i in range(len(lines)): + + if (lines[i] != "command!start!pid!end\n"): + + if (len(lines[i].split("!")) == 3): + firstTime = lines[i].split('!')[1] + firstLine = [long(s) for s in firstTime.split() if s.isdigit()] + if (firstLine[0] < minStart): + + minStart = firstLine[0] + else: + firstTime = lines[i].split('!')[3] + firstLine = [long(s) for s in firstTime.split() if s.isdigit()] + if (firstLine[0] > maxEnd): + + maxEnd = firstLine[0] + + + duration = maxEnd- minStart + writeLine = "total duration: " + "%ld" % duration + "\n" + fSort.write(writeLine) + + usedCommands=[] + hashAll = {} + for i in range(1, len(lines) - 1): + if (lines[i] != "command!start!pid!end\n" and len(lines[i].split('!')) == 3): + j = i+1 + while (j < len(lines)): + secondLine = lines[j] + if (len(lines[i].split('!')) < len(secondLine.split('!'))): + if (hasSamePid(lines[i],secondLine)): + a = lines[i].split('!')[2] + if a.endswith('\n'): + a = a[:-1] + firstTime = lines[i].split('!')[1] + firstLine = [long(s) for s in firstTime.split() if s.isdigit()] + secondTime= secondLine.split('!')[3] + secondLine = [long(s) for s in secondTime.split() if s.isdigit()] + + duration = secondLine[0] - firstLine[0] + comLine = lines[i].split('!')[0] + if (comLine not in usedCommands): + usedCommands.append(comLine) + hashAll[comLine] = [duration, 1, duration] + else: + hashAll[comLine][0] += duration + hashAll[comLine][1] += 1 + hashAll[comLine][2] = hashAll[comLine][0]/hashAll[comLine][1] + break + else: + j += 1 + continue + else: + j += 1 + continue + + hashAll=sorted(hashAll.items(), key=lambda e: e[1][2]) + for i in range(len(hashAll)): + writeLine = "\n" + hashAll[i][0] + "!" + " %ld " % hashAll[i][1][0] + "!" + " %ld " % hashAll[i][1][1] + "!" + " %ld " % hashAll[i][1][2] + fSort.write(writeLine) + fAll.close() + fSort.close() + + + diff --git a/main.py b/main.py new file mode 100755 index 000000000..70973c948 --- /dev/null +++ b/main.py @@ -0,0 +1,13 @@ +#!/usr/bin/python + +''' + python file to run all functions needed to analyze + data from busybox ash +''' + +import collect_data as cd + +cd.loadScores() + +cd.calculateDuration() +