#include #include #include #include #include #include #include #include #include "proto.h" #define BUF_SIZE 256 static int expLiteralChars(char *orig, char *new, int *oldl_ind, int *newl_ind, int *insideQuoteFlag) { if(orig[*oldl_ind] == '"') *insideQuoteFlag = !(*insideQuoteFlag); new[*newl_ind] = orig[*oldl_ind]; (*newl_ind)++; (*oldl_ind)++; return 0; } static int expEnvVars(char *orig, char *new, int *oldl_ind, int *newl_ind) { char *envValue; int envNameLen = 0; (*oldl_ind)++; while(orig[*oldl_ind + envNameLen] != '}') { if(orig[*oldl_ind + envNameLen] == 0 || orig[*oldl_ind + envNameLen] == '$') { fprintf(stderr, "msh: no matching }\n"); return 1; } envNameLen++; } orig[*oldl_ind + envNameLen] = 0; envValue = getenv(&(orig[*oldl_ind])); if(envValue != NULL) { strcpy(&(new[*newl_ind]), envValue); *newl_ind = *newl_ind + strlen(envValue); } *oldl_ind = *oldl_ind + envNameLen + 1; // envNameLen = 0; return 0; } static int expShPid(char *orig, char *new, int *oldl_ind, int *newl_ind) { char pidBuff[8]; int pid = (int)getpid(); int i = 0; if(sprintf(pidBuff, "%d", pid) > -1) { while(pidBuff[i]) { new[*newl_ind] = pidBuff[i++]; (*newl_ind)++; } (*oldl_ind)++; return 0; } return 1; } static int expMainArgs(char *orig, char *new, int *oldl_ind, int *newl_ind) //, int mainargc, char **mainargv, char **shiftedMArgV) { int argInd; int argLen; char tempChar; char *argIndStr = &(orig[*oldl_ind]); while(isdigit(orig[*oldl_ind])) (*oldl_ind)++; tempChar = orig[(*oldl_ind)]; orig[*oldl_ind] = 0; argInd = atoi(argIndStr); orig[*oldl_ind] = tempChar; if(m_argc == 1) { if(argInd >= m_shifted_argc) return 0; argLen = strlen(m_argv[0]); strcpy(&(new[*newl_ind]), m_argv[0]); } else { if((argInd+1) >= m_shifted_argc) return 0; if(argInd == 0) { argLen = strlen(m_argv[1]); strcpy(&(new[*newl_ind]), m_argv[1]); } else { argLen = strlen(m_shifted_argv[argInd+1]); strcpy(&(new[*newl_ind]), m_shifted_argv[argInd+1]); } } *newl_ind = *newl_ind + argLen; return 0; } static int expMainCount(char *new, int *newl_ind) //, int mainargc) { int argStrLen; int offset = 1; if(m_argc == 1) offset = 0; argStrLen = sprintf(&(new[*newl_ind]), "%d", (m_shifted_argc - offset)); *newl_ind = *newl_ind + argStrLen; return 0; } static int expLastExitS(char *new, int *newl_ind) { int exStatStrLen = sprintf(&(new[*newl_ind]), "%d", (last_exit_status)); *newl_ind = *newl_ind + exStatStrLen; return 0; } static int expWildCard(char *orig, char *new, int *oldl_ind, int *newl_ind, int filterFlag) { int i; int dirLen; int matchCount = 0; int passedFilterFlag = 0; int dirNameStrLen; char *dirName; char *filterStr; char tempChar; struct dirent **namelist; /* GET ALL THE DIRECTORIES AND PUT THEM IN namelist */ dirLen = scandir(".", &namelist, 0, alphasort); if(dirLen < 0) { perror("scandir"); return 1; } (*oldl_ind)++; if(filterFlag) { filterStr = &(orig[*oldl_ind]); while(orig[*oldl_ind] != ' ' && orig[*oldl_ind] != '"' && orig[*oldl_ind] != 0) { if(orig[*oldl_ind] == '/') { fprintf(stderr, "./msh: no match\n"); return 1; } (*oldl_ind)++; } tempChar = orig[*oldl_ind]; orig[*oldl_ind] = 0; } for(i = 0; i < dirLen; i++) { dirName = namelist[i]->d_name; dirNameStrLen = strlen(dirName); if(dirName[0] == '.') { passedFilterFlag = 0; } else if(filterFlag) { if(strlen(filterStr) > dirNameStrLen) passedFilterFlag = 0; else { if(!strcmp(filterStr, &(dirName[dirNameStrLen - strlen(filterStr)]))) passedFilterFlag = 1; else passedFilterFlag = 0; } } else passedFilterFlag = 1; if(passedFilterFlag) { matchCount++; strcpy(&(new[*newl_ind]), dirName); if(i != (dirLen -1)) { *newl_ind = *newl_ind + dirNameStrLen + 1; new[*newl_ind - 1] = ' '; } else *newl_ind = *newl_ind + dirNameStrLen; } free(namelist[i]); } if(!matchCount) { new[*newl_ind] = '*'; (*newl_ind)++; if(filterFlag) { strcpy(&(new[*newl_ind]), filterStr); *newl_ind = *newl_ind + strlen(filterStr); } } if(filterFlag) orig[*oldl_ind] = tempChar; free(namelist); return 0; } static int expHomeDir(char *orig, char *new, int *oldl_ind, int *newl_ind) { int i = 1; char temp; char *name = 0; char *hdir; struct passwd *pwResult; /* SEE IF NAME PRESENT AFTER ~ AND PUT NULL TERMINATOR AT END IF THERE IS IF NOT USE getlogin */ while(orig[*oldl_ind + i] != ' ' && orig[*oldl_ind + i] != '/' && orig[*oldl_ind + i] != 0) i++; temp = orig[*oldl_ind +i]; if(i == 1) name = getlogin(); else { orig[*oldl_ind + i] = 0; name = &(orig[*oldl_ind + 1]); } /* GET PASSWD RESULTS, REPLACE NULL(OR NOTHING) WITH TEMP */ pwResult = getpwnam(name); orig[*oldl_ind + i] = temp; /* UPDATE IND'S. IF THERE ARE NO PASSWD RESULTS, LEAVE LITERAL TILDA, OTHERWISE COPY HOME FOLDER TO NEW. */ if(!pwResult) { new[*newl_ind] = '~'; *oldl_ind = *oldl_ind + 1; *newl_ind = *newl_ind + 1; } else { hdir = pwResult->pw_dir; strcpy(&(new[*newl_ind]), hdir); *oldl_ind = *oldl_ind + i; *newl_ind = *newl_ind + strlen(hdir); } return 0; } static int expCmdOutput(char *orig, char *new, int *oldl_ind, int *newl_ind) { char buf[BUF_SIZE]; int bytes_read; int total_bytes_read = 0; int fd[2]; int parenthCount = 1; int i = *oldl_ind + 1; /* ENSURE MATCHING PARENS - REPLACE LAST PAREN WITH 0 */ while(parenthCount > 0) { if(orig[i] == '(') parenthCount++; else if(orig[i] == ')') parenthCount--; else if(orig[i] == 0) { fprintf(stderr, "./msh: missing )\n"); return 1; } i++; } orig[i-1] = 0; /* PIPE, RECURSIVELY CALL PROCESSLINE(should pass 0 for 3rd arg), AND CLOSE WRITE END */ if(pipe (fd) < 0) perror("pipe"); processline(&(orig[*oldl_ind + 1]), fd[1], 0); close(fd[1]); /* READ OUTPUT OF COMMAND FROM READ END OF PIPE, THEN CLOSE READ END */ while((bytes_read = read(fd[0],buf,BUF_SIZE-1))) { if(bytes_read < 0) { if(errno == EWOULDBLOCK || errno == EAGAIN) continue; else if(errno == EINTR) fprintf(stderr, "WE GOT AN EINTR SIGNAL\n"); else { perror("read"); break; // Or should this be exit? } } else if(bytes_read > 0) total_bytes_read += bytes_read; } buf[total_bytes_read] = 0; close(fd[0]); /* REPLACE ORIGINAL MATCHING PAREN, UPDATE oldl_ind */ orig[i-1] = ')'; *oldl_ind = i; /* COPY OUTPUT OF COMMAND TO EXPANDED LINE, UPDATE newl_ind */ i = 0; while(buf[i] != 0)// && buf[i] != '\n') { new[*newl_ind + i] = buf[i]; i++; } *newl_ind = *newl_ind + i; /* REMOVING EXTRA LINES */ i = 0; while(new[i]) { if(new[i] == '\n') new[i] = ' ';// && new[i+1] != 0) new[i] = ' '; i++; } return 0; } int expand(char *orig, char *new, int newsize) //, int mainargc, char **mainargv, char **shiftedMArgV) { int newl_ind = 0; int oldl_ind = 0; int insideQuoteFlag = 0; while(orig[oldl_ind] && newl_ind < newsize) { if(orig[oldl_ind] == '$') { if(orig[++oldl_ind] == '{') { if(expEnvVars(orig, new, &oldl_ind, &newl_ind)) return 1; } else if(orig[oldl_ind] == '(') { if(expCmdOutput(orig, new, &oldl_ind, &newl_ind)) return 1; } else if(orig[oldl_ind] == '$') { if(expShPid(orig, new, &oldl_ind, &newl_ind)) return 1; } else if(isdigit(orig[oldl_ind])) { if(expMainArgs(orig, new, &oldl_ind, &newl_ind)) return 1; } //, mainargc, mainargv, shiftedMArgV)) return 1; } else if(orig[oldl_ind] == '#') { if(expMainCount(new, &newl_ind)) return 1; oldl_ind++; } else if(orig[oldl_ind] == '?') { if(expLastExitS(new, &newl_ind)) return 1; oldl_ind++; } else { new[newl_ind] = orig[oldl_ind - 1]; newl_ind++; } } else if(orig[oldl_ind] == '*') { if(orig[oldl_ind-1] == ' ' || orig[oldl_ind-1] == '"' || oldl_ind == 0) { if(orig[oldl_ind+1] == ' ' || orig[oldl_ind+1] == '"' || orig[oldl_ind+1] == 0) { if(expWildCard(orig, new, &oldl_ind, &newl_ind, 0)) return 1; } else { if(expWildCard(orig, new, &oldl_ind, &newl_ind, 1)) return 1; } } else if(orig[oldl_ind-1] == '\\') { new[newl_ind-1] = '*'; oldl_ind++; } else { /*new[newl_ind] = '*'; newl_ind++; oldl_ind++;*/ if(expLiteralChars(orig, new, &oldl_ind, &newl_ind, &insideQuoteFlag)) return 1; } } else if(orig[oldl_ind] == '#' && !insideQuoteFlag) break; else if(orig[oldl_ind] == '~' && orig[oldl_ind-1] == ' ') { if(expHomeDir(orig, new, &oldl_ind, &newl_ind)) return 1; } else { /*if(orig[oldl_ind] == '"') insideQuoteFlag = !insideQuoteFlag; new[newl_ind] = orig[oldl_ind]; newl_ind++; oldl_ind++;*/ if(expLiteralChars(orig, new, &oldl_ind, &newl_ind, &insideQuoteFlag)) return 1; } } new[newl_ind] = 0; return 0; }