A Day In The Life

とあるプログラマの備忘録

whoコマンドを作成してみた。

Unix/Linuxプログラミング理論と実践
Bruce Molay
アスキー・メディアワークス

このアイテムの詳細を見る
Unix/Linuxプログラミング理論と実践という本を読んでUnixの基本とC言語について勉強しています。

whoコマンドの作り方が載っていたので本の通り作成してみました。

内容は簡単でユーザのログイン情報が書き込まれるutmpというファイルを読み込んでutmp構造体にデータを格納し表示するだけです。

#include <stdio.h>
#include <unistd.h>
#include <utmp.h>
#include <fcntl.h>
#include <time.h>

void show_info(struct utmp *);
void show_time(long);

int main() {
  struct utmp utbuf;
  int utmpfd;
  if ((utmpfd = open(UTMP_FILE, O_RDONLY)) == -1) {
    perror(UTMP_FILE);
    return 1;
  }
  while (read(utmpfd, &utbuf, sizeof(utbuf)) == sizeof(utbuf))
    show_info(&utbuf);
  close(utmpfd);
  return 0;
}

void show_info(struct utmp *utbufp) {
  if (utbufp->ut_type != USER_PROCESS)
    return;
  printf("%-8.8s", utbufp->ut_name);
  printf(" ");
  printf("%-8.8s", utbufp->ut_line);
  printf(" ");
  show_time(utbufp->ut_time);
  if (utbufp->ut_host[0] != '\0')
    printf(" (%s)", utbufp->ut_host);
  printf("\n");
}

void show_time(long timeval) {
  char *cp;
  cp = ctime(&timeval);
  printf("%12.12s", cp + 4);
}

Fedora上では問題なくコンパイルが通り動いたのですがMac OS Xだといろんな箇所でコンパイルエラーになりうまくいきませんでした。

しかもutmpは非推奨とまでいわれる始末です。

more /usr/include/utmp.h
でヘッダファイルの中身を見てみるとなんか構造が微妙に違うし...。

調べてみるとMac OS X Leopardではutmpではなくutmpxを使うのがお作法のようです。

で以下のように修正するとうまく動きました。

#include <stdio.h>
#include <unistd.h>
#include <utmpx.h>
#include <fcntl.h>
#include <time.h>

void show_info(struct utmpx *);
void show_time(long);

int main() {
  struct utmpx utbuf;
  int utmpfd;
  if ((utmpfd = open(UTMPX_FILE, O_RDONLY)) == -1) {
    perror(UTMPX_FILE);
    return 1;
  }
  while (read(utmpfd, &utbuf, sizeof(utbuf)) == sizeof(utbuf))
    show_info(&utbuf);
  close(utmpfd);
  return 0;
}

void show_info(struct utmpx *utbufp) {
  if (utbufp->ut_type != USER_PROCESS)
    return;
  printf("%-8.8s", utbufp->ut_user);
  printf(" ");
  printf("%-8.8s", utbufp->ut_line);
  printf(" ");
  show_time(utbufp->ut_tv.tv_sec);
  if (utbufp->ut_host[0] != '\0')
    printf(" (%s)", utbufp->ut_host);
  printf("\n");
}

void show_time(long timeval) {
  char *cp;
  cp = ctime(&timeval);
  printf("%12.12s", cp + 4);
}

Macはなんでutmpを非推奨にしてutmpxにしたんでしょう。
こういう微妙な違いが意外に面白かったりするんですけどね。