忍者ブログ
PCメモ
PC関係のメモ、気付いたこと。 simhとChromium OSをいじって遊んでいます。 Chromium OSのカスタムビルドを配布しています。(http://chromiumosde.gozaru.jp) twitter: @zui22904336 PGP fingerprint: 45FC 0E47 A68A FA06 02FE 2BEF B72C C6E6 F9FF 1C19
Admin / Write
2014/03/01 (Sat) 22:52
ここまでsimhのPDP-11エミュレータにUNIX V7をインストールしてきましたが、やはり気になるのは日付関連です。

起動直後の状態はこんな感じになっています。

# date
Thu Sep 22 05:47:43 EDT 1988

これを修正しようとするとこうなります。
# date 1403011921
Sun Mar  1 19:21:00 EST 1970
# 

1970年に戻ってしまいました。いわゆる2000年問題というやつですね。 また、タイムゾーンがEST(アメリカの東部標準時)になっているのも気になります。
今回はこの辺を直してみようと思います。

まず、OSのタイムゾーンの変更を行います。UNIX V7でタイムゾーンを変更するためには、ソースを修正したうえでカーネルを再構築する必要があります。修正するソースコードは/usr/sys/h/param.hです。今使っているSoftware Kitの環境では/mnt/usr/sys/h/param.hにあります(こちらの記事参照)。中身はこんな感じです。

# cat param.h
 
/*
 * tunable variables
 */

#define NBUF    29              /* size of buffer cache */
#define NINODE  200             /* number of in core inodes */
#define NFILE   175             /* number of in core file structures */
#define NMOUNT  8               /* number of mountable file systems */
#define MAXMEM  (64*32)         /* max core per process - first # is Kw */
#define MAXUPRC 25              /* max processes per user */
#define SSIZE   20              /* initial stack size (*64 bytes) */
#define SINCR   20              /* increment of stack (*64 bytes) */
#define NOFILE  20              /* max open files per process */
#define CANBSIZ 256             /* max size of typewriter line */
#define CMAPSIZ 50              /* size of core allocation area */
#define SMAPSIZ 50              /* size of swap allocation area */
#define NCALL   20              /* max simultaneous time callouts */
#define NPROC   150             /* max number of processes */
#define NTEXT   40              /* max number of pure texts */
#define NCLIST  100             /* max total clist size */
#define HZ      60              /* Ticks/second of the clock */
#define TIMEZONE (5*60)         /* Minutes westward from Greenwich */
#define DSTFLAG 1               /* Daylight Saving Time applies in this locality */
#define MSGBUFS 128             /* Characters saved from error messages */
#define NCARGS  5120            /* # characters in exec arglist */
(略)

ここの#define TIMEZONEで指定している値を日本時間に直します。
また、DSTFLAGでサマータイムの設定をしています。日本で使う場合は必要ないのでここを0に変えます。修正後は以下のようになります。
#define TIMEZONE (-9*60)                /* Minutes westward from Greenwich */
#define DSTFLAG 0               /* Daylight Saving Time applies in this locality

修正を行ったらカーネルを再構築します。このとき、makeだけではだめで、make allしてからmakeします。
# cd /mnt/usr/sys/conf
# make all
cd ../sys; cc -c -O *.c; mklib; rm *.o
acct.c:
(略)
# make
as -o mch.o mch0.s mch.s
ld -o unix -X -i l.o mch.o c.o ../sys/LIB1 ../dev/LIB2
#

とりあえずこれでOSは日本時間で動くようになりましたが、今のままではタイムゾーン表示ができません。タイムゾーンの表示のための処理は/usr/src/libc/gen/timezone.cにあります。
カーネルソースと違い、ライブラリやコマンドのソースはもとから入っています。 中身をみるとアメリカの各地区とGMTしかタイムゾーンの定義が入っていません。
# cd /usr/src/libc/gen
# cat timezone.c

/*
 * The arguments are the number of minutes of time
 * you are westward from Greenwich and whether DST is in effect.
 * It returns a string
 * giving the name of the local timezone.
 *
 * Sorry, I don't know all the names.
 */

static struct zone {
        int     offset;
        char    *stdzone;
        char    *dlzone;
} zonetab[] = {
        4*60, "AST", "ADT",             /* Atlantic */
        5*60, "EST", "EDT",             /* Eastern */
        6*60, "CST", "CDT",             /* Central */
        7*60, "MST", "MDT",             /* Mountain */
        8*60, "PST", "PDT",             /* Pacific */
        0, "GMT", 0,                    /* Greenwich */
        -1
};
(略)

これではどうしようもないのでタイムゾーンの定義に日本時間を表すJSTを追加します。
(略)
static struct zone {
        int     offset;
        char    *stdzone;
        char    *dlzone;
} zonetab[] = {
        4*60, "AST", "ADT",             /* Atlantic */
        5*60, "EST", "EDT",             /* Eastern */
        6*60, "CST", "CDT",             /* Central */
        7*60, "MST", "MDT",             /* Mountain */
        8*60, "PST", "PDT",             /* Pacific */
        -9*60, "JST", 0,   ← 追加
        0, "GMT", 0,                    /* Greenwich */
        -1
};
(略)

これでソースを再コンパイルします。
# cc -c -O timezone.c

timezoneはlibc.aの一部なので、作成したオブジェクトでlibc.aの中身を置き換えます。
# cd /lib
# cp libc.a libc.a.org
# ar r libc.a /usr/src/libc/gen/timezone.o

最後はdateコマンドの修正です。ソースは/usr/src/cmd/date.cです。問題の処理はgtime()関数にあり、入力された年を無条件で1900年代と扱うようになっています。今回はとりあえず年の値が50以下だったら2000年代と扱うようにします。
(略)
gtime()
{
(略)
        if (hour==24) {
                hour=0; day++;
        }
        if (hour<0 hour="">23)
                return(1);
        timbuf = 0;
        /* fix y2k */
        /*year += 1900;*/  ← ここを修正
        if (year > 50){
                year += 1900;
        }
        else{
                year += 2000;
        }
        /* fix y2k end */
        for(i=1970; i<year; i++)
                timbuf += dysize(i);
        /* Leap year */
        if (dysize(year)==366 && month >= 3)
                timbuf++;
        while(--month)
                timbuf += dmsize[month-1];
        timbuf += day-1;
        timbuf = 24*timbuf + hour;
        timbuf = 60*timbuf + mins;
        timbuf = 60*timbuf + secs;
        return(0);

}


これをコンパイルして/bin/dateを置き換えます。
# cd /usr/src/cmd
# cc -o date date.c
# mv /bin/date /bin/date.org
# cp ./date /bin/

最後にカーネルを置き換えてリブートします。
# cp /mnt/usr/sys/conf/unix /unix
# sync;sync;sync;
# (Ctrl-E)

リブート後のコマンド実行結果はこんな感じです。
# date 1403012025
Sat Mar  1 20:25:00 JST 2014
# date
Sat Mar  1 20:25:02 JST 2014
# date -u
Sat Mar  1 11:25:07 GMT 2014

date -uは日時をGMTで表示します。9時間差なのでうまくいったようです。
ほかにも2000年問題はあると思いますが、気になったら対処するということで今回はここまで。
 
  
[関連記事]



ランキングに参加してみました。クリックしていただければ嬉しいです。

にほんブログ村 IT技術ブログ IT技術メモへ
にほんブログ村

パソコン ブログランキングへ

拍手[0回]

PR


Comment
Name
Title
Mail
URL
Comment
Pass   Vodafone絵文字 i-mode絵文字 Ezweb絵文字
  HOME   15  14  13  12  11  10  9  8  7  6  5 
プロフィール
HN:
zui
性別:
非公開
PR
忍者カウンター
忍者ブログ [PR]