Skip to content

Instantly share code, notes, and snippets.

@ipodipad
Created April 14, 2019 14:08
Show Gist options
  • Save ipodipad/70ca0e6d1d477d55939a911cb29b3472 to your computer and use it in GitHub Desktop.
Save ipodipad/70ca0e6d1d477d55939a911cb29b3472 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>
#include <signal.h>
#include "smsh.h"
static char curBuf[MAXLENGTH], commBuf[20][MAXLENGTH], connect[MAXARGS];
int line = 0;
void BufFull()
{
int i;
for(i = 1; i < 20; i++)
strcpy(commBuf[i - 1], commBuf[i]);
line = 19;
}
int GetCommand()
{
int c, count, i;
printf("[smsh] ");
count = 0;
while(1)
{
if((c = getchar()) == EOF)
return (EOF);
if(count < MAXLENGTH)
{
if(line == 20)
BufFull();
commBuf[line][count++] = c;
}
if(c == '\n' && count < MAXLENGTH)
{
if(count == 1)
return 0;
commBuf[line++][count - 1] = '\0';
strcpy(curBuf, commBuf[line - 1]);
return count;
}
if(c == '\n')
{
printf("too long\n");
count = 0;
printf("[smsh] ");
}
}
}
/* 백그라운드 모드 */
int isBack()
{
int i;
for(i = 0; curBuf[i] != '\0'; i++)
{
if(curBuf[i] == '&')
{
curBuf[i] = '\0';
return 1;
}
}
return 0;
}
int Parse(char ret[], char *vec[], char parsign[])
{
int ln, count;
char *token;
count = 0;
ln = 0;
token = strtok(ret, parsign);
while(token != '\0' && ln < MAXARGS)
{
count++;
vec[ln] = token;
token = strtok('\0', parsign);
ln++;
}
vec[ln] = '\0';
count--;
return count;
}
int SinglePipe(char *Vec[])
{
int p[2], status;
char *execVec[MAXARGS];
switch(fork())
{
case -1 : fprintf(stderr, "fork error!");
break;
case 0 : if(pipe(p) < 0)
{
fprintf(stderr, "pipe error!");
return -1;
}
switch(fork())
{
case -1 : fprintf(stderr, "fork error!");
break;
case 0 : close(1);
dup(p[1]);
close(p[0]);
close(p[1]);
Parse(Vec[0], execVec, " ");
execvp(execVec[0], execVec);
default : close(0);
dup(p[0]);
close(p[0]);
close(p[1]);
Parse(Vec[1], execVec, " ");
execvp(execVec[0], execVec);
}
default : wait(&status);
break;
}
}
int PipeExec(char *Vec[], int count, int execIndex)
{
int p[MAXPIPE][2];
char *execVec[MAXARGS];
pid_t pid[MAXPIPE + 1];
if(pipe(p[count - 1]) < 0)
{
fprintf(stderr, "pipe error!");
return -1;
}
count--;
switch(fork())
{
case -1 : fprintf(stderr, "fork error!");
return -1;
case 0 : close(1);
dup(p[count][1]);
close(p[count][0]);
close(p[count][1]);
if(count > 0)
PipeExec(Vec, count, execIndex + 1);
Parse(Vec[count], execVec, " ");
execvp(execVec[0], execVec);
break;
default : close(0);
dup(p[count][0]);
close(p[count][0]);
close(p[count][1]);
if(execIndex == 1)
{
Parse(Vec[count + 1], execVec, " ");
execvp(execVec[0], execVec);
}
break;
}
return 0;
}
int IsHistory(char *Vec[])
{
if(strcmp(Vec[0], "history") == 0)
return 1;
else if(strncmp(Vec[0], "!", 1) == 0)
return 2;
else
return 0;
}
int History(char Vec[], int flag)
{
char numStr[3];
int i, exeNum;
if(flag == 1)
{
printf("== history list ==\n");
for(i = 0; i < 20; i++)
{
if(commBuf[i][0] == '\0')
break;
printf("[%2d] %s\n", i, commBuf[i]);
}
printf("== history list end ==\n");
}
else
{
for(i = 1; i < 3; i++)
{
numStr[i - 1] = Vec[i];
}
if(numStr[0] == '!')
exeNum = line - 2;
else
exeNum = atoi(numStr);
if(line == 20 && strcmp(commBuf[19], "\0") != 0)
{
exeNum--;
}
strcpy(curBuf, commBuf[exeNum]);
strcpy(commBuf[line - 1], curBuf);
printf("%s\n", curBuf);
RunCommand();
}
}
int IsDirection(char *Vec[])
{
int i;
for(i = 0; strstr(Vec[i], "\0") != '\0'; i++)
{
if(strstr(Vec[i], ">>") != '\0')
return 1;
else if(strstr(Vec[i], ">!") != '\0')
return 2;
else if(strstr(Vec[i], ">") != '\0')
return 3;
else if(strstr(Vec[i], "<") != '\0')
return 4;
}
return 0;
}
int Direction(char *Vec[], int flag)
{
int fd, nbyte, i;
char buf[1024];
char temp[MAXLENGTH];
char *vector[MAXLENGTH];
memset(temp, '\0', sizeof(temp));
for(i = 0; i < MAXARGS; i++)
{
if(strncmp(Vec[i], ">", 1) == 0 || strncmp(Vec[i], "<", 1) == 0)
break;
strcat(temp, Vec[i]);
strcat(temp, " ");
}
Parse(temp, vector, " ");
switch(flag)
{
case 1 : fd = open(Vec[i + 1], O_WRONLY | O_CREAT | O_APPEND, 0644);
switch(fork())
{
case -1 : fprintf(stderr, "fork error!");
break;
case 0 : close(1);
dup(fd);
execvp(vector[0], vector);
default : wait(0);
}
close(fd);
break;
case 2 : fd = open(Vec[i + 1], O_WRONLY | O_CREAT | O_TRUNC, 0644);
switch(fork())
{
case -1 : fprintf(stderr, "fork error!");
break;
case 0 : close(1);
dup(fd);
execvp(vector[0], vector);
default : wait(0);
}
close(fd);
break;
case 3 : fd = open(Vec[i + 1], O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0644);
switch(fork())
{
case -1 : fprintf(stderr, "fork error!");
break;
case 0 : close(1);
dup(fd);
execvp(vector[0], vector);
default : wait(0);
}
close(fd);
break;
case 4 : fd = open(Vec[i + 1], O_RDONLY);
switch(fork())
{
case -1 : fprintf(stderr, "fork error!");
break;
case 0 : close(0);
dup(fd);
execvp(vector[0], vector);
default : wait(0);
}
close(fd);
break;
}
}
int IsChdir(char *Vec[])
{
if(strncmp(Vec[0], "cd ..", 5) == 0)
return 1;
if(strncmp(Vec[0], "cd", 2) == 0)
return 2;
return 0;
}
void ChDir(char *Vec[], int flag)
{
if(flag == 1)
{
chdir("..");
}
else
{
chdir(Vec[1]);
}
}
int RunCommand()
{
int i, j, status, pipeCount, hisflag, drflag, cdflag;
char *vector[MAXARGS];
char *execVec[MAXARGS];
char *pipeVec[MAXARGS];
int pip[MAXPIPE][2];
pid_t pid, pipepid[MAXPIPE];
fd_set rset[MAXPIPE], wset[MAXPIPE];
if(isBack())
{
if((pid = fork()) < 0)
fprintf(stderr, "fork error!");
else if(pid == 0)
{
printf("[Background] Process ID : %d\n", getpid());
RunCommand();
printf("[Background] Process ID : %d --> Done\n", getpid());
exit(0);
}
else
return 0;
}
else
{
if(Parse(curBuf, vector, ";") > 0)
{
for(i = 0; i < MAXARGS; i++)
{
if(vector[i] == '\0')
break;
strcpy(curBuf, vector[i]);
RunCommand();
}
}
else if((pipeCount = Parse(curBuf, pipeVec, "|")) > 0)
{
int status;
pid_t pid;
if(pipeCount == 1)
SinglePipe(pipeVec);
else
{
if((pid = fork()) < 0)
fprintf(stderr, "fork error!");
else if(pid == 0)
PipeExec(pipeVec, pipeCount, 1);
else
waitpid(pid, &status, 0);
}
}
else
{
Parse(pipeVec[0], execVec, " ");
if(strncmp(execVec[0], "\0", 1) == 0)
return 0;
if((hisflag = IsHistory(execVec)) > 0)
History(execVec[0], hisflag);
else if((drflag = IsDirection(execVec)) > 0)
{
Direction(execVec, drflag);
return 0;
}
else if((cdflag = IsChdir(execVec)) > 0)
{
ChDir(execVec, cdflag);
}
else
{
if((pid = fork()) < 0)
fprintf(stderr, "fork error!");
else if(pid == 0)
{
execvp(execVec[0], execVec);
}
else
{
if(waitpid(pid, &status, 0) == -1)
return -1;
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment