__LINE__や__FILE__を使ったログ出力を

UNIX(RedHat Solaris AIX等)の
syslog機能を使って行う方法を
教えてください。

#include<stdio.h>

void printlog(void){
printf(" %s %d 行目\n",
         __FILE__,__LINE__);
}

int main(){

printlog();

printlog();
}

上記のようにすると(ものすごく
適当なソースですが)意図したログ出力に
ならないので、マクロを組まないと
いけないのは知っているのですが、
syslog関数を使って下記のサイトで
作成しているような
ログ出力関数を作りたいのです。
http://shugo.net/jit/20050209.html
どのように実装すればよいか
・可変長引数を使ったできるだけ適切な
 ログ出力フォーマット
・オープン、クローズ等をログ出力関数
 呼び出しの度に呼ばずに一度だけ行う
上記の点を踏まえて教えてください。
又、syslog系の関数は仕様があまりよく分からないので、その部分の説明ももらえると助かります。

又、マクロを使わずに意図したログ出力関数はできるのかも Yes or No+簡単な説明 でかまわないので教えてもらえると助かります。

回答の条件
  • 1人5回まで
  • 登録:2006/07/03 23:10:37
  • 終了:2006/07/10 23:15:03

回答(2件)

id:znz No.1

znz回答回数193ベストアンサー獲得回数252006/07/04 00:07:13

ポイント35pt

マクロを使わずに直接syslogを呼ぶのならこのようになります。

#include <syslog.h>
int
main(void)
{
    syslog(LOG_INFO, "%s:%d: info - %d", __FILE__, __LINE__, 12345);
    return 0;
}

http://shugo.net/jit/20050209.html に書いてあるように、GCC拡張やC99の可変長引数マクロを使わずになんとかするのなら、長さがBUFFER_SIZE未満に制限されてしまいますが、このような感じでしょうか。

__FILE__や__LINE__が別の行になっても構わないのなら、fprintfの代わりにsyslogで__FILE__と__LINE__を出力して、vfprintfの代わりにvsyslogでログを出力するだけなのですが。

エラー処理周りにもバグが入りやすそうで、不安が残ります。

mysyslog.c:

#include <stdio.h>
#include <stdarg.h>
#include "mysyslog.h"
static const char *syslog_file = NULL;
static int syslog_line = -1;
void
my_syslog_locate(const char *file, int line)
{
    syslog_file = file;
    syslog_line = line;
}
#define BUFFER_SIZE 2048
void
my_syslog(int priority, const char *fmt, ...)
{
    char buf[BUFFER_SIZE];
    va_list ap;
    int width;
    width = snprintf(buf, BUFFER_SIZE-1, "%s:%d: ", syslog_file, syslog_line);
    if (width <= 0 || BUFFER_SIZE-1 <= width)
        return;
    va_start(ap, fmt);
    vsnprintf(buf+width, BUFFER_SIZE-1-width, fmt, ap);
    va_end(ap);
    buf[BUFFER_SIZE-1] = '\0';
    syslog(priority, "%s", buf);
}

mysyslog.h:

#include <syslog.h>
void my_syslog_locate(const char *file, int line);
void my_syslog(int priority, const char *fmt, ...);
#define printlog (my_syslog_locate(__FILE__, __LINE__), my_syslog)

mysyslog_test.c:

#include "mysyslog.h"
int
main(void)
{
    printlog(LOG_INFO, "error - %d", 12345);
    return 0;
}

GCC拡張を使うと一番簡単にかけます。

#include <syslog.h>
#define mysyslog(priority, fmt, arg...) syslog(priority, "%s:%d: " fmt, __FILE__, __LINE__, ##arg)
int
main(void)
{
    mysyslog(LOG_INFO, "info - %d", 12345);
    mysyslog(LOG_INFO, "info");
    return 0;
}

C99の可変長引数マクロは単純に__VA_ARGS__を使うだけだと、省略した場合にエラーになるので悩んでしまったのですが、

http://tdiary.flowernet.gr.jp/masm/?date=20051207

を参考にしてこのようにすると回避できました。

#include <syslog.h>
#define mysyslog(priority, ...) mysyslog_(priority, __FILE__, __LINE__, __VA_ARGS__)
#define mysyslog_(priority, FILE, LINE, ...) mysyslog__(priority, FILE, LINE, __VA_ARGS__)
#define mysyslog__(priority, FILE, LINE, ...) syslog(priority, FILE ":" #LINE " " __VA_ARGS__)
int
main(void)
{
    mysyslog(LOG_INFO, "info - %d", 12345);
    mysyslog(LOG_INFO, "info");
    return 0;
}
id:eimu

一通りやってみましたが、

GCC拡張とvsyslogが良さそうですね。

それぞれの問題点があるのかとかは

まだ全然把握してないですが。なんかあるの

でしょうか?

GCC拡張はsyslog使わないログ出力も

できそうですし、vsyslogはもともと

可変長引数を受け付ける関数のようですし。

引き続き回答を受け付けますのでよろしくお願いします。ひとまず今日の朝8時ぐらいまで受け付けます。

2006/07/05 00:29:43
id:kurukuru-neko No.2

kurukuru-neko回答回数1844ベストアンサー獲得回数1552006/07/04 01:12:41

ポイント35pt

可変長マクロを利用した方法で可能です。

http://www.linux.or.jp/JM/html/LDP_man-pages/man3/syslog.3.html


C99規格 可変個数の引き数をもつマクロ

http://www.cqpub.co.jp/interface/column/freesoft/2003/200305/0.h...

  • xxx.h ---

#define SINFO(fmt,...) \

vsyslog(LOG_INFO,"%s:%d" fmt, \

__FILE__,__LINE__,__VA_ARGS__)

#define SDBG(fmt,...) \

vsyslog(LOG_DEBUG,"%s:%d" fmt, \

__FILE__,__LINE__,__VA_ARGS__)


//プログラムの最初

openlog("XXXX",LOG_NDELAY,LOG_USER);

SINFO("MSG ");

SDBG("FFF RC=%d",123);

// 最後に

closelog();


GCC,AIX,SUNだと 可変個数の引数の書式が少し違う

場合がマクロを切り替える。

可変個数の引数を持つマクロ

http://www.asahi-net.or.jp/~wg5k-ickw/html/online/gcc-2.95.2/gcc...

Developing and Porting

C and C++ Applications on AIX

Page 9

http://www.redbooks.ibm.com/redbooks/pdfs/sg245674.pdf

Solaris k. 引数の個数が可変のプリプロセッサ関数マクロ

http://jp.sun.com/products/software/tools/fd602/documentation/mr...

※:コンパイルはしていないのでエラーになるかもしれません。

id:eimu

早速の返信お二方どうもありがとうございます。

回答を見て、結構自分には難易度が高いように感じたので、少し自分で調べて確認後また回答を受け付けるようにします。1、2日かかると

思います。

現時点で2つ分からなかったのが、

syslog単体でいきなりCallできるにも関わらず、

openlog,closelogがあるのはどういうこと

なのでしょうか?

当方の開発環境はAIXで、

openlog_r closelog_r とか書いてあった

はずです。

OSによって使い方が違うということ

なのでしょうか?

それとも、別の理由があるのでしょうか?

自分のAIX環境では、

printlog(LOG_INFO,__FILE__,__LINE__, "error - %d", 12345);

のようにして、呼び出し元で最初から

__FILE__と__LINE__を書いていました。

つまりは、マクロを使わずに構築していた

のですが、マクロを使わないことによる

メリットがあるからこのように構築した

のでしょうか?業界的にどちらが

メジャーなやりかたなのかが気になりました。

質問が多くなってしまいましたが、分かれば

よろしくお願いします。

2006/07/04 02:04:19

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません