대화형 응용프로그램을 작성하다보니 터미널 설정까지 봐야하는 일이 생겼다.
프로그램을 일반적으로 수행한 것인지 쉘스크립트에서 스크립팅 용도로 수행한 것인지 구별할 방법이 필요했다.
예를 들면 쉘 스크립트로 아래와 같이 작성했을 때이다.

#!/bin/bash
./tcgetattr << EOF
EOF

일반 적으로 수행 되었을 때는 프롬프트를 띄우고 싶었고, 스크립팅일 경우에는 프롬프트를 띄우기 싫었다. 그래서 어떤 환경인지 구분할 무언가가 필요했는데 tcgetattr 함수를 이용하니 해결이 가능했다.
리눅스 환경에서 어떤 프로그램이 수행될 때 /proc/[PID]/fd 경로를 보면 대충 아래와 같이 파일이 생성된다.

$ ll
합계 0
dr-x------ 2 fhan smrf  0 2015-04-10 18:29 ./
dr-xr-xr-x 8 fhan smrf  0 2015-04-10 13:02 ../
lrwx------ 1 fhan smrf 64 2015-04-10 18:29 0 -> /dev/pts/0
lrwx------ 1 fhan smrf 64 2015-04-10 18:29 1 -> /dev/pts/0
lrwx------ 1 fhan smrf 64 2015-04-10 18:29 2 -> /dev/pts/0

위에서 보는 바와 같이 0번(stdin), 1번(stdout), 2번(stderr)이 모두 /dev/pts라는 장치로 연결되어있다.
하지만 스크립팅을 통해 수행을 한다면 다르다.  아래와 같이 0번(stdin)이 /tmp/에 생성된 파일로 연결되어있다.

$ ll
합계 0
dr-x------ 2 fhan smrf  0 2015-04-10 18:34 ./
dr-xr-xr-x 8 fhan smrf  0 2015-04-10 18:34 ../
lr-x------ 1 fhan smrf 64 2015-04-10 18:34 0 -> /tmp/sh-thd-1428667350 (deleted)
lrwx------ 1 fhan smrf 64 2015-04-10 18:34 1 -> /dev/pts/0
lrwx------ 1 fhan smrf 64 2015-04-10 18:34 2 -> /dev/pts/0

이렇게 /proc 경로를 확인해보는 방법을 선택할 수도 있겠지만 이쁘지 않다. 이 때, tcgetattr 함수를 사용하면 분별할 수 있는 값을 알려준다.

#include <termios.h>
#include <unistd.h>
#include <stdio.h>

int main()
{
    int rc=0;
    struct termios t;
    rc = tcgetattr( 0, &t );
    printf("[%d] FLAG=[%d]\n", rc, t.c_iflag);
    return 0;
}

수행 결과는 아래와 같다.

$ ./tcgetattr
[0] FLAG=[1280]

$ sh tcgetattr.sh
[-1] FLAG=[419322856]

tcgetattr 함수의 리턴값을 이용하면 간단하다.

C프로그램 안에서 OS명령을 수행하는 방법은 여러가지가 있는데 그 중 system이란 함수가 있다.

난 보통 이 함수를 이용해서 OS명령을 수행하는데 system 함수를 통해 수행한 명령의 리턴값이 필요할 때가 있다.

이전에는 몰랐지만 그냥 system 함수의 리턴값을 사용하면 된다.

int          sRet = 0;
sRet = system( "diff a b" );
이런 식으로 리턴값을 받아와서 결과에 따른 핸들링이 가능하다. 특이 점으로는 위에서 예를 들은 diff 명령의 리턴값은 0,1,2인데 변수에 담아서 확인 해보면 0, 256, 512로 나온다.

데이터베이스를 구축하는데 있어 자료구조는 공간관리 파트에서만 하면 될 줄 알았는데..
내 작업 범위에 자료구조의 이해가 필요한 부분이 있었다.
lr parser가 아직 미구현되어 있어 대충 if ~ then ~으로 비슷하게 동작하는 parser를 구현해두었는데 여기서 offset을 입력해야 한다.
이에 대해 정확하게 하기 위해 조금 알아보니 시스템 별로 다르기도 하단다;;;;;
여튼 일단은 linux에서 구현하는 중이라 linux에 국한된 offset 계산법을 알아야 한다.
이를 공부하기 위해서 문헌을 찾아보는게 가장 좋지만 몸으로 계산해서 규칙을 찾아내 보려고 한다.
물론 대강의 규칙은 수석연구원분이 이미 알려주셨기에 가능했다.
offset을 알아내는데 쓰인 offsetof 매크로이다. 간단한 예제를 아래와 같이 작성했다.

#include <stddef.h>
#include <stdio.h>

struct foo 
{
    short       s;
    int         i;
    double      d;
    float       f;
    long        l;
    char        c[10];
};


int main()
{
    printf("short  size:%lu offset:%lu\n", (unsigned long)sizeof(short), (unsigned long)offsetof(struct foo, s));
    printf("int    size:%lu offset:%lu\n", (unsigned long)sizeof(int), (unsigned long)offsetof(struct foo, i));
    printf("double size:%lu offset:%lu\n", (unsigned long)sizeof(double), (unsigned long)offsetof(struct foo, d));
    printf("float  size:%lu offset:%lu\n", (unsigned long)sizeof(float), (unsigned long)offsetof(struct foo, f));
    printf("long   size:%lu offset:%lu\n", (unsigned long)sizeof(long), (unsigned long)offsetof(struct foo, l));
    printf("char   size:%lu offset:%lu\n", (unsigned long)sizeof(char[10]), (unsigned long)offsetof(struct foo, c));
    return 0;
}

문자열에서 특정 문자의 위치를 찾는 함수로 strchr이 있다. 단점이라 하면 한글자의 문자만 찾을 수 있는 것 같다.
원형이 아래와 같다.

char* strchr(const* s, int c);

대충 간단하게 아래 예제와 같이 쓰면 된다. 문자열에서 검색할 문자가 검색되지 않는다면 NULL을 리턴한다. strrchr은 뒤부터 검색하여 위치를 알려준다. 또, memchr이란 함수도 있는데 비슷할거라 생각한다.

#include <string.h>
void main()
{
    char string[] = "abcdcfg";
    char* i;

    i=strchr( string, 'c' );
    printf("##%d, %s\n", i-string, i);
    i=strrchr( string, 'c' );
    printf("##%d, %s\n", i-string, i);

}

strtok을 사용하다가 1번만 자른 뒤 나머지가 필요한 경우가 생겼다.
그래서 뒤적이다 보니 strsep라는 또다른 분리 함수를 찾았다. 하지만 이걸로도 해결은 불가능 했다.
원했던 만큼만 분리 후 나머지를 취할 수는 있었지만 strtok과는 다르게 구분자로 된 문자열을 통째로 분리하지 못했다. 이전에 포스팅 했던 strtok 샘플과 비교해보면 눈에 띄는 차이를 알 수 있다.
샘플은 이전 strtok 때 썼던 것을 재사용했다.

#include <STRING.H>  
int main( ) 
{ 
    char* token = NULL; 
    char* str = NULL;
    char str1[] = " ! This is\tStrtok,Test Program!!!! end\n"; 
    char  str2[] = " ,\t\n!"; 

    str = strdup( str1 );
    token = strsep( &str, str2 ); 
    while( token != NULL ) 
    { 
        printf( "token = %s", token ); 
        putchar( '\n' ); 
        token = strsep( &str, str2 ); 
    } 

    printf("검색이 완료된 원본 문자열 : %s\n",str1); 
    str = strdup( str1 );
    token = strsep( &str, str2 ); 
    printf( "token = %s", token ); 
    printf( "seped = %s", str ); 

  
    return 0; 
}