/** @file util.c @date 2009/1/15 ~ @author 오재경 freefrug@falinux.com FALinux.Co.,Ltd. @brief 단순한 유틸리티 함수들을 모아놓았다. Ver 0.2.1 @modify @todo @bug @remark @warning */ //---------------------------------------------------------------------------- #define EMBEDDED_LINUX // 이렇게 처리하지 않으면 EClipse에서 C 영역이 회색 바탕이 됨 #ifdef MS_WIN32 #undef EMBEDDED_LINUX #endif #include #include #include #include #include #include #include #include #include #include #include #ifdef EMBEDDED_LINUX #include #include #include #include #include #include #include #include #else #include #endif #include #ifdef EMBEDDED_LINUX //------------------------------------------------------------------------------ /** @brief 드라이버 이름으로 드라이버의 메이져번호를 얻는다. @param driver_name 디바이스드라이버 이름 @return 메이져번호 *///---------------------------------------------------------------------------- int find_dev_major( char *driver_name ) { FILE *fp; char linebuff[128]; char tmp_driver_name[32]; int major; major = -1; fp = fopen("/proc/devices", "r"); if(fp == NULL) return major; while(1) { if( fgets(linebuff, sizeof( linebuff) , fp ) == NULL ) break; if( sscanf(linebuff, "%d %s", &major, tmp_driver_name) == 2 ) { if (strcmp( tmp_driver_name, driver_name ) == 0) break; } } fclose( fp ); return major; } //------------------------------------------------------------------------------ /** @brief 디바이스 드라이버 노드파일을 연다. @param fname 디바이스 노드파일 이름 @param major 디바이스 드라이버 메이져번호 @param minor 디바이스 드라이버 마이너번호 @return 노드파일 핸들, 0보다 작으면 에러 @remakr 노드파일이 없으면 노드파일을 생성한 후 연다. *///---------------------------------------------------------------------------- int dev_open( char *fname, unsigned char major, unsigned char minor ) { int dev; dev = open( fname, O_RDWR|O_NDELAY ); if (dev < 0 ) { if( access( fname, F_OK ) == 0 ) { unlink( fname ); } mknod( fname, (S_IRWXU|S_IRWXG|S_IFCHR), MKDEV(major,minor) ); dev = open( fname, O_RDWR|O_NDELAY ); if (dev < 0 ) { printf( " Device OPEN FAIL %s\n", fname ); return -1; } } return dev; } //------------------------------------------------------------------------------ /** @brief tftp 유틸리티를 사용하여 파일을 다운로드받는다. @param ip 서버주소 @param fname 서버에서 받을 파일이름 @return 성공여부 @retval 0 성공 @retval -1 실패 *///---------------------------------------------------------------------------- int tftp_download_file( char *ip, char *fname ) { #define TEMP_DOWNLOAD_FILE ".tftpdnfile.tmp" char line[256]; int rst; // 받기용 temp 파일을 지운다. remove( TEMP_DOWNLOAD_FILE ); // tftp 를 이용하여 파일을 받는다. sprintf( line, "tftp %s -r %s -l %s -g", ip, fname, TEMP_DOWNLOAD_FILE ); rst = system( line ); if ( ( -1 == rst) || ( 127 == rst) ){ printf( "call system() error: LINE=%d\n", __LINE__); return -1; } // 파일이 존재하면 기존파일에 덮어쓴다. if ( 0 == exist_file( TEMP_DOWNLOAD_FILE ) ){ sprintf( line, "cp -a %s %s", TEMP_DOWNLOAD_FILE, fname ); rst = system( line ); if ( ( -1 == rst) || ( 127 == rst) ){ printf( "call system() error: LINE=%d\n", __LINE__); return -1; } return 0; } return -1; } //------------------------------------------------------------------------------ /** @brief tftp 유틸리티를 사용하여 파일을 업로드한다 @param ip 서버주소 @param fname 서버에 전송할 파일이름 @return 성공여부 @retval 0 성공 @retval -1 실패 *///---------------------------------------------------------------------------- int tftp_upload_file( char *ip, char *fname ) { char *ptr_name; char *ptr_slash; char line[256]; int rst; ptr_name = fname; while( 1){ ptr_slash = index( ptr_name, '/'); if ( NULL == ptr_slash){ break; } ptr_name = ptr_slash+1; } // tftp 를 이용하여 파일을 전송한다. sprintf( line, "tftp %s -r %s -l %s -p", ip, ptr_name, fname ); rst = system( line ); if ( ( -1 == rst) || ( 127 == rst) ){ printf( "call system() error: LINE=%d\n", __LINE__); } return 0; } //------------------------------------------------------------------------------ /** @brief usec 시간틱을 얻어온다. @return usec 단위의 시간틱 @remark 하루단위의 시간범위이다. *///---------------------------------------------------------------------------- unsigned long get_cur_usec(void) { struct timeval mytime; // 현재 시간을 얻어온다. gettimeofday(&mytime, NULL); return ( (mytime.tv_sec%(24*3600))*1000000 + mytime.tv_usec ); } //------------------------------------------------------------------------------ /** @brief 문자열에서 앞뒤의 특수문자와 공백문자를 제거한다. @param line 문자열 포인터 *///---------------------------------------------------------------------------- void trimstr( char *line ) { int idx, len; // 뒷쪽 공백문자와 특수문자 제거 len = strlen(line); for( idx=len-1; idx>=0; idx-- ) { if ( line[idx] > ' ' ) break; } line[idx+1] = '\0'; // 앞쪽 공백문자와 특수문자 제거 len = strlen(line); for( idx=0; idx ' ' ) break; } if ( (0 < idx) && (idx < len) ) { memmove( line, line + idx, len-idx+1 ); } } //------------------------------------------------------------------------------ /** @brief 문자열에서 특정 문자를 분리자로 사용하여 분리한다 @param line 분리할 문자열 @param delim 델리미터 @param item 분리된 문자열중 아이템 @param val 분리된 문자열중 값 @return 성공시 0, 실패시 -1 @remark aaa = bbbb 형태를 분리한다. @bug 좀더 테스트가 필요하다. *///---------------------------------------------------------------------------- int item_value_parse( const char *line, char delim, char *item, char *val ) { char buff[1024]; char *pch; int pos; strcpy( buff, line ); pch = strchr( buff, delim ); if ( pch ) { pos = pch - buff; buff[ pos ] = '\0'; strcpy( item, buff ); strcpy( val, &buff[ pos+1 ] ); trimstr( item ); trimstr( val ); return 0; } return -1; } //------------------------------------------------------------------------------ /** @brief 문자열에서 정수형값을 분리하여 배열에 넣는다. @param str 분리할 문자열 @param delim 델리미터 문자열 @param int_array 정수형 배열 @param count 정수형 배열 개수 *///---------------------------------------------------------------------------- int str_to_int_array( char *str, char *delim, int *int_array, int count ) { char *tok, *item, cp_str[2048]; int idx; strncpy( cp_str, str, 2048 ); idx = 0; for (tok = strtok( cp_str, delim ); tok; tok = strtok(NULL, delim )) { item = tok; trimstr( item ); if ( 1 <= strlen( item ) ) { int_array[idx] = strtol( item, NULL, 0 ); idx ++; if ( idx >= count ) break; } } return idx; } //------------------------------------------------------------------------------ /** @brief 자기 IP를 가져 온다. @param ip 를 받을 문자열 포인터 @return 성공시 0, 실패시 -1 @todo tstrlist 객체에 저장하여야 한다. @bug *///---------------------------------------------------------------------------- int get_myip( char *ip ) { const int MAX_NIC = 10; struct ifconf ifc; struct ifreq ifr[MAX_NIC]; int skt_fd; int num_ifs; int i; //jks int count; int max=2; int cmd = SIOCGIFCONF; max++; ifc.ifc_len = sizeof ifr; ifc.ifc_ifcu.ifcu_req = ifr; if( (skt_fd = socket(AF_INET,SOCK_STREAM,0)) < 0) { perror("socket"); return -1; } if( ( ioctl(skt_fd, cmd, &ifc) ) < 0) { perror("ioctl"); close( skt_fd ); return -1; } num_ifs = ifc.ifc_len / sizeof ( struct ifreq ); //jks count = 0; strcpy( ip, "127.0.0.1" ); for( i=0; isin_addr; if( addr.s_addr == htonl( 0x7f000001 ) ) { continue; } strcpy( ip, inet_ntoa( addr ) ); //printf( "%s IP: %s\n", ifc.ifc_ifcu.ifcu_req[i].ifr_ifrn.ifrn_name, ip ); } close( skt_fd ); if ( 0 < num_ifs ) return 0; return -1; } //------------------------------------------------------------------------------ /** @brief 파일이나 디렉토리가 존재하는지 확인한다. @param fname 파일이나 디렉토리이름 @return 0 이면 정상, 음수이면 존재하지 않음 *///---------------------------------------------------------------------------- int exist_file( char *fname ) { return access( fname, F_OK ); } //------------------------------------------------------------------------------ /** @brief 파일의 크기를 얻는다. @param fname 파일이나 디렉토리이름 @return 파일의 크기 에러일때 음수 *///---------------------------------------------------------------------------- int get_file_size( char *fname ) { struct stat fstat; fstat.st_size = -1; lstat( fname, &fstat); return fstat.st_size; } //------------------------------------------------------------------------------ /** @brief 로그정보를 파일에 써 넣는다. @param fmt 형식문자열 @param 가변 스택인자. @return 파일에 저장한 문자개수 *///---------------------------------------------------------------------------- int log_printf( const char *log_file, const char *fmt, ... ) { FILE *fp; va_list ap; int len; fp = fopen( log_file, "a" ); if( fp != NULL ) { va_start(ap, fmt); len = vfprintf( fp, fmt, ap); va_end(ap); fclose( fp ); return len; } return 0; } //------------------------------------------------------------------------------ /** @brief 날짜와 시간을 문자열 형태로 돌려준다. @param fmt 형식문자열 @param 반환문자열. *///---------------------------------------------------------------------------- void format_date_text( char *fmt, char *text ) { time_t cur_time; struct tm *tm_data; time( &cur_time ); tm_data = localtime( &cur_time ); sprintf( text, fmt, tm_data->tm_year + 1900, tm_data->tm_mon +1, tm_data->tm_mday, tm_data->tm_hour, tm_data->tm_min, tm_data->tm_sec ); } //------------------------------------------------------------------------------ /** @brief 좌표가 사각영역안에 있는지 검사 @param x,y 좌표 @param sx, sy, wdt, hgt 사각영역 @return 사각영역에 포함되면 1, 아니면 0 *///---------------------------------------------------------------------------- int is_rect_region( int x, int y, int sx, int sy, int wdt, int hgt ) { if ( ( sx <= x ) && ( x < (sx+wdt) ) && ( sy <= y ) && ( y < (sy+hgt) ) ) { return 1; } return 0; } //------------------------------------------------------------------------------ /** @brief 인터럽트가 발생 횟수를 돌려준다. @param irq irq 번호 @return 인터럽트 발생회수, irq 번호가 없다면 -1 *///---------------------------------------------------------------------------- int get_irq_count( int irq ) { FILE *fp; char line[256], cmp[32], *ptr; int int_cnt, cmp_len; int_cnt = -1; cmp_len = sprintf( cmp, "%3d:", irq ); fp = fopen( "/proc/interrupts", "r" ); if ( fp ) { while( NULL != fgets( line, sizeof(line), fp) ) { if ( 0 == strncmp( line, cmp, cmp_len ) ) { ptr = line + cmp_len; trimstr( ptr ); int_cnt = strtoul( ptr, NULL, 10 ); break; } } fclose( fp ); } return int_cnt; } //------------------------------------------------------------------------------ /** @brief ping 명령을 수행하여 성공한 회수를 돌려준다. @param host 상대방 IP 문자열 @param count 핑통신 회수 @return 핑성공 회수 *///---------------------------------------------------------------------------- int ping( char *host, int count ) { FILE *fp; char cmd[256], line[1024], *ptr; int ok_cnt = 0; int rst; sprintf( cmd, "ping -c %d %s > temp.log", count, host ); rst = system( cmd ); if ( ( -1 == rst) || ( 127 == rst) ){ return 0; } fp = fopen( "temp.log", "r" ); if ( fp ) { while( NULL != fgets( line, sizeof(line), fp) ) { ptr = strstr( line, "packets transmitted," ); if ( ptr ) { ok_cnt = strtoul( ptr+20 , NULL, 10 ); break; } } fclose( fp ); } return ok_cnt; } //------------------------------------------------------------------------------ /** @brief 바이너리 데이타를 헥사 문자열로 변환한다. @param hex 문자열을 담을 버퍼 @param bin 바이너리 문자열 버퍼 @param bcnt 바이너리 문자열 개수 *///---------------------------------------------------------------------------- void bin_to_hex( char *hex, char *bin, int bcnt ) { int idx; char tmp[16]; if ( 0 < bcnt ) { sprintf( hex, "%02X", bin[0] ); for(idx=1; idx>> [%s] = [%s]\n", str_item, str_val ); if ( 0 == strncmp( str_val, "EZS3C6410", 9 ) ) { rtn = 6410; } else if ( 0 == strncmp( str_val, "EZS5PV210", 9 ) ) { rtn = 210; } break; } } fclose( fp ); return rtn; } //------------------------------------------------------------------------------ /** @brief 키보드 입력을 엔터없이 한문자씩 즉시 받는다. @return 키보드 입력값 *///---------------------------------------------------------------------------- char getchar_without_enter( void ) { struct termios oldt, newt; char ch; tcgetattr( STDIN_FILENO, &oldt ); newt = oldt; newt.c_lflag &= ~( ICANON | ECHO ); tcsetattr( STDIN_FILENO, TCSANOW, &newt ); ch = getchar(); tcsetattr( STDIN_FILENO, TCSANOW, &oldt ); return ch; } //------------------------------------------------------------------------------ /** @brief 시스템 시간을 변경한다. @param yyyy, MM, dd, hh, mm, ss @return 성공 0, 실패 -1 *///---------------------------------------------------------------------------- int set_sys_time( int yyyy, int MM, int dd, int hh, int mm, int ss ) { struct timeval newtime; struct tm tm; memset( (void *)&tm, 0 ,sizeof(tm) ); tm.tm_year = yyyy-1900; tm.tm_mon = MM; tm.tm_mday = dd; tm.tm_hour = hh; tm.tm_min = mm; tm.tm_sec = ss; newtime.tv_sec = mktime( &tm ); newtime.tv_usec = 0; return settimeofday( &newtime, NULL ); } #endif //------------------------------------------------------------------------------ /** @brief 현재시간을 초단위로 돌려준다 @return 현재 시간초 *///---------------------------------------------------------------------------- unsigned long get_cur_sec( void ) { struct timeval mytime; // 현재 시간을 얻어온다. gettimeofday(&mytime, NULL); return mytime.tv_sec; } //------------------------------------------------------------------------------ /** @brief 현재의 msec 시간틱을 얻어온다. @return 현재 msec @todo 오버플로우에 대한 고찰이 필요하다. *///---------------------------------------------------------------------------- msec_t get_cur_msec( void ) { struct timeval mytime; long long tm_sec; // 현재 시간을 얻어온다. gettimeofday(&mytime, NULL); tm_sec = (unsigned long) mytime.tv_sec; return ( tm_sec * 1000LL + mytime.tv_usec / 1000); } //------------------------------------------------------------------------------ /** @brief 버퍼의 데이타를 헥사 문자열로 보여준다. @param buf 버퍼 @param count 버퍼개수 *///---------------------------------------------------------------------------- void print_buffer( char *buf, int count ) { int loop; for( loop=0; loop 1) { sum += *w++; nleft -= 2; } if (nleft == 1) sum += *(unsigned char*)w; sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); return sum; } //------------------------------------------------------------------------------ /** @brief msec 단위로 기다린다. @param msec @remark 스케줄 틱에 의존한다. *///---------------------------------------------------------------------------- void msleep( int msec ) { msec_t over; over = get_cur_msec() + msec; while(1) { if ( over <= get_cur_msec() ) break; sleep(0); } }