// Mitnick Shell Version 2.0 // by Dmitry Melnik #include #include #include #include #include #include #include #include #include //#include #define RIGHTS 0644 #define BUF_SIZE 255 //#define _DEBUG_ 1 char finish, err; // Считывает строку с stdin, печатая перед этим prompt char *readline(const char *prompt) { char *s; printf(prompt); s = (char *) malloc(BUF_SIZE); fgets(s, BUF_SIZE, stdin); if (s[strlen(s)-1]=='\n') s[strlen(s)-1]=0; return s; } char **explode(char *s1, int len) { char st, *p, rd; char **r; char s[BUF_SIZE]; int count=0, scount=0; p=s1; st=0; rd=0; for (p=s1; p')&&!rd) { rd=1; st=1; if (count) { s[scount++]=0; r[count-1]=(char*)malloc(strlen(s)); strcpy(r[count-1], s); } scount=0; count++; if (count==1) { r=(char**)malloc(sizeof(char**) * count); } else r=(char**)realloc(r, sizeof(char**) * count); // s[scount++]=*p; } else rd=0; s[scount++]=*p; } } else { if (*p!=' '&&*p!=9) { if (*p=='<'||*p=='>') rd=1; else rd=0; st=1; scount=0; count++; if (count==1) { r=(char**)malloc(sizeof(char**) * count); } else r=(char**)realloc(r, sizeof(char**) * count); s[scount++]=*p; } } } if (st) { s[scount++]=0; r[count-1]=(char*)malloc(strlen(s)); strcpy(r[count-1], s); } r=(char**)realloc(r, sizeof(char**) * (count+1)); r[count]=NULL; return r; } int prog_mv(int argc, char **argv) { // printf("%d\n", argc); if (argc<3) { printf("Usage: mv file1 file2\n"); return 2; } if (rename(argv[1], argv[2])<0) { perror("mv"); return 2; } return 0; } int prog_cmp(int argc, char **argv) { FILE *f1, *f2; char b1[BUF_SIZE], b2[BUF_SIZE]; char e1, e2; int rv, line, s; rv=0; line=0; if (argc<3) { fprintf(stderr, "Usage: cmp file1 file2\n"); return 2; } f1 = fopen(argv[1], "rt"); f2 = fopen(argv[2], "rt"); if (!f1 || !f2) { perror("cmp"); return 2; } for (;;) { fgets(b1, BUF_SIZE, f1); fgets(b2, BUF_SIZE, f2); e1=feof(f1); e2=feof(f2); if (e1||e2) { if (e1&&e2) { rv=0; break; } else if (e1) fprintf(stderr, "cmp: EOF on %s\n", argv[1]); else fprintf(stderr, "cmp: EOF on %s\n", argv[2]); rv=1; break; } line++; s=strspn(b1, b2); if (b1[s]) { printf("%s %s differ: char %d, line %d\n", argv[1], argv[2], s+1, line); rv=1; break; } } fclose(f1); fclose(f2); return rv; } int prog_od(int argc, char **argv) { char *fname, oct, c; int count; FILE *f; oct=0; if (argc<2) { printf("Usage: od [-b] file\n"); return 2; } if (!strcmp(argv[1], "-b")) oct=1; fname = argv[oct?2:1]; f = fopen(fname, "rt"); if (!f) { perror("od"); return 2; } count = 0; // fscanf(f, "%c", &c); // while (!feof(f)) { while (fscanf(f, "%c", &c)>0) { if (!(count%10)) printf("%07d ", count); if (oct) { printf(" %03o", c); } else { if (c>=32) printf(" %c", c); else printf(" .", c); } // fscanf(f, "%c", &c); if (!((count+1)%10)) printf("\n"); count++; } // Если закончилось на числе, кратном 10, \n и так напечаталось if (count%10) printf("\n"); printf("%07d\n", count); fclose(f); return 0; } int run_cmd(char *path, char **args) { int code, argc; // Считаем параметры argc=0; while (args[++argc]); if (!strcmp(path, "mv")) code = prog_mv(argc, args); else if (!strcmp(path, "cmp")) code = prog_cmp(argc, args); else if (!strcmp(path, "od")) code = prog_od(argc, args); else { execvp(args[0], args); perror("Error"); return 1; } exit(code); } int parse_cmd(char *s, int len, int in, int out, int wt) { int l=len; int pid, code; char **args, c; int i, j; char *p, append; #ifdef _DEBUG_ p=s; printf("cmd (in %d, out %d, len %d): ", in, out, len); while (l--) putchar(*p++); printf("\n"); #endif if (!len) return 0; args = explode(s, len); #ifdef _DEBUG_ i=0; printf("exec: %s\n", s); while (args[i]) { printf("%d:*%s*\n", i, args[i]); i++; } #endif i=0; append=0; while (args[i]) { c=args[i][0]; if (c=='>'||c=='<') { if (args[i][1]=='>') { if (c=='<') { printf("Syntax error\n"); return -1; } p=&args[i][2]; append=1; } else { p=&args[i][1]; append=0; } // if (!*p) p=args[i+1]; j=i; while (args[j]) { args[j]=args[j+1]; j++; } i--; if (c=='<') { if (in>0) { printf("Syntax error\n"); return -1; } in=open(p, O_RDONLY, 0); if (in<0) { perror("< : Can't open file"); return -1; } } if (c=='>') { if (out!=1) { printf("Syntax error\n"); return -1; } #ifdef _DEBUG_ printf("redir file: *%s*\n", p); #endif if (append) { // Если файла не существует if (open(p, O_RDONLY, 0)<0) { out=creat(p, RIGHTS); } else { out=open(p, O_WRONLY|O_APPEND, RIGHTS); } } else out=creat(p, RIGHTS); if (out<0) { if (append) perror(">> : Can't open file"); else perror("> : Can't open file"); return -1; } } } i++; } if (!strcmp(args[0], "exit")) { finish=1; return 0; } pid = fork(); if (pid) { if (in!=0) close(in); if (out!=1) close(out); if (wt) { int stat; waitpid(pid, &stat, 0); while (waitpid(-1, NULL, WNOHANG)>0); return WEXITSTATUS(stat); } else return 0; } else { if (in!=0) { dup2(in, 0); close(in); } if (out!=1) { dup2(out, 1); close(out); } return run_cmd(args[0], args); // return run_cmd(args[0], args); } return 0; } int parse_conv(char *s, int len, int in, int out, int count) { char *p; #ifdef _DEBUG_ int l=len; p=s; printf("conv: "); while (l--) putchar(*p++); printf("\n"); #endif p = strstr(s, "|"); if (!p || p>s+len) { #ifdef _DEBUG_ printf("no pipes.\n"); #endif return parse_cmd(s, len, in, 1, 1); } else { char code; int fd[2]; pipe(fd); code = parse_cmd(s, p-s, in, fd[1], 0); if (!code) { return parse_conv(p+1, len-(p-s+1), fd[0], 1, count+1); } else { return code; } } } // Обрабатывает двойные амперсанды && int parse_and(char *s, int len) { char *p; p = strstr(s, "&&"); if (!p || p>=s+len) { return parse_conv(s, len, 0, 1, 0); } else { char code; code = parse_conv(s, p-s, 0, 1, 0); if (!code) { return parse_and(p+2, len-(p-s+2)); } else { return code; } } } // Парсит строку на наличие амперсанда, bg - внутренний флаг, указывает на // необходимость запуска в фоновом режиме int parse_str(char *s, char bg) { char *p; p = s + strlen(s)-1; //printf("%c = ", *p); while (p>=s && (*p==' '||*p==9)) p--; //printf("%s ** %s\n", s, p); if (*p=='&') { if (bg) { err=1; return 0; } else { *p = 0; return parse_str(s, 1); } } else { if (bg) { int pid; pid = fork(); if (pid) { printf("Child PID: %d\n", pid); return 0; } else { finish = 1; return parse_and(s, strlen(s)); } } else { return parse_and(s, strlen(s)); } } } int main() { // char s[]=" 1 23 456 7 8908 "; /* char s[]="1 < 2 > > 3 >> 2 > 1 >>1 >1"; char **r = explode(s, strlen(s)); int i=0; while (r[i]) { printf("%d:*%s*\n", i, r[i]); i++; }*/ finish = 0; do { char *s; err = 0; s = readline("$ "); while (waitpid(-1, NULL, WNOHANG)>0); parse_str(s, 0); if (err) { printf("Syntax error !\n"); } free(s); } while (!finish); return 0; }