Search
Duplicate
💡

minishell

Holy Graph
3Circle
간략한 내용
미니쉘먹으면서 미니쉘 하기..
적정 기간
210 hours
제작에 참여한 사람
진행 중인 사람
최종 편집일
Jul 10
통과한 사람
1 more property
미니쉘 맛잇당
미니쉘 하는 사람들한테는 주기적으로 미니쉘 지급해줘야됨. 당떨어짐
→ 222

0. Minishell subject!

Search
Mandatory part
이름
태그
readline, rl_on_new_line, rl_replace_line, rl_redisplay, add_history, printf, malloc, free, write, open, read, close, fork, wait, waitpid, wait3, wait4, signal, kill, exit, getcwd, chdir, stat, lstat, fstat, execve, dup, dup2, pipe, opendir, readdir, closedir, strerror, errno, isatty, ttyname, ttyslot, ioctl, getenv, tcsetattr, tcgetattr, tgetent, tgetflag, tgetnum, tgetstr, tgoto, tputs
Write a shell
COUNT5
안닫힌 ' 이나 " 는 핲 필요 없음, \ 이나 ; . 가 있으면 안됨
전역 변수 1개 만 가능
새로운 커맨드를 입력 받을때는 prompt 를 출력해야댐
History가 돼야함
PATH 변수나, 상대 경로, 절대 경로 에 있는걸 기반으로 올바르게 검색하고 실행해야한다.
구현해야할 builtin
echo (n 옵션)
cd (절대, 상대 경로만)
pwd
export
unset
env
exit
리다이렉션 되야함
파이프 있어야함
환경 변수가 작동해야함
$? 는 가장 최근 실행된 파이프라인의 종료 값이 들어가야함
ctrl-C, ctrl-D, ctrl-\ 작동해야댐
ctrl-C : prompt 출력
ctrl-D : 쉘 종료
ctrl-\ : 아무것도 안함

실행부

builtin 함수를 우선 구현해야 한다.(mantatory에 있는 함수들!)

파싱

; 없음
파싱해서 명령어와 실행문을 넘겨주어야한다.

1. 함수 정리하기!

이미 아는 함수

printf, malloc, free, write, open, read, close, exit

fork

function

fork함수를 사용하면 새로운 프로세스를 하나 호출한다.
이때, 호출하는 자식 프로세스는 부모 프로세스의 메모리를 그대로 복사하여 가진다.
그리고 fork함수 호출 이후 각자의 메모리를 사용하여 실행된다.
#include <unistd.h> //header file pid_t fork(void);
C
복사

return value

성공 시 : 부모 프로세스에서는 자식 프로세스의 PID값, 자식 프로세스에서는 0
실패 시 : -1

example

#include <stdio.h> #include <unistd.h> int main(void) { int x = 0; fork(); x = 1; printf("PID : %d, x : %d\n", getpid(), x); return (0); }
C
복사
$ ./a.out PID : 8270, x : 1 PID : 8271, x : 1
Shell
복사
결국 x 에 값을 대입할 때, fork() 명령 이전에 대입하나 이후에 대입하나 상관이 없다! fork를 하면 자식 프로세스가 부모의 메모리를 그대로 복사해서 가지기 때문. 이후 같은 작업을 각 프로세스가 개별적으로 실행한다.
또한 자식 프로세스는 fork()함수를 실행하지 않기 때문에 이때 getpid()의 return value는 0이다. 따라서 getpid()의 return value를 기준으로 자식인지 부모인지 알 수 있다.
#include <stdio.h> #include <unistd.h> int main(void) { pid_t pid; pid = fork(); if(pid > 0) // 부모 코드 printf("부모 프로세스 입니다."); else // 자식 코드 printf("자식 프로세스 입니다."); return (0); }
C
복사

wait

function

1.
자식 프로세스가 동작 중이면 상태를 얻어올 때까지 대기
2.
wait() 함수 호출자가 시그널을 받을 때까지 대기
3.
자식 프로세스가 종료된 상태라면 즉시 호출이 반환되어 상태를 얻음, 이 때 wait() 함수는 자식 프로세스의 프로세스 ID를 반환
4.
자식 프로세스가 없다면 호출이 즉시 반환되며, 에러값을 반환
#include <sys/wait.h> pid_t wait(int *statloc);
C
복사
wait()의 인자 status 를 통하여 자식 프로세스의 상태를 받아올 수 있는데,
자식프로세스의 상태값은 자식프로세스의 종료값 * 256(FF) 이다.

return value

성공 시 : PID
실패 시 : -1

example

#include <stdio.h> #include <unistd.h> #include <sys/wait.h> int main() { pid_t pidi; int status,i; pid = fork(); if (pid > 0) { pid_t waitpid; printf("부모 PID : %d\n", getpid()); waitpid = wait(&status); // 자식 프로세스의 상태를 받아올 때까지 wait! if (waitpid == -1) printf("error\n"); else { if (WIFEXITED(status)) printf("자식 프로세스 정상 종료\n"); else if (WIFSIGNALED(status)) printf("자식 프로세스 비정상 종료: %d\n", WTERMSIG(status)); } } else if(pid == 0){ // 자식 프로세스 sleep(6); printf("자식 PID : %ld \n",(long)getpid()); } else { // fork 실패 perror("fork Fail! \n"); return (-1); } return (0); }
C
복사
$ ./a.out 부모 PID : 10695 자식 PID : 10696 자식 프로세스 정상 종료
Shell
복사
wait 명령을 사용할 때 위치에 주의하여야 한다! 만약 위 코드에서 부모 pid를 출력하는 부분이 wait명령어 아래로 내려간다면, 부모 pid출력이 자식프로세스가 종료될때까지 기다렸다가 출력하게 된다.
wait()관련 함수에서 자식 프로세스의 종료 상태를 확인하기 위해서 인수로 전달했던 변수 status 값은 아래와 같이 구성되어 있다! 기존에는 255를 기준으로 비교 했었지만 아래 매크로를 활용해서 간단하게 확인할 수 있다.
Search
이름
태그
자식 프로세스가 정상적으로 종료되었다면 TRUE
자식 프로세스가 시그널에 의해 종료되었다면 TRUE
자식 프로세스가 중단되었다면 TRUE
자식 프로세스가 정상 종료되었을 때 반환한 값
자식 프로세스를 종료하도록한 신호의 번호 반환 (WIFSGNALED가 non
자식을 정지하도록 야기한 신호의 숫자를 반환
COUNT6
WIF로 시작하는 macro는 상위 바이트의 상태를 판단하는 함수이며 나머지 macro함수는 상세 값을 읽을 수 있습니다.
이제 자식 프로세스를 오랜 시간동안 실행시키고 터미널에서 kill명령으로 자식 프로세스를 종료시켜보자!
$ kill -9 13439 부모 PID : 13438, 자식 PID : 13439 자식 프로세스 비정상 종료: 9
Shell
복사

waitpid

function

waitpid()는 wait()함수와 동일하게 자식 프로세스를 기다릴 때 사용한다. 하지만 자식 프로세스가 종료될 때까지 차단되는 것을 원하지 않을 경우, 옵션을 사용하여 차단을 방지할 수 있다.
#include <sys/wait.h> //header file pid_t waitpid(pid_t pid, int *status, int options);
C
복사
pid : wait()할 자식 프로세스의 유형
pid < -1 : 그룹ID가 절대값과 같은 자식 프로세스를 기다린다
pid == -1 : 아무 자식 프로세스 ID라도 기다린다
pid == 0 : 자신과 같은 프로세스 그룹 ID를 가진 자식 프로세스를 기다린다.
pid > 0 : 인자로 넘어온 pid를 가진 자식 프로세스만 기다린다.
status : wait()함수와 동일
options : 0 혹은 상수의 조합으로 설정된다
0 : 결과를 return 할 떄까지 block한다
WNOHANG : 현재 종료된 자식 프로세스가 없으면 block하지 않고 바로 0을 반환한다
WUNTRACED : 자식 프로세스가 STOP하면 반환한다
WCONTINUED : STOP되었던 자식 프로세스가 재 실행되면 반환한다

return value

성공 시 : PID → 상태가 변경된 자식 프로세스 ID (status가 상태값 저장)
성공 시 : 0 → option이 WNUHANG인 경우 종료된 자식 프로세스가 없으면 0을 return
실패 시 : -1 → wait 중 오류가 발생, 오류 내용은 errno 전역변수에 설정

example

#include <stdio.h> #include <unistd.h> #include <sys/wait.h> int main() { pid_t pid; int status,i; pid = fork(); if (pid > 0) { pid_t waitpid; printf("부모 PID : %d, 자식 PID : %d\n", getpid(), pid); } else if(pid == 0){ // 자식 프로세스 for (int i = 0 ; i < 3 ; ++i) sleep(1); printf("자식 PID : %ld \n",(long)getpid()); printf("자식 종료\n"); } else { // fork 실패 perror("fork Fail! \n"); return -1; } pid = waitpid(pid, &status, 0); if (pid == -1 ) { printf("error\n"); } else { if (WIFEXITED(status)){ printf("프로그램에서 exited(%d) 또는 main에서 return ;하여 종료되었습니다.\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("siganl %d번이 발생하여 종료되었습니다.\n", WTERMSIG(status)); } else if (WIFSTOPPED(status)) { printf("signal %d번으로 인하여 stop되었습니다. \n", WSTOPSIG(status)); } else if (WIFCONTINUED(status)) { printf("stop된 프로세스를 진행합니다\n"); } } return 0; }
C
복사

wait3, wait4

function

wait3, wait4 함수는 사용자 시간 정보를 확인할 수 있다.
#include <sys/types.h> //header file #include <sys/wait.h> pid_t wait3(int *staloc, int options, struct rusage *rus); pid_t wait4(pid_t pid, int *staloc, int options, struct rusage *rus);
C
복사

parameters

staloc, options, pid : 위와 동일
rusage : 자식 프로세스의 리소스 사용량에 대한 정보가 담긴다. (struct rusage 형태로 담긴다)

return value

성공 시 : PID, 만약 함수가 WNOHANG 옵션으로 실행되었고, 자식 프로세스가 아직 종료되지 않았을 때, 0
실패 시 : -1

example

#include <stdio.h> #include <stdlib.h> #include <time.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/resource.h> void ViewRUsage(pid_t pid, struct rusage *pru); int main() { pid_t cpid = fork(); if(cpid == -1) { perror("error fork"); return 0; } if(cpid>0) { printf("<parent> fork child pid:%u\n",cpid); int rvalue = 0; struct rusage ru; pid_t wpid = wait3(&rvalue,0, &ru); ViewRUsage(wpid, &ru); } else { printf("<child> pid:%d \n",getpid()); int i=0,j=0; for(i=0;i<100000;i++) { fprintf(stderr,"."); } } return 0; } void ViewRUsage(pid_t pid, struct rusage *pru) { printf("\n=== pid rusage info ===\n"); struct timeval *tv = &(pru->ru_utime); printf("user CPU time used [%ld]sec [%d]usec\n", tv->tv_sec,tv->tv_usec ); tv = &(pru->ru_stime); printf("system CPU time used [%ld]sec [%d]usec\n", tv->tv_sec,tv->tv_usec ); }
C
복사

signal

프로세스가 시그널을 받게 되면
1. 시그널에 해당되는 기본 동작을 하거나
2. 그 시그널을 무시하거나
3. 사용자가 정의한 함수를 통해 동작 방식을 바꿀 수 있다.

function

위와 같은 시그널을 제어할 수 있는 함수. signal번호를 받아와 해당 signal에서의 행동을 지정할 수 있다.
#include <signal.h> //header file void (*signal(int signum, void (*handler)(int)))(int);
C
복사

parameters

signum : 시그널 번호
(*handler)(int) : 시그널을 처리할 핸들러

return value

성공 시 : void *()(int); 이전에 설정된 시그널 핸들러
실패 시 : null(?)
아래는 MacOS에 정의되어 있는 Signal들이다.
SIGKILL, SIGSTOP 등은 제어할 수 없다.

example

#include <stdio.h> #include <signal.h> #include <unistd.h> void (*old_fun)(int); void sigint_handler(int signo) { printf("signo : %d", signo); printf("Ctrl-C 키를 누르셨죠!!\n"); printf("또 누르시면 종료됩니다.\n"); signal(SIGINT, old_fun); //signal( SIGINT, SIG_DFL); } int main( void) { old_fun = signal(SIGINT, sigint_handler); // printf("asdf : %d", SIGTSTP); // printf("zxcv : %d", SIGCHLD); while (1) { printf("forum.falinux.com\n"); sleep(1); } }
C
복사

kill

function

프로세스에 시그널을 전송해주는 함수. 시그널 SIGKILL을 보내면 쉘의 kill과 같은 역할을 한다.
#include <signal.h> //header file int kill(pid_t pid, int signo)
C
복사

parameters

pid, signo : 위와 동일

return value

성공 시 : 0
실패 시 : -1

getcwd

function

현재 작업 중인 디렉토리를 가져온다
#include <unistd.h> //header file char *getcwd(char *buf, size_t size);
C
복사

parameters

buf : 현재 작업 디렉토리를 저장할 buffer. 만약 buffer가 null이면 malloc을 통해서 할당된 메모리를 사용한다. 따라서 이 경우 무조건 free를 해주어야 한다.
size : buffer에 할당된 메모리의 크기

return value

성공 시 : 포인터
실패 시 : null (오류 내용은 errno에 저장된다)

example

#include <unistd.h> #include <stdio.h> #include <limits.h> int main() { char cwd[PATH_MAX]; if (getcwd(cwd, sizeof(cwd)) != NULL) { printf("Current working dir: %s\n", cwd); } else { perror("getcwd() error"); return 1; } return 0; }
C
복사

chdir

function

작업 디렉토리 폴더 변경하기 (cd in linux)
// man 2 chdir #include <unistd.h> //header file int chdir(const char *dirname);
C
복사

return value

성공 시 : 0
실패 시 : -1

example

#include <stdio.h> #include <limits.h> #include <unistd.h> // chdir header int main(void) { char buffer[PATH_MAX] = { 0, }; char changeDir[PATH_MAX] = { "/Users/42seoul/minishell/" }; int result = chdir(changeDir); if(result == 0) printf("Success\n"); else perror("Fail...\n"); return 0; }
C
복사

stat

function

파일의 크기, 권한, 생성일시, 최종 변경일 등 파일의 상태나 정보를 얻는 함수이다.
stat(2) 함수는 symbolic link인 파일을 path로 넘기면 그 원본 파일의 정보를 얻는다.
// man 2 stat #include <sys/stat.h> //header file int stat(const char *path, struct stat *buf);
C
복사

parameters

path : 파일 명 또는 파일에 대한 상대경로/절대경로
buf : 파일의 상태 및 정보를 저장할 구조체
struct stat { dev_t st_dev; ino_t st_ino; mode_t st_mode; nlink_t st_nlink; uid_t st_uid; gid_t st_gid; dev_t st_rdev; off_t st_size; blksize_t st_blksize; blkcnt_t st_blocks; time_t st_atime; tiem_t st_mtime; time_t st_ctime; };
C
복사

return value

성공 시 : 0
실패 시 : -1

example

상세 예시는 아래 블로그를 가면 확인할 수 있다.

lstat, fstat

#include <unistd.h> int lstat(const char *path, struct stat *buf); int fstat(int fd, struct stat *buf);
C
복사
lstat : symbolic link인 파일 자체의 정보를 얻는다. 나머지는 같다.
fstat : 인자로 가져온 fd(열려있는 file)의 정보를 얻어온다. 나머지는 같다.

execve

function

실행가능한 파일인 filename의 실행 코드를 현재 프로세스에 적재하여 기존의 실행 코드와 교체하여 새로운 기능으로 실행한다.  즉, 현재 실행되는 프로그램의 기능은 없어지고 filename 프로그램을 메모리에 Loading하여 처음부터 실행한다.
#include <unistd.h> //header file int execve(const char *filename, char *const argv[], char *const envp[]);
C
복사

parameters

filename : 교체할 실행 파일 / 명령어. path와 명령어가 합쳐진 형태라고 생각하면 편함
ex) "usr/bin/ls"
argv : execve에는 argc가 없으므로 array의 마지막 원소 다음은 NULL이 있다
envp : key = value 형태의 환경변수 문자열 배열 리스트. 마지막은 NULL. 만약 이미 설정된 환경변수를 사용하려면 environ 전역변수를 그냥 사용한다.

return value

성공 시 : 없음 (이미 지정된 프로그램의 로직으로 실행되기 때문에 return을 받을 수 없다)
실패 시 : -1
명령어 위치를 찾아보자 which "명령어" → 만약 alias가 되어 있으면 해제하고 확인 해야 한다.

example

#include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <errno.h> extern char **environ; int main(int argc, char *argv[], char **envp) { char **new_argv; char command[] = "ls"; int idx; new_argv = malloc(sizeof(char *) * argc + 1); // 명령어를 ls로 변경 new_argv[0] = command; // command line으로 넘어온 parameter를 그대로 사용 for (idx = 1 ; idx < argc ; ++idx) new_argv[idx] = argv[idx]; // argc를 execve 파라미터에 전달할 수 없기 때문에 NULL을 끝으로 지정해우저야 함 new_argv[argc] = NULL; if (execve("/bin/ls", new_argv, environ) == -1){ fprintf(stderr, "프로그램 실행 error: %s\n", strerror(errno)); return 1; } printf("이후 로직은 실행되지 않습니다..\n"); return (0); }
C
복사

dup

function

파일 디스크립터를 복제하여 다른 파일 디스크립터 생성
#include <unistd.h> //header file int dup(int file_des);
C
복사

parameters

file_des : 파일 디스크립터

return value

성공 시 : 파일 디스크립터
실패 시 : -1

example

#include <unistd.h> // dup header file #include <fcntl.h> #include <stdio.h> #include <stdlib.h> int main(void) { int fd1, fd2; if ((fd1 = open("file_1.txt", O_RDONLY)) < 0) { printf("file open error\n"); exit(0); } fd2 = dup(fd1); printf("fd1 : %d, fd2 : %d\n", fd1, fd2); close(fd1); close(fd2); return (0); }
C
복사
항상 낮은 서술자를 반환함

dup2

function

fd2 에 기존의 파일 디스크립터를 복제.
만일 fd2가 이미 열려있으면 fd2를 닫은 후 복제.
#include <unistd.h> //header file int dup2(int file_des1, int file_des2);
C
복사

parameters

file_des : 기존의 파일 디스크립터
file_des2 : 새로운 파일 디스크립터

return value

성공 시 : -1 이외의 값
실패 시 : -1

example

int main(void) { int fd; if ((fd = open("file_1.txt", O_RDONLY)) < 0){ printf("file open error\n"); exit(0); } +- /* 표준 출력을 file_1.txt 파일로 redirection 함 */ dup2(fd, 1); /* 표준 오류를 file_1.txt 파일로 redirection 함 */ dup2(fd, 2); close(fd); return (1); }
C
복사

pipe

function

서로 독립된 프로세스들이 데이터를 주고 받을 수 있게 도와준다.
#include <unistd.h> //header file int pipe(int fd[2]);
C
복사

parameters

fd[0] : 함수 호출 후 fd[0]에 데이터를 입력 받을 수 있는 fd가 담김(파이프 출구)
fd[1] : 함수 호출 후 fd[1]에 데이터를 출력할 수 있는 fd가 담김(파이프 입구)

return value

성공 시 : 0
실패 시 : -1

example

#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h> int pipes[2] ; void parent_proc() { char * buf = 0x0; ssize_t s; size_t len = 0; // 읽기용 파이프를 닫는다 close(pipes[0]); while ((s = getline(&buf, &len, stdin)) != -1) { buf[s - 1] = 0x0; ssize_t sent = 0; char * data = buf; while (sent < s) { sent += write(pipes[1], buf + sent, s - sent); } free(buf); buf = 0x0; len = 0; } close(pipes[1]); } void child_proc() { char buf[32]; ssize_t s; // 쓰기용 파이프를 닫는다 close(pipes[1]); while ((s = read(pipes[0], buf, 31)) > 0) { buf[s + 1] = 0x0; printf(">%s\n", buf); } exit(0); } int main() { pid_t child_pid; int exit_code; if (pipe(pipes) != 0) { perror("Error"); exit(1); } printf("%d %d\n", pipes[0], pipes[1]); child_pid = fork(); if (child_pid == 0) child_proc(); else parent_proc(); return (0); }
C
복사

opendir

function

디렉토리 열기
#include <dirent.h> // header file DIR * opendir(const char * name);
C
복사

parameters

name : open 할 디렉토리의 이름

return value

성공 시 : DIR 포인터 디렉토리 정보 구조체 포인터
실패 시 : NULL

readdir

function

디렉토리 내에 있는 모든 파일과 디렉토리 정보 구하기
#include <dirent.h> // header file struct dirent *readdir(DIR *dirp);
C
복사

parameters

dirp : open 할때 반환되는 DIR 포인터

return value

성공 시 : 디렉토리내의 파일/디렉토리에 대한 정보를 가진 구조체 포인터
실패 시 : NULL
readdir()을 처음 호출하면 opendir()를 통해 연 디렉토리 내의 첫번째 파일에 대한 정보를 가져오고, 다시 호출시 두번째 파일에 대한 정보, 다시 호출시 세번째 파일을 호출,,, 하다가 더이상 파일이나 디렉토리가 없으면 NULL 반환

closedir

function

디렉토리 닫기
#include <dirent.h> // header file int closedir(DIR *dirp);
C
복사

parameters

dirp : open 할때 반환되는 DIR 포인터

return value

성공 시 : 0
실패 시 : -1

example (opendir/readdir/closedir)

#include <dirent.h> #include <stdio.h> #include <unistd.h> #include <sys/stat.h> int main() { DIR *dir_info; struct dirent *dir_entry; mkdir("test_A", 0755); // 실행파일이 있는 곳에 dir 생성 mkdir("test_B", 0755); dir_info = opendir("."); // 현재 디렉토리 열기 if (dir_info) { while((dir_entry = readdir(dir_info))) // 디렉토리 안에 있는 모든 파일과 디렉토리 출력 printf("%s\n", dir_entry->d_name); // d_name : 읽힌 디렉토리/파일의 이름 저장 closedir(dir_info); } return (0); }
C
복사

strerror

function

시스템 오류 번호에 대한 오류 메세지를 문자열로 반환하는 함수이다.
#include <string.h> char *strerror(int errnum);
C
복사

parameters

errnum : 오류 번호

return value

성공 시 : 오류 번호와 일치하는 오류 메세지 문자열
실패 시 : NULL or "Unknown error nnn"

example

#include <errno.h> #include <string.h> #include <stdio.h> int main(int argc, char **argv) { FILE *fp; if ((fp = fopen(argv[1], "r")) == NULL) { fprintf(stderr, "errno[%d] : %s\n", errno, strerror(errno)); return (1); } return (0); }
C
복사

errno

마지막으로 발생한 에러 번호
#include <errno.h> extern int errno;
C
복사

isatty

function

매개변수로 넣은
#include <unistd.h> int isatty(int fildes);
C
복사

parameters

fildes : fd, 파일디스크립터

return value

성공 시 : 1 (터미널에 연결되어 있는 경우)
실패 시 : 0

example

코드 실행 전 현재 pc에 어떤 tty파일들이 있는지 확인해보자
$ cd /dev $ ls
C
복사
tty(teletypewriter) 리눅스 디바이스 드라이브 중에서 콘솔이나 터미널을 의미
#include <stdio.h> #include <unistd.h> #include <fcntl.h> int main() { int fd; printf("%d\n", isatty(0)); fd = open("/dev/ttyp0",O_RDONLY); printf("fd : %d, %d\n", fd, isatty(fd)); return (0); }
C
복사

ttyname

function

fd에 대한 터미널 이름을 얻어온다.
#include <unistd.h> char *ttyname(int desc);
C
복사

parameters

desc : fd

return value

성공 시 : 터미널 이름, 없으면 "(null)"
실패 시 : NULL

example

#include <unistd.h> #include <stdio.h> int main(void) { printf("your tty name is : %s\n", ttyname(0)); printf("your tty name is : %s\n", ttyname(1)); printf("your tty name is : %s\n", ttyname(2)); return (0); }
C
복사
➜ funcStudy git:(main) ✗ ./a.out your tty name is : /dev/ttys008 your tty name is : /dev/ttys008 your tty name is : /dev/ttys008
Shell
복사

ttyslot

function

ttyslot - find the slot of the current user's terminal in somefile
#include <unistd.h> int ttyslot(void);
C
복사

return value

성공 시 : slot number
실패 시 : 0, -1

example

C
복사
ioctl
getenv
tcsetattr
tcgetattr

tgetent

function

커서 제어를 위해서는 termcap 라이브러리를 사용해야 한다.
라이브러리 사용을 위한 세팅은 tgetent() 함수로 시작된다.
termcap 라이브러리를 사용할 경우 컴파일 시 -lncurses 옵션을 붙여주어야 한다.
#include <curses.h> #include <term.h> int tgetent(char *bp, const char *name);
C
복사

parameters

bp : 버퍼 포인터
name : 루틴이름(?)

return value

성공 시 : 1
해당항목이 없을 경우 : 0
terminfo 데이터베이스를 찾을 수 없는 경우 : -1

example

#include <termcap.h> char *env = getenv("TERM"); //TERM 설정을 가져옴 if (env == NULL) env = "xterm"; //대부분 기본값은 xterm tgetent(NULL, env); // xterm 설정을 사용하도록 초기화 char *cm = tgetstr("cm", NULL); // cursor motion char *ce = tgetstr("ce", NULL); // 현재 커서 위치에서 한 줄의 끝까지 지우기
C
복사

tgetflag

function

??
#include <curses.h> int tgetflag(char id[2]);
C
복사

parameters

id : ??

return value

성공 시 : the boolean entry for id
실패 시 : 0

tgetnum

function

??
#include <curses.h> int tgetnum(char id[2]);
C
복사

parameters

id : ??

return value

성공 시 : the numeric entry for id
실패 시 : -1

tgetstr

function

사용할 수 있는 루틴을 가져옴
#include <curses.h> char *tgetstr(char id[2], char **area);
C
복사

parameters

id : ??
area : ??

return value

성공 시 : the string entry for id
실패 시 : 0

tgoto

function

동작 실행에 필요한 명령을 받기
#include <curses.h> char *tgoto(char *cap,int col,int row);
C
복사

parameters

cap : 명령어
col : 이동할 행
row : 이동할 열

return value

성공 시 : ??
실패 시 : ??

example

// (5, 5) 위치로 커서를 옮기기 // 터미널 창의 가장 왼쪽 위가 (0, 0) #include <unistd.h> #include <termcap.h> int putchar_tc(int tc) { write(1, &tc, 1); return (0); } int main(void) { tgetent(NULL, "xterm"); char *cm = tgetstr("cm", NULL); tputs(tgoto(cm, 5, 5), 1, putchar_tc); // (5, 5) 위치로 이동하는(cm - cursor motion) 명령을 tputs에 전달하여 실행 } // ce 명령의 경우 tgoto 없이 바로 tputs(ce, 1, putchar_tc)의 형식으로 사용해주면 된다. // 예시 : tputs에 있음
C
복사

tputs

function

동작 실행 하기
#include <curses.h> int tputs(const char *str, int affcnt, int (*putc)(int));
C
복사

parameters

str : ??
affcnt : ??
putc : ??

return value

성공 시 : ??
실패 시 : ??

example

// ce - clear line from cursor 명령 #include <unistd.h> #include <termcap.h> int putchar_tc(int tc) { write(1, &tc, 1); return (0); } int main(void) { tgetent(NULL, "xterm"); char *cm = tgetstr("cm", NULL); tputs(ce, 1, putchar_tc); }
C
복사

2. 명령어 정리하기!

echo (-n 옵션)

C언어에서의 printf 와 같은 역할을 함.
1) 옵션 없이 → 에코 후 개행출력
\ 를 만나도 특별하게 해석하지 않고 문자 그대로 출력
2) -n 옵션 → 에코 후 개행하지 않음
testcase → 무조건 돌려볼 것...
echo echo hello echo -n hello echo hello -n echo -nnn hello echo -n-n hello echo -nnn hello -n echo -nnn -n hello echo - echo - - echo -- echo -n -n -nhjk hello echo -n -n -n -n -n hello echo "hello World" echo "hello World" echo \\\"\'''\"
Plain Text
복사

cd (상대경로 또는 절대경로만)

"change directory"의 약자로 특정 디렉토리로 이동하고 싶을 때 사용.
cd 뒤에 가고 싶은 디렉토리 경로를 입력.
cd / : 루트 디렉토리로 이동 (절대 경로)
cd /home/pi : /home/pi 로 이동 (상대 경로)

pwd (옵션 없이)

"print working directory"의 약자로 현재 작업 중인 디렉토리의 절대 경로를 반환

export (옵션 없이)

사용자 환경 변수를 전역 변수로 설정 (변수명에 공백이 있으면 안됨)
# 예시 export <변수명>=<> : export JAVA_HOME=/user/lib/java-7-openjdk-amd64/
Shell
복사
# 짜증나는 예시 export a #key값만 생성 export b= #value에 아무 값 없음 export c=hello export c+=world #환경변수 뒤에 덧붙이기 export d="oh my god" #echo출력과 export출력 다름 export e=elephant f=flower
Bash
복사
echo로 출력
(매개변수 없는 export) 출력결과

unset (옵션 없이)

변수를 제거
# 예시 [root@wiki ~] str="hello world" [root@wiki ~] echo $str hello world [root@wiki ~] unset str [root@wiki ~] echo $str [root@zetawiki ~]
Shell
복사

env (옵션과 매개변수 없이)

전역 변수 설정 및 조회

exit (옵션 없이)

shell 종료

', " (따옴표)

<, >, >> (리디렉션)

- file descriptor aggregation을 제외하고 bash에서처럼 작동
< : 입력 리다이렉션
> : 출력 리다이렉션 - 출력된 파일은 존재하지 않을 경우 자동생성 - 만약 이미 존재하는 경우 덮어쓰기
>> : > 와 같지만 이미 파일이 존재하는 경우 데이터를 추가한다

<<

연산자의 오른쪽에 지정된 것이 한 줄 (예 : EOF)에서 충족 될 때까지 줄 바꿈을 포함한 사용자 입력을 가져옵니다.
EOF 값을 제외하고 읽은 모든 것을 왼쪽 프로그램의 표준 입력으로 보냅니다.
cat << EOF > Hello > World > EOF --result-- Hello World
Shell
복사

| (파이프)

command1 | command2 와 같은 형태로 사용되고, command1의 표준 출력command2의 표준 입력으로 전달. (&를 붙이면 표준 에러도 함께 전달)

$char (메타)

Ctrl + C, D, \ (스크립트 제어)

3. 평가 정리

4. 참고할만한 링크