STDIN _IO_FILE structure <_IO_2_1_stdin_> & fgets VS argv
STDIO
Note ) 파이프와 STDIO는 다르다!파이프는 키보드나 모니터같은 하드웨어 장치와 프로세스를 연결하는 방법이 아니라, 한 프로세스의 stdout을 다른 프로세스의 stdin으로 연결하는 IPC 방법이다. 따라서 STDIO는 pipe 구조로 이루어져 있는 것이 아니다! pipe에 접근하든 STDIO에 접근하든 file philosophy에 의해 `` fd``를 이용해 접근하기 때문에 착각할 수 있음.
fgets의 stdin 처리
_IO_FILE structure
stdin 객체 `` <_IO_2_1_stdin_>``은 `` _IO_FILE`` type이다. `` _IO_FILE``은 /usr/include/libio.h에 정의되어 있다.
```c
struct _IO_FILE {
int _flags; /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags
/* The following pointers correspond to the C++ streambuf protocol. */
/* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
char* _IO_read_ptr; /* Current read pointer */
char* _IO_read_end; /* End of get area. */
char* _IO_read_base; /* Start of putback+get area. */
char* _IO_write_base; /* Start of put area. */
char* _IO_write_ptr; /* Current put pointer. */
...
}
```
첫번째는 flag,
두번째는 현재 읽어야할 위치,
세번째는 get area의 끝,
네번째는 get area의 시작점이다.
get area가 흔히 말하는 입력 버퍼다.
( fgets 수행 이후에는 버퍼를 읽었기 때문에 두번째와 세번째값이 같아진다. )
stdin으로 넘긴 데이터는 네번째 entry ~ 세번째 entry 공간에 존재한다는 것을 알 수 있다.
입력 버퍼 초기화
fgets / read / argv
``c strcpy()``는 origin data에 `` 0x00``이 있는지만 따져보면 된다.참고 ) ``c strcpy()`` 시 알아서 `` 0x00``을 넣어준다.
fgets
- 입력 데이터에 0x0a가 있는지 따져보아야 한다.
- EOF 또는 개행문자(0x0a)를 입력하지 않는 경우 계속 입력을 대기하기 때문에 특히 소켓을 사용할 때 끝에 ``c \n``을 보내주어야 한다.
이 때 입력한 \n(0x0a) 까지 포함해서 받기 때문에 당연히 문자열 끝에 0x00이 들어갈 거라고 생각하면 안된다. - EOF와 개행문자(0x0a)만 인식하므로 공백(0x20)이나 0x00도 모두 받을 수 있다.
\x00
제대로 들어간다.
```bash
$ python -c 'print "abc"+"\x00"+"def"' | ./2
0xfee84cf0 61 62 63 00 64 65 66 0a 00 4d e8 fe 56 86 04 08 abc.def..M..V...
```
\x20
제대로 들어간다.
```bash
$ python -c 'print "abc"+"\x20"+"def"' | ./2
0xfee8b390 61 62 63 20 64 65 66 0a 00 b3 e8 fe 56 86 04 08 abc def.....V...
```
\x0a
\x0a까지만 들어간다.
```bash
$ python -c 'print "abc"+"\x0a"+"def"' | ./2
0xfefa6e90 61 62 63 0a 00 00 00 00 b8 6e fa fe 56 86 04 08 abc......n..V...
```
read
- 버퍼에 있는 데이터가 `` nbytes`` 보다 작은 경우 모두 읽어오고 종료
- 버퍼에 있는 데이터가 `` nbytes`` 보다 큰 경우 `` nbytes``만큼 읽어오고 종료
```bash
argv
- 입력 데이터에 0x00, 0x20, 0x0a가 있는지 따져보아야 한다.
Note ) argv에 ``c \x00`` 넘기는 법 : ``bash ./aaa ""``
``c \x20 | \x0a``도 같은 방법으로 넘기면 된다.
\x00
\x00은 그냥 무시하고 끝까지 들어간다.
```bash
$ ./1 `python -c 'print "abc"+"\x00"+"def"'`
0xfef1cc41 61 62 63 64 65 66 00 48 4f 53 54 4e 41 4d 45 3d abcdef.HOSTNAME=
```
\x20
\x20이 \x00으로 바뀌지만 끝까지 들어간다.
* `` \x20``을 argv 구분자로 사용하기 때문. 즉 ``c argv[1] == "abc", argv[2] == "def"``
```bash
$ ./1 `python -c 'print "abc"+"\x20"+"def"'`
0xfef4fc40 61 62 63 00 64 65 66 00 48 4f 53 54 4e 41 4d 45 abc.def.HOSTNAME
```
\x0a
\x0a가 \x00으로 바뀌지만 끝까지 들어간다.
* \x20과 같다.
```bash
$ ./1 `python -c 'print "abc"+"\x0a"+"def"'`
0xfef01c40 61 62 63 00 64 65 66 00 48 4f 53 54 4e 41 4d 45 abc.def.HOSTNAME
```
'OS > LINUX & UNIX' 카테고리의 다른 글
libc 버전 문제 (0) | 2017.07.23 |
---|---|
SSH Server 설정 (0) | 2017.05.22 |
[*-nix] 패키지 관련 및 OS update & upgrade (0) | 2017.04.13 |
[procfs_search.h] 메모리에서 특정 값의 주소 찾기 (0) | 2017.03.08 |
생성자, 소멸자 low-level (0) | 2017.01.13 |