/* vim: set tabstop=4 paste nocindent noautoindent ff=unix: */ /** 汎用ツールプログラム tools.c '05 10/10 ヘッダ #include "tools.h" */ #include "tools.h" int DebugMode = OFF; int KanjiCode = EUC; int UnitTestMode = OFF; int HostEndian = UNKNOWN_ENDIAN; char LocalIPNum[4] = {0x7f, 0x00, 0x00, 0x01}; /////////////////////////////////////////////////////////////////////////////////////////// // // case of C++, isNull() is inline #ifndef CPLUSPLUS int isNull(void* p) { if (p==NULL) return TRUE; #ifdef WIN32 if (p==WIN32_NULL) return TRUE; #endif #ifdef WIN64 if (p==WIN64_NULL) return TRUE; #endif return FALSE; } #endif /////////////////////////////////////////////////////////////////////////////////////////// // /** int is_little_endian() int is_big_endian() エンディアンの動的チェック */ int is_little_endian(void) { unsigned char x[] = {0x01, 0x00}; if (HostEndian==LITTLE_ENDIAN) return TRUE; else if (HostEndian==BIG_ENDIAN) return FALSE; else { if (*((unsigned short*)x)==1) { HostEndian = LITTLE_ENDIAN; return TRUE; } else { HostEndian = BIG_ENDIAN; return FALSE; } } } int is_big_endian(void) { unsigned char x[] = {0x00, 0x01}; if (HostEndian==BIG_ENDIAN) return TRUE; else if (HostEndian==LITTLE_ENDIAN) return FALSE; else { if (*((unsigned short*)x)==1) { HostEndian = BIG_ENDIAN; return TRUE; } else { HostEndian = LITTLE_ENDIAN; return FALSE; } } } void check_endian(void) { if (HostEndian==UNKNOWN_ENDIAN) is_little_endian(); } // // // double double_from_little_endian(void* ptr) { double ret = *((double*)ptr); if (HostEndian==UNKNOWN_ENDIAN) check_endian(); if (HostEndian==BIG_ENDIAN) reverse_str((uByte*)(&ret), 8); return ret; } float float_from_little_endian(void* ptr) { float ret = *((float*)ptr); if (HostEndian==UNKNOWN_ENDIAN) check_endian(); if (HostEndian==BIG_ENDIAN) reverse_str((uByte*)(&ret), 4); return ret; } int int_from_little_endian(void* ptr) { int ret = *((int*)ptr); if (HostEndian==UNKNOWN_ENDIAN) check_endian(); if (HostEndian==BIG_ENDIAN) reverse_str((uByte*)(&ret), 4); return ret; } short short_from_little_endian(void* ptr) { short ret = *((short*)ptr); if (HostEndian==UNKNOWN_ENDIAN) check_endian(); if (HostEndian==BIG_ENDIAN) reverse_str((uByte*)(&ret), 2); return ret; } double double_from_big_endian(void* ptr) { double ret = *((double*)ptr); if (HostEndian==UNKNOWN_ENDIAN) check_endian(); if (HostEndian==LITTLE_ENDIAN) reverse_str((uByte*)(&ret), 8); return ret; } float float_from_big_endian(void* ptr) { float ret = *((float*)ptr); if (HostEndian==UNKNOWN_ENDIAN) check_endian(); if (HostEndian==LITTLE_ENDIAN) reverse_str((uByte*)(&ret), 4); return ret; } int int_from_big_endian(void* ptr) { int ret = *((int*)ptr); if (HostEndian==UNKNOWN_ENDIAN) check_endian(); if (HostEndian==LITTLE_ENDIAN) reverse_str((uByte*)(&ret), 4); return ret; } short short_from_big_endian(void* ptr) { short ret = *((short*)ptr); if (HostEndian==UNKNOWN_ENDIAN) check_endian(); if (HostEndian==LITTLE_ENDIAN) reverse_str((uByte*)(&ret), 2); return ret; } /////////////////////////////////////////////////////////////////////////////////////////// // Time char _Local_Time[32]; char* get_local_time(void) { struct tm* pt; time_t tm; tm = time(NULL); pt = localtime(&tm); snprintf(_Local_Time, 20, "%04d:%02d:%02d %02d:%02d:%02d", pt->tm_year+1900, pt->tm_mon+1, pt->tm_mday, pt->tm_hour, pt->tm_min, pt->tm_sec); return _Local_Time; } /////////////////////////////////////////////////////////////////////////////////////////// /** char* get_line(char* str, int n) 機能:strのバッファ内の n行目を取り出す.改行コードは削除される. n は 1から数える.取り出した行を char型変数のバッファに格納 して返す. 返されたデータは free()する必要がある. 引数:str -- 操作対象文の字列型データ(含む改行) n -- 行の指定. 戻り値:指定された n行目の文字列.改行は含まない. */ char* get_line(char* buf, int n) { int i, j, pos, cnt; char* ret=NULL; if (buf==NULL) return NULL; for(i=0,j=0; j=0) { ret = (char*)malloc(cnt+1); if (ret==NULL) return NULL; for(i=0; i0 && j1>=0 && j2>=0) { if (s1[j1--] != s2[j2--]) return 1; n--; } if (n==0) return 0; else return 1; } /** int strncaservscmp(const char* s1, const char* s2, int n) 機能: 文字列 s1と s2を後ろから n文字比較する. 戻り値: 一致する場合は 0,一致しない場合は 1 を返す. strncmp()の戻り値の定義とは異なるので注意すること. */ int strncaservscmp(const char* s1, const char* s2, int n) { int j1, j2; if (s1==NULL || s2==NULL) return 1; j1 = (int)strlen(s1) - 1; j2 = (int)strlen(s2) - 1; while (n>0 && j1>=0 && j2>=0) { if (toupper(s1[j1--]) != toupper(s2[j2--])) return 1; n--; } if (n==0) return 0; else return 1; } /** char* strstrcase(const char* buf, const char* nd) 機能:文字列 bufの中に文字列 ndがあるかどうかをチェックする.大文字小文字を区別しない.      大文字小文字を区別しない点を除けば,strstr() と同じ. つまり strcasestr() と同じ.標準で strcasestr()が存在しない場合に使用. */ char* strstrcase(const char* buf, const char* nd) { char* pp; char* pb; char* pn; if (buf==NULL || nd==NULL) return NULL; pb = (char*)malloc(strlen(buf)+1); if (pb==NULL) return NULL; memcpy(pb, buf, (int)strlen(buf)+1); pn = (char*)malloc(strlen(nd)+1); if (pn==NULL) { free(pb); return NULL; } memcpy(pn, nd, (int)strlen(nd)+1); upper_string(pb); upper_string(pn); pp = strstr(pb, pn); if (pp!=NULL) { pp = (pp - pb) + (char*)buf; } free(pb); free(pn); return pp; } /** int ex_strncmp(const char* dat, const char* key, int len) 機能: 拡張文字比較 引数: dat -- 比べる文字列1. key -- 比べる文字列2. len -- 1以上: 一致させる長さ. 0: 完全一致. -1: dat の長さに合わせる. -2: key の長さに合わせる. 戻り値: 一致した場合 TRUE.一致しなかった場合 FALSE. */ int ex_strncmp(const char* dat, const char* key, int len) { if (dat==NULL || key==NULL) return FALSE; if (len==0) { if (!strcmp(dat, key)) return TRUE; } else if (len>0) { if (!strncmp(dat, key, len)) return TRUE; } else if (len<0) { int sz; if (len==-1) sz = (int)strlen(dat); else sz = (int)strlen(key); if (!strncmp(dat, key, sz)) return TRUE; } return FALSE; } /** int ex_strncasecmp(const char* dat, const char* key, int len) 機能: 拡張文字比較.ケース無視. 引数: dat -- 比べる文字列1. key -- 比べる文字列2. len -- 1以上: 一致させる長さ. 0: 完全一致. -1: dat の長さに合わせる. -2: key の長さに合わせる. 戻り値: 一致した場合 TRUE.一致しなかった場合 FALSE. */ int ex_strncasecmp(const char* dat, const char* key, int len) { if (dat==NULL || key==NULL) return FALSE; if (len==0) { if (!strcasecmp(dat, key)) return TRUE; } else if (len>0) { if (!strncasecmp(dat, key, len)) return TRUE; } else if (len<0) { int sz; if (len==-1) sz = (int)strlen(dat); else sz = (int)strlen(key); if (!strncasecmp(dat, key, sz)) return TRUE; } return FALSE; } /** int ex_strnrvscmp(const char* dat, const char* key, int len) 機能: 拡張文字比較 引数: dat -- 比べる文字列1. key -- 比べる文字列2. len -- 1以上: 一致させる長さ. 0: 完全一致. -1: dat の長さに合わせる. -2: key の長さに合わせる. 戻り値: 一致した場合 TRUE.一致しなかった場合 FALSE. */ int ex_strnrvscmp(const char* dat, const char* key, int len) { if (dat==NULL || key==NULL) return FALSE; if (len==0) { if (!strcmp(dat, key)) return TRUE; } else if (len>0) { if (!strnrvscmp(dat, key, len)) return TRUE; } else if (len<0) { int sz; if (len==-1) sz = (int)strlen(dat); else sz = (int)strlen(key); if (!strnrvscmp(dat, key, sz)) return TRUE; } return FALSE; } /** int ex_strncaervscmp(const char* dat, const char* key, int len) 機能: 拡張文字比較.ケース無視. 引数: dat -- 比べる文字列1. key -- 比べる文字列2. len -- 1以上: 一致させる長さ. 0: 完全一致. -1: dat の長さに合わせる. -2: key の長さに合わせる. 戻り値: 一致した場合 TRUE.一致しなかった場合 FALSE. */ int ex_strncaservscmp(const char* dat, const char* key, int len) { if (dat==NULL || key==NULL) return FALSE; if (len==0) { if (!strcasecmp(dat, key)) return TRUE; } else if (len>0) { if (!strncaservscmp(dat, key, len)) return TRUE; } else if (len<0) { int sz; if (len==-1) sz = (int)strlen(dat); else sz = (int)strlen(key); if (!strncaservscmp(dat, key, sz)) return TRUE; } return FALSE; } /** char* chomp(char* buf) 機能:最初の改行コード以降を無視する. 引数:buf -- 改行を無効にする文字列. */ char* chomp(char* buf) { int i, len; if (buf==NULL) return NULL; len = (int)strlen(buf); for (i=0; i=0) { if (pp[i]==cc) i--; else break; } pp[i+1] = '\0'; return pp; } /** char* change_esc(char* mesg) 機能:文字列中の CR, LF を \r, \n に変換する 返されたデータは free()する必要がある. */ char* change_esc(char* mesg) { int i, j; char* pp; if (mesg==NULL) return NULL; pp = (char*)malloc((strlen(mesg)+1)*2); if (pp==NULL) return NULL; i = j = 0; while(mesg[i]!='\0') { if (mesg[i]==CR) { pp[j++] = '\\'; pp[j++] = 'r'; } else if (mesg[i]==LF) { pp[j++] = '\\'; pp[j++] = 'n'; } else { pp[j++] = mesg[i]; } i++; } pp[j] = '\0'; return pp; } /** char* cut_str(char* buf, int ls, int le) 機能:buf[ls] 〜 buf[le] を切り出してメモリに格納して返す. 返されたデータは free()する必要がある. */ char* cut_str(char* buf, int ls, int le) { int i, len; char* ret; if (buf==NULL) return NULL; ls = Max(ls, 0); le = Min(le, (int)strlen((const char*)buf)); len = le - ls + 1; if (len<=0) return NULL; ret = (char*)malloc(len+1); if (ret==NULL) return NULL; memset(ret, 0, len+1); for (i=0; i='0' && str[i]<='9') { ret = ret*16; ret += (int)(str[i] - '0'); } else if (str[i]>='A' && str[i]<='F') { ret = ret*16; ret += (int)(str[i] - 'A') + 10; } else if (str[i]>='a' && str[i]<='f') { ret = ret*16; ret += (int)(str[i] - 'a') + 10; } else if (str[i]!=' ') { break; } } return ret; } /* ************************************************************************* */ #ifndef WIN32 /** void init_rand(void) 機能:/dev/urandom から乱数の系列を初期化する      /dev/urandom が読めない場合は,呼び出された時の時間(秒数)によって 乱数の系列を初期化する. */ void init_rand(void) { FILE* fp; unsigned int seed; fp = fopen("/dev/urandom", "rb"); if (fp==NULL) { srand(time(NULL)); return; } fread(&seed, sizeof(unsigned int), 1, fp); fclose(fp); srand(seed); } #endif /** char* randstr(int n) 機能:ランダムに A-Za-z0-9 までの文字を n文字生成する. 返されたデータは free()する必要がある. 引数:n -- 出力する文字数. 戻り値:ランダムに生成された n文字の文字列. */ char* randstr(int n) { char base[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; char* pass; int i, sz; if (n<=0) return NULL; pass = (char*)malloc(n+1); if (pass==NULL) return pass; sz = (int)strlen(base); for (i=0; i=0xa1 && mesg[i]<=0xfe){ // EUC euc2sjis(&mesg[i], &mesg[i+1]); i = i + 2; } else i++; } } /** void kanji_convert_sjis2euc(unsigned char* mesg) 機能:SJISをEUCに変換する. 引数:変換する文字列を持つ unsigned char*型データ.内容が書き換えられる. */ void kanji_convert_sjis2euc(unsigned char* mesg) { int i = 0; while(mesg[i]!='\0' && mesg[i+1]!='\0'){ // if文が変則的なのは,コンパイラで警告が出るため (GCC) 3.3.2 20031218 if ((mesg[i]>=0x81 && mesg[i]<=0x9f) || (mesg[i]>=0xe0 && mesg[i]<=0xfe) || mesg[i]==0xff) { // SJIS sjis2euc(&mesg[i], &mesg[i+1]); i = i + 2; } else i++; } } /** void euc2sjis(unsigned char *c1, unsigned char *c2) 機能:漢字コード変換.EUC→SJIS 引数:c1 -- 変換する文字の第一バイト.内容が書き換えられる. c2 -- 変換する文字の第二バイト.内容が書き換えられる. */ void euc2sjis(unsigned char *c1, unsigned char *c2) { if (*c1%2==0) *c2 -= 0x02; else{ *c2 -= 0x61; if (*c2>0x7e) (*c2)++; } if (*c1<0xdf) { (*c1)++; *c1 /= 2; *c1 += 0x30; } else { (*c1)++; *c1 /= 2; *c1 += 0x70; } } /** void sjis2euc(unsigned char *c1, unsigned char *c2) 機能:漢字コード変換.SJIS→EUC 引数:c1 -- 変換する文字の第一バイト.内容が書き換えられる. c2 -- 変換する文字の第二バイト.内容が書き換えられる. */ void sjis2euc(unsigned char *c1, unsigned char *c2) { if (*c2<0x9f) { if (*c1 < 0xa0) { *c1 -= 0x81; *c1 *= 2; *c1 += 0xa1; } else { *c1 -= 0xe0; *c1 *= 2; *c1 += 0xdf; } if (*c2>0x7f) (*c2)--; *c2 += 0x61; } else { if (*c1<0xa0) { *c1 -= 0x81; *c1 *= 2; *c1 += 0xa2; } else { *c1 -= 0xe0; *c1 *= 2; *c1 += 0xe0; } *c2 += 2; } } /** void upper_string(char* str) 機能:str中の小文字を大文字に変換する 引数:str -- 変換する文字列へのポインタ.内容が書き換えられる. */ void upper_string(char* str) { int i; for (i=0; i<(int)strlen((const char*)str); i++) { if (str[i]>='a' && str[i]<='z') str[i] += 'A' - 'a'; } } /** unsigned char* decode_base64(unsigned char* buf, int* sz) 機能:buf を base64からデコードする. 変換は bufの先頭から順次行われる.A-Za-z0-9+/ 以外は無視する(例えば改行コード). 入力バッファ部が 4byte(6bit*4)の場合, 出力バッファ部は 3byte (8bit*3)となる.入力バッファ部のバイト数が 4の倍数でない場合 (不正なデータ), 足りない入力バッファ部には '='が挿入されてい るものとみなす. 返されたデータは free()する必要がある. 引数:buf -- base64からデコードする文字列. sz -- デコードされたデータの長さを格納する int へのポインタ 戻り値:return -- base64からデコードされたデータ *sz -- デコードされたデータのサイズ 例:"QQ" をデコードすると 'A',0x00 となる. */ unsigned char* decode_base64(unsigned char* buf, int* sz) { int i, j, cc=0, bas, lt; unsigned char* dcd; lt = 0; while (buf[lt]!='=' && lt<(int)strlen((const char*)buf)) { lt++; if (lt==(int)strlen((const char*)buf)) break; } *sz = lt/4*3 + (lt%4)*3/4; dcd = (unsigned char*)malloc(*sz); if (dcd==NULL) return dcd; memset(dcd, 0, *sz); for (i=0; i='A' && buf[i]<='Z') cc = buf[i] - 'A'; else if (buf[i]>='a' && buf[i]<='z') cc = buf[i] - 'a' + 26; else if (buf[i]>='0' && buf[i]<='9') cc = buf[i] - '0' + 52; else if (buf[i]=='+') cc = 62; else if (buf[i]=='/') cc = 63; if (cc<64) { bas = 32; for (j=0; j<6; j++) { setBit(dcd, i*6+j, cc/bas); cc = cc%bas; bas = bas/2; } } } return dcd; } /** unsigned char* encode_base64(unsigned char* buf, int sz) 機能:バイナリデータ bufを base64にエンコードする. 入力バッファ部が 3byte(8bit*3)の場合, 出力バッファ部は 4byte (6bit*4)となる.入力バッファ部が 6bit境界でない場合, 6bit境界 まで 0が付加されたと見される. 出力バッファ部が 4byte境界でない場合, 4byte境界まで '='を付加 して出力する. また,出力バッファ部での 60byte毎の改行は行わない. 一般に n byte 入力された場合, base64の出力の文字数は (n+2)/3*4 byte となる. 返されたデータは free()する必要がある. 引数:buf -- base64にエンコードするデータ. sz -- データの長さを示す.-1以下の場合は buf は文字列とみなす. 戻り値:return -- base64にエンコードされた文字列 例:'A',0x00,0x01 を文字列(sz=1)とみなして符号化すると "QQ==" となる. 'A',0x00,0x01 の 3byteを符号化(sz=3)すると "QQAB" となる. */ unsigned char* encode_base64(unsigned char* buf, int sz) { unsigned char base[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; unsigned char bas; int i, j, len; unsigned char* ecd; if (buf==NULL) return NULL; if (sz<0) len = (int)strlen((const char*)buf); else len = sz; if (len==0) return NULL; sz = (len + 2)/3*4; ecd = (unsigned char*)malloc(sz+1); if (ecd==NULL) return NULL; memset(ecd, 0, sz+1); for (i=0; i i*6) { for (j=0; j<6; j++) { if (len*8 > i*6+j) setBit(&bas, j+2, getBit(buf, i*6+j)); //else setBit(&bas, j+2, 0); } ecd[i] = base[(int)bas]; } else { ecd[i] = '='; } } return ecd; } /** unsigned char* decode_urlenc(unsigned char* buf, int* sz) 機能:buf を URLエンコードからデコードする. 返されたデータは free()する必要がある. 引数:buf -- デコードする文字列. *sz -- デコードされたデータの長さを格納する変数. 戻り値:return -- デコードされたデータ *sz -- デコードされたデータの長さ */ unsigned char* decode_urlenc(unsigned char* buf, int* sz) { int i, j, len; unsigned char* dec; if (buf==NULL) return NULL; len = (int)strlen((const char*)buf) + 1; dec = (unsigned char*)malloc(len); if (dec==NULL) return NULL; memset(dec, 0, len); i = j = 0; while (buf[i]!='\0') { if (buf[i]=='%') { if (buf[i+1]=='\0') return dec; if (buf[i+2]=='\0') return dec; dec[j++] = decode_hex(buf[i+1], buf[i+2]); i += 2; } else { if (buf[i]=='+') dec[j++] = ' '; else dec[j++] = buf[i]; } i++; } *sz = j; return dec; } /** unsigned char* encode_urlenc(unsigned char* buf) 機能:バイナリデータ bufを URLエンコードする. エンコードしない文字については色々考え方があるが,最大公約数的に考えて      このプログラムでは以下のようにする. エンコードしない文字 0-9, A-Z, a-z, -._ 返されたデータは free()する必要がある. 引数:buf -- エンコードするデータ. sz -- エンコードするデータの長さ.-1以下の場合は buf は文字列とみなす. 戻り値:return -- エンコードされた文字列 */ unsigned char* encode_urlenc(unsigned char* buf, int sz) { int i, j, len; unsigned char* enc; if (sz<0) sz = (int)strlen((const char*)buf); len = sz*3 + 1; enc = (unsigned char*)malloc(len); if (enc==NULL) return NULL; memset(enc, 0, len); for(i=0, j=0; i=0x30 && buf[i]<=0x39) || // 0-9 (buf[i]>=0x41 && buf[i]<=0x5a) || // A-Z (buf[i]>=0x61 && buf[i]<=0x7a) || // a-z buf[i]=='-' || buf[i]=='.' || buf[i]=='_'){ // - . _ enc[j++] = buf[i]; } else { unsigned char* asc = encode_hex(buf[i]); if (asc==NULL) { free(enc); return NULL; } enc[j++] = '%'; enc[j++] = asc[0]; enc[j++] = asc[1]; free(asc); } } return enc; } /** unsigned char* decode_quoted_printable(unsigned char* buf, int* sz) 機能:buf を quoted printableからデコードする. 返されたデータは free()する必要がある. 引数:buf -- デコードする文字列. *sz -- デコードされたデータの長さを格納する変数. 戻り値:return -- デコードされたデータ *sz -- デコードされたデータの長さ */ unsigned char* decode_quoted_printable(unsigned char* buf, int* sz) { int i, j, len; unsigned char* dec; len = (int)strlen((const char*)buf) + 1; dec = (unsigned char*)malloc(len); if (dec==NULL) return NULL; memset(dec, 0, len); i = j = 0; while (buf[i]!='\0') { if (buf[i]=='=') { if (buf[i+1]=='\0') return dec; if (buf[i+2]=='\0') return dec; dec[j++] = decode_hex(buf[i+1], buf[i+2]); i += 2; } else { if (buf[i]=='_') dec[j++] = ' '; // RFC2047 else dec[j++] = buf[i]; } i++; } *sz = j; return dec; } /** unsigned char* encode_quoted_printable(unsigned char* buf, int sz) 機能:バイナリデータ bufを quoted printable にエンコードする. RFC2047 に従い,' ' は '_' にエンコードする. エンコードしない文字 '=', '_' 以外の 0x21-0x7e エンコードする文字 '=', '_', 0x00-0x20, 0x7f-0xff 返されたデータは free()する必要がある. 引数:buf -- エンコードするデータ. sz -- エンコードするデータの長さ.-1以下の場合は buf は文字列とみなす. 戻り値:return -- エンコードされた文字列 */ unsigned char* encode_quoted_printable(unsigned char* buf, int sz) { int i, j, len; unsigned char* enc; if (sz<0) sz = (int)strlen((const char*)buf); len = sz*3 + 1; enc = (unsigned char*)malloc(len); if (enc==NULL) return NULL; memset(enc, 0, len); for (i=0, j=0; i=0x7f) { unsigned char* asc = encode_hex(buf[i]); if (asc==NULL) { free(enc); return NULL; } enc[j++] = '='; enc[j++] = asc[0]; enc[j++] = asc[1]; free(asc); } else { enc[j++] = buf[i]; } } return enc; } /** unsigned char* encode_hex(unsigned char cc) 機能:キャラクタを16進コードの文字列に変換する. 返されたデータは free()する必要がある. 引数:変換するキャラクタ. 戻り値:新しく確保された 3byteの領域 [0] -- 16進コードの上位4Bit. 0-9,A-F [1] -- 16進コードの下位4Bit. 0-9,A-F [2] -- '\0' NULL の場合はメモリ不足. 例:encode_hex(' ') は "20" を返す. */ unsigned char* encode_hex(unsigned char cc) { unsigned char* ret; unsigned char pp1, pp2; unsigned char base[] = "0123456789ABCDEF"; ret = (unsigned char*)malloc(3); if (ret==NULL) return NULL; pp1 = cc >> 4; pp2 = cc & 0x0f; ret[0] = base[pp1]; ret[1] = base[pp2]; ret[2] = '\0'; return ret; } /** unsigned char decode_hex(unsigned char pp1, unsigned char pp2) 機能:16進コードをキャラクタに変換する.O-9,A-F以外が指定された場合は0とみなす. 引数:pp1 -- 16進コードの上位4Bit. 0-9,A-F pp2 -- 16進コードの下位4Bit. 0-9,A-F 戻り値:指定されたASCIIコードのキャラクタ 例:decode_hex('2', '0') は ' ' を返す. */ unsigned char decode_hex(unsigned char pp1, unsigned char pp2) { unsigned char ret; if (pp1>=0x30 && pp1<=0x39) pp1 -= 0x30; // 0-9 else if (pp1>=0x41 && pp1<=0x46) pp1 -= 0x37; // A-F else if (pp1>=0x61 && pp1<=0x66) pp1 -= 0x57; // a-f else pp1 = 0x00; if (pp2>=0x30 && pp2<=0x39) pp2 -= 0x30; // 0-9 else if (pp2>=0x41 && pp2<=0x46) pp2 -= 0x37; // A-F else if (pp2>=0x41 && pp2<=0x46) pp2 -= 0x57; // a-f else pp1 = 0x00; ret = (pp1<<4) + pp2; return ret; } ////////////////////////////////////////////////////////////////////////////////////////////////////// // // /** void print_message(char* fmt, ...) 機能:バッファリング無しのメッセージ出力(stderr) 引数:fmt -- 出力フォーマット.その他は printf() に準拠. */ void print_message(char* fmt, ...) { char* nfmt; int len; va_list args; va_start(args, fmt); len = (int)strlen(fmt); nfmt = (char*)malloc(len + 1); if (nfmt==NULL) return; strncpy(nfmt, fmt, len); nfmt[len] = '\0'; vfprintf(stderr, nfmt, args); fflush(stderr); free(nfmt); va_end(args); return; } /** void fprint_message(FILE *fp, char* fmt, ...) 機能:バッファリング無しのメッセージ出力(stderr) 引数:fmt -- 出力フォーマット.その他は printf() に準拠. */ void fprint_message(FILE* fp, char* fmt, ...) { char* nfmt; int len; va_list args; va_start(args, fmt); len = (int)strlen(fmt); nfmt = (char*)malloc(len + 1); if (nfmt==NULL) return; strncpy(nfmt, fmt, len); nfmt[len] = '\0'; vfprintf(fp, nfmt, args); fflush(fp); free(nfmt); va_end(args); return; } /** void print_escape(char* fmt, char* mesg) 機能:エスケープ文字を含むメッセージの出力.    現在は CR, LF のみ \r, \n に変換する.see change_esc() */ void print_escape(char* fmt, char* mesg) { char* pp; if (fmt==NULL || mesg==NULL) return; pp = change_esc(mesg); if (pp==NULL) return; print_message(fmt, pp); free(pp); } /** void fprint_escape(FILE* fp, char* fmt, char* mesg) 機能:エスケープ文字を含むメッセージの出力.    現在は CR, LF のみ \r, \n に変換する.see change_esc() */ void fprint_escape(FILE* fp, char* fmt, char* mesg) { char* pp; if (fmt==NULL || mesg==NULL) return; pp = change_esc(mesg); if (pp==NULL) return; fprint_message(fp, fmt, pp); free(pp); } /** void fdump(FILE* fp, unsigned char* mesg, int n) 機能:デバッグ用 16進出力 mesgの nバイトを16進表示する.n<0 の場合は 文字列とみなす. 引数:fp -- 出力するファイルへのポインタ.NULLの場合は stderr mesg -- 表示するデータ. n -- 表示するバイト数 */ void fdump(FILE* fp, unsigned char* mesg, int n) { int i, j, mod, len; char ascii[16]; if (fp==NULL) fp = stderr; if (mesg==NULL) { fprintf(fp, "(Dump Data is NULL)\n"); return; } if (n<0) len = (int)strlen((const char*)mesg); else len = n; memset(ascii, 0x2e, 16); for (i=0, j=0; i=0x20 && mesg[i]<=0x7e) ascii[j] = mesg[i]; j++; if (j==16) { fprintf(fp, " "); for (j=0; j<16; j++) { fprintf(fp, "%c ", ascii[j]); } fprintf(fp, "\n"); memset(ascii, 0x2e, 16); j = 0; } } mod = len%16; if (mod>0) { for (i=0; i<17-mod; i++) fprintf(fp, " "); for (i=0; ibuf); free(*rb); *rb = NULL; } } /** ringbuffer init_ringbuffer() 機能:初期化された ringbuffer変数を返す. */ ringbuffer init_ringbuffer() { ringbuffer rb; memset(&rb, 0, sizeof(ringbuffer)); //rb.bufsz = -1; return rb; } /** ringbuffer make_ringbuffer(int sz) 機能:バッファ部が存在するリングバッファを作り出す. バッファ部は free()する必要がある. */ ringbuffer make_ringbuffer(int sz) { ringbuffer rb; memset(&rb, 0, sizeof(ringbuffer)); if (sz>0) { rb.buf = (unsigned char*)malloc(sz); if (rb.buf==NULL) return rb; memset(rb.buf, 0, sz); rb.bufsz = sz; } return rb; } /** void free_ringbuffer(ringbuffer* rb) 機能:リングバッファのバッファ部を開放する. */ void free_ringbuffer(ringbuffer* rb) { if (rb!=NULL) { freeNull(rb->buf); memset(rb, 0, sizeof(ringbuffer)); } } /** void clear_ringbuffer(ringbuffer* rb) 機能:リングバッファ rb のデータをクリア(初期化)する. */ void clear_ringbuffer(ringbuffer* rb) { if (rb!=NULL) { int sz = rb->bufsz; unsigned char* ptr = rb->buf; memset(rb->buf, 0, rb->bufsz); memset(rb, 0, sizeof(ringbuffer)); rb->buf = ptr; rb->bufsz = sz; } } /** int put_ringbuffer(ringbuffer* rb, unsigned char* pp, int sz) 機能:リングバッファ rb へデータを szバイト格納する. 引数:sb メッセージストリームへのポインタ pp 格納するデータへのポインタ.  sz 格納するデータのサイズ(Byte) 戻り値:0以上:書き込んだバイト数. -1: 引数にNULLのデータがある. -2: バッファ(データ格納)部の領域がない. -3: バッファ(データ格納)部の大きさがたりない.データはputされなかった. rb->state: 0 バッファは正常状態.-1 バッファは異常な状態にある. */ int put_ringbuffer(ringbuffer* rb, unsigned char* pp, int sz) { if (rb==NULL) return -1; rb->state = 0; if (pp==NULL) return -1; if (rb->buf==NULL) return -2; if (rb->datasz+sz>rb->bufsz) { rb->state = -1; return -3; } if (rb->epoint+sz<=rb->bufsz) { memcpy(&((rb->buf)[rb->epoint]), pp, sz); rb->epoint = rb->epoint + sz; if (rb->epoint==rb->bufsz) rb->epoint = 0; } else { memcpy(&(rb->buf[rb->epoint]), pp, rb->bufsz-rb->epoint); memcpy(rb->buf, &(pp[rb->bufsz-rb->epoint]), sz-(rb->bufsz-rb->epoint)); rb->epoint = rb->epoint + sz - rb->bufsz; } rb->datasz += sz; return sz; } /** unsigned char* get_ringbuffer(ringbuffer* rb, int sz) 機能:リングバッファ rb から szバイトのデータを取り出す. 返されたデータは free()する必要がある. 引数:リングバッファへのポインタ 戻り値:取り出したデータへのポインタ.使い終わったら free()する必要がある. NULL データ取得失敗.現在有効なデータサイズはszより小さい.または単に失敗した. rb->state: 0 バッファは正常状態.-1 バッファは異常な状態にある. */ unsigned char* get_ringbuffer(ringbuffer* rb, int sz) { unsigned char* pp; if (rb==NULL) return NULL; rb->state = 0; if (rb->buf==NULL) return NULL; if (sz>rb->datasz) return NULL; pp = (unsigned char*)malloc(sz+1); if (pp==NULL) { rb->state = -1; return NULL; } memset(pp, 0, sz+1); if (rb->spoint+sz<=rb->bufsz) { memcpy(pp, &(rb->buf[rb->spoint]), sz); rb->spoint = rb->spoint + sz; if (rb->spoint==rb->bufsz) rb->spoint = 0; } else { memcpy(pp, &(rb->buf[rb->spoint]), rb->bufsz-rb->spoint); memcpy(&(pp[rb->bufsz-rb->spoint]), rb->buf, sz-(rb->bufsz-rb->spoint)); rb->spoint = rb->spoint + sz - rb->bufsz; } rb->datasz -= sz; return pp; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // バイト型 メッセージストリームバッファ // /** int put_mstream(mstream* sb, unsigned char* mesg) 機能:メッセージ(文字列)ストリーム sb へメッセージ(の一部)を格納する.  ここで,メッセージとは \r\n, \r または \n で区切られている文字列でのことである. 引数:sb メッセージストリームへのポインタ mesg 格納するメッセージ,またはその一部 戻り値:0以上:書き込んだバイト数(CRLFを含む) -1: 引数にNULLのデータがある. -2: バッファ(データ格納)部の領域がない. -3: バッファ(データ格納)部の大きさがたりない. sb->state: 0 ストリームは正常状態.-1 ストリームは異常な状態にある. */ int put_mstream(mstream* sb, unsigned char* mesg) { int i, n, m, cc, np=0, len; if (sb==NULL) return -1; sb->state = 0; if (mesg==NULL) return -1; if (sb->buf==NULL) return -2; len = (int)strlen((const char*)mesg); for (i=0, n=0, m=0; idatano==0 && n>=1) np = (sb->epoint + m + 1) % sb->bufsz; cc = put_ringbuffer(sb, mesg, len); if (cc>=0) { if (sb->datano==0 && n>=1) sb->npoint = np; sb->datano += n; } if (cc<0) sb->state = -1; return cc; } /** unsigned char* get_mstream(mstream* sb) 機能:メッセージ(文字列)ストリーム sb から次のメッセージを取り出す. 改行コードは削除される.  ここで,メッセージとは \r\n, \r または \n で区切られている文字列でのことである. 引数:メッセージストリームへのポインタ 戻り値:取り出したストリームデータへのポインタ.使い終わったら free()する必要がある. NULL データ取得失敗.現在有効なメッセージデータは無い.または単に失敗した. sb->state: 0 ストリームは正常状態.-1 ストリームは異常な状態にある.非実装 */ unsigned char* get_mstream(mstream* sb) { int n, len; unsigned char* pp; if (sb==NULL) return NULL; sb->state = 0; if (sb->buf==NULL) return NULL; if (sb->datano==0) return NULL; len = sb->npoint - sb->spoint; if (len==0) return NULL; else if (len<0) len += sb->bufsz; pp = get_ringbuffer(sb, len); if (pp==NULL) { sb->state = -1; return NULL; } chomp((char*)pp); sb->datano += -1; sb->spoint = sb->npoint; if (sb->datano>=1) { int m; n = sb->spoint; while (n!=sb->epoint) { m = (n + 1) % sb->bufsz; if (sb->buf[n]==LF || (sb->buf[n]==CR && sb->buf[m]!=LF)) { sb->npoint = m; break; } n = m; } } return pp; } /** unsigned char* fgets_mstream(unsigned char* mesg, mstream* sb) 機能:メッセージ mesg はメッセージストリームに一旦バッファリングされ,この関数により 一行ずつ読み出される.結果が返される時,行中の改行コードは削除され,行末には必ず \0 が入る. メッセージストリームのバッファ部が確保されていない場合は,最初に呼び出された時点で  確保される.一旦この関数を使用して,受信データをバッファリングしたら,最後まで読み取りには 必ず同じストリームを使用してこの関数を呼び出さばければならない.そうで無い場合は受信データ の整合性は保証されない. 引数: mesg バッファに一旦格納されるメッセージ.NULLでも可. sb ストリームバッファ(リングバッファ型のストリームバッファ) バッファ部が確保さえていなければ,自動的に確保される. 戻り値: return : 取り出した文字列へのポインタ sb->state : <0 メッセージストリーム操作中は異常な状態にある. 1 メッセージストリーム中に有効なデータがない.return は NULL */ unsigned char* fgets_mstream(unsigned char* mesg, mstream* sb) { int state=0; unsigned char* pp; if (sb==NULL) return NULL; if (sb->buf==NULL) { *sb = make_mstream(RECVBUFSZ); if (sb->buf==NULL) return NULL; } if (mesg!=NULL) put_mstream(sb, mesg); if (sb->state<0) state = sb->state; if (sb->datano==0) { sb->state = 1; return NULL; } pp = get_mstream(sb); if (sb->state>=0 && state<0) sb->state = state; return pp; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // /** unsigned char* uuid2guid(unsigned char* p) 機能:バイナリの UUID を テキストのGUIDに変換する.要 free() */ unsigned char* uuid2guid(unsigned char* p) { unsigned char* guid; if (p==NULL) return NULL; guid = (unsigned char*)malloc(LGUID); // 40 = 32+4+1(\0) + α if (guid==NULL) return NULL; snprintf((char*)guid, 37, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15]); return guid; } /** unsigned char* guid2uuid(unsigned char* p) 機能:テキストのGUID をバイナリのUUID に変換する.要 free() 入力が GUIDの形式でない時は,処理結果は保証されない. */ unsigned char* guid2uuid(unsigned char* p) { int i, j; unsigned char* uuid; if (p==NULL) return NULL; uuid = (unsigned char*)malloc(16); if (uuid==NULL) return NULL; i = j = 0; while (p[i]!='\0' && j<16) { if (p[i]!='-' && p[i+1]!='\0') { unsigned char hb, lb; if (p[i]>='0' && p[i]<='9') hb = p[i] - '0'; else if (p[i]>='a' && p[i]<='f') hb = p[i] - 'a' + 10; else if (p[i]>='A' && p[i]<='F') hb = p[i] - 'A' + 10; else hb = '\0'; if (p[i+1]>='0' && p[i+1]<='9') lb = p[i+1] - '0'; else if (p[i+1]>='a' && p[i+1]<='f') lb = p[i+1] - 'a' + 10; else if (p[i+1]>='A' && p[i+1]<='F') lb = p[i+1] - 'A' + 10; else lb = '\0'; uuid[j] = (hb<<4) + lb; i++; j++; } i++; } return uuid; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // シグナル処理 // #ifndef WIN32 #ifdef SIGCHLD /** void set_sigterm_child(void (*handler)(int)) 機能:child プロセス終了時の処理を設定. */ void set_sigterm_child(void (*handler)(int)) { struct sigaction sa; if (handler!=NULL) sa.sa_handler = handler; else sa.sa_handler = sigterm_child; sa.sa_flags = SA_NOCLDSTOP | SA_RESTART; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGINT); sigaddset(&sa.sa_mask, SIGHUP); sigaddset(&sa.sa_mask, SIGTERM); sigaction(SIGCHLD, &sa, NULL); } /** void set_sigsegv_handler(void (*handler)(int)) 機能:セグメンテーションエラー時のハンドラを設定. 引数に NULLを指定した場合は,ハンドラ関数として trap_segmentation_falt() を使用. */ void set_sigsegv_handler(void (*handler)(int)) { struct sigaction sa; if (handler!=NULL) sa.sa_handler = handler; else sa.sa_handler = trap_segmentation_falt; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(SIGSEGV, &sa, NULL); } void trap_segmentation_falt(int signal) { print_message("****************************************************************\n"); print_message("* Segmentation Falt in [%d] !!!!!\n", getpid()); print_message("****************************************************************\n"); exit(signal); } /** void ignore_sigterm_child() 機能:child プロセスの終了を無視する. */ void ignore_sigterm_child() { struct sigaction sa; sa.sa_handler = SIG_IGN; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(SIGCHLD, &sa, NULL); } /** void sigterm_child(int signal) 機能:child プロセス終了時の処理 */ void sigterm_child(int signal) { pid_t pid = 0; int ret; DEBUG_MESG("%d is waiting for children. signal = %d\n", getpid(), signal); do { // チャイルドプロセスの終了を待つ pid = waitpid(-1, &ret, WNOHANG); } while(pid>0); } #endif // SIGCHLD #endif // NOT WIN32 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // for Windows // #ifdef WIN32 /* see common.h void bzero(char* p, unsigned int n) { for (unsigned int i=0; i