Solaris 共通デスクトップ環境 プログラマーズ・ガイド

コーディング例

カレンダのリストおよび出力


例 10-1 サーバがサポートするカレンダをリストし出力する

Example:
List and print out the calendars supported by a server.
 	   Free memory returned by a CSA function. 
list_calendar() 
{
 	CSA_return_code		stat;
	CSA_uint32		i, number;
 	CSA_calendar_user	*calendars;
 	char			*host;

  	/* ネットワーク上のいくつかのマシンを指定します */
 	host = "somehost";

  	stat= csa_list_calendars(host, &number, &calendars, NULL);
  	for (i = 0; i< number; i++) {
 		/* calendar_address フィールドには、カレンダのアドレスが
 		 * user@host の書式で入っています		 */
 	printf("%d: %s¥n", i, calendars[i].calendar_address); 	
   }

  	/* 例: CSA 関数により返されるメモリを解放する
 	 * csa_list_calendars により返されるメモリを解放します
 	 */
 	stat = csa_free(calendars); 
}


カレンダの追加


例 10-2 activity という名前のカレンダをホスト host1 に追加する

#include <csa/csa.h>  

CSA_access_rights *setup_access_list() {
 	CSA_access_rights	*ptr1, *ptr2;
  	/* 任意のユーザに、公開および非公開エントリを表示する許可を与え、
 	 * ユーザ user1 に、公開エントリを表示し、挿入する許可を与えます。
 	 * 特別なユーザ名 world は任意のユーザを意味します。
   */

ptr2 = (CSA_access_rights *)calloc(1, sizeof(CSA_access_rights));
ptr2->user = (CSA_calendar_user *)calloc(1, sizeof(CSA_calendar_user));
ptr2->user->user_name = strdup("world");
ptr2->user->user_type = CSA_USER_TYPE_INDIVIDUAL;
ptr2->flags = CSA_VIEW_PUBLIC_ENTRIES | CSA_VIEW_CONFIDENTIAL_ENTRIES;
ptr1 = (CSA_access_rights *)calloc(1, sizeof(CSA_access_rights));
ptr1->user = (CSA_calendar_user *)calloc(1, sizeof(CSA_calendar_user));
ptr1->user->user_name = strdup("user1");
ptr1->user->user_type = CSA_USER_TYPE_INDIVIDUAL;
ptr1->flags = CSA_VIEW_PUBLIC_ENTRIES | CSA_INSERT_PUBLIC_ENTRIES;
ptr1->next = ptr2; 
} 

void destroy_access_list(CSA_access_rights *list) 
{
 	CSA_access_rights	*ptr;

  	while (list != NULL) {
 		ptr = list->next;

  		if (list->user) {
 			if (list->user->user_name)
 			free(list->user->user_name);
 			free(list->user);
 		} 		free(list);
  		list = ptr;
 	}
} 
add_calendar() 
{
 	CSA_return_code		stat;
 	CSA_calendar_user	caddr;
 	CSA_attribute		attr;
 	CSA_attribute_value	attr_val;

  	/* 追加するカレンダを指定します。 */

 	caddr.user_name = NULL;
 	caddr.user_type = NULL;
 	caddr.calendar_address = "activity@host1";
 	caddr.calendar_user_extensions = NULL;

  	/* アクセス・リストを設定します */
 	attr_val.type			= CSA_VALUE_ACCESS_LIST;
 	attr_val.item.access_list_value	= setup_access_list();
 	attr.name			= CSA_CAL_ATTR_ACCESS_LIST;
 	attr.value			= &attr_val;
 	attr.attribute_extensions	= NULL;
  	stat = csa_add_calendar(NULL, &caddr, 1, &attr, NULL);
  	destroy_access_list(attr_val.item.access_list_value);
}


カレンダへのログイン


例 10-3 カレンダにログインする

CSA_session_handle	cal;

logon() 
{
 	CSA_return_code		stat;
 	CSA_calendar_user	caddr;
 	CSA_flags		access;
 	CSA_extension		logon_exts[2];
 	CSA_X_COM_support	check_support[2];

  	/* ログインするカレンダを指定します */
caddr.user_name = NULL;
caddr.user_type = CSA_USER_TYPE_INDIVIDUAL;
caddr.calendar_address = "user@host";
caddr.calendar_user_extensions = NULL;

  	/* (CSA_X_DT_GET_USER_ACCESS_EXT) を指定して、
 	 * カレンダに関するユーザのアクセス権を取得します。
 	 */
logon_exts[0].item_code		= CSA_X_DT_GET_USER_ACCESS_EXT;
logon_exts[0].item_data		= 0;
logon_exts[0].item_reference	= NULL;
logon_exts[0].extension_flags	= NULL;

	/* CSA_X_COM_SUPPORT_EXT 拡張を指定して、
 	 * CSA_X_XT_APP_CONTEXT_EXT 拡張と、CSA_X_UI_ID_EXT 拡張が
 	 * サポートされているかどうかをチェックします。
 	 */
check_support[0].item_code	= CSA_X_XT_APP_CONTEXT_EXT;
check_support[0].flags		= NULL;
check_support[1].item_code	= CSA_X_UI_ID_EXT;
check_support[1].flags		= NULL;
logon_exts[1].item_code		= CSA_X_COM_SUPPORT_EXT;
logon_exts[1].item_data		= 2;
logon_exts[1].item_reference	= (CSA_buffer)check_support;
logon_exts[0].extension_flags	= CSA_EXT_LAST_ELEMENT;

  	stat = csa_logon(NULL, &caddr, NULL, NULL, NULL, &cal, logon_exts);

  	if (stat == CSA_SUCCESS) {
 		access = (CSA_flags)get_access_ext.item_data;
  		if (check_support[0].flag & CSA_X_COM_SUPPORTED)
 			printf("The CSA_X_XT_APP_CONTEXT_EXT extension is supported¥n");
  		if (check_support[1].flag & CSA_X_COM_SUPPORTED)
 			printf("The CSA_X_UI_ID_EXT extension is supported¥n");
 	}
 }


カレンダ・セッションの終了


例 10-4 カレンダ・セッションを終了する

logoff() 
{
 	CSA_return_code		stat;

  	/* セッションが必要ない場合は、csa_logoff を呼び出すことにより終了できます。
 	 * 前の例で csa_logon により返されたセッションを終了します。
 	 */
 	stat = csa_logoff(cal, NULL); 
}


カレンダの削除


例 10-5 カレンダを削除する

delete_calendar() 
{
 	/* csa_logon() を呼び出すことによりカレンダ・セッションを確立後、
 	 * csa_delete_calender() を使用してカレンダを削除できます。
 	 */
 	CSA_return_code		stat;
  	stat = csa_delete_calendar(cal, NULL);
}


カレンダ・エントリの追加


例 10-6 カレンダ・エントリを追加する

#include <csa/csa.h>  

CSA_return_code		stat;
CSA_session_handle	cal;
CSA_attribute		attrs[9];
CSA_attribute_value	attr_val[9];
CSA_reminder		audio;
CSA_reminder		mail;
CSA_entry_handle	new_entry;
int			i;

i = 0;

/* 開始日の属性。この属性にはデフォルトがないため、必ず指定してください。
 * CSA_date_time 値は、ISO 8601 規格にある UTC ベースの日付と時間を指定します。
 */
attrs[i].name = CSA_ENTRY_ATTR_START_DATE;
 attrs[i].value = &attr_val[i];
 attrs[i].attribute_extensions = NULL;
 attr_val[i].type = CSA_VALUE_DATE_TIME;
 attr_val[i].item.date_time_value = iso8601time(time(NULL));
 i++;

/* 終了日の属性。
 * 指定しないと、エントリは終了日の属性を持ちません。
 */ 
attrs[i].name = CSA_ENTRY_ATTR_END_DATE;
 attrs[i].value = &attr_val[i];
 attrs[i].attribute_extensions = NULL;
 attr_val[i].type = CSA_VALUE_DATE_TIME;
 attr_val[i].item.date_time_value = iso8601time(time(NULL) + 3600);
 i++;

/* 分類属性。
 * 指定しないと、デフォルト値は CSA_CLASS_PUBLIC になります。
 */ 
attrs[i].name = CSA_ENTRY_ATTR_CLASSIFICATION;
attrs[i].value = &attr_val[i];
attrs[i].attribute_extensions = NULL;
attr_val[i].type = CSA_VALUE_UINT32;
attr_val[i].item.sint32_value = CSA_CLASS_CONFIDENTIAL;
i++;  

/* タイプ属性。
 * この属性にはデフォルトがないため、必ず指定してください。
 */
attrs[i].name = CSA_ENTRY_ATTR_TYPE;
attrs[i].value = &attr_val[i];
attrs[i].attribute_extensions = NULL;
attr_val[i].type = CSA_VALUE_UINT32;
attr_val[i].item.sint32_value = CSA_TYPE_EVENT;
i++;

/* サブタイプ属性。
 * 指定しないと、デフォルト値は CSA_SUBTYPE_APPOINTMENT になります。
 */ 
attrs[i].name = CSA_ENTRY_ATTR_SUBTYPE;
attrs[i].value = &attr_val[i];
attrs[i].attribute_extensions = NULL;
attr_val[i].type = CSA_VALUE_STRING; 
attr_val[i].item.string_value = CSA_SUBTYPE_APPOINTMENT; 
i++;  

/* サマリ属性 */
attrs[i].name = CSA_ENTRY_ATTR_SUMMARY; 
attrs[i].value = &attr_val[i]; 
attrs[i].attribute_extensions = NULL; 
attr_val[i].type = CSA_VALUE_STRING; 
attr_val[i].item.string_value = argv6; 
attrs[i].attribute_extensions = NULL; 
i++;

/* 反復規則属性。
 * 指定しないと、エントリは 1 回だけのエントリになります。反復規則 D1 #3 は、
 * エントリが毎日 3 日間繰り返されるよう指定します。
 */ 
attrs[i].name = CSA_ENTRY_ATTR_RECURRENCE_RULE; 
attrs[i].value = &attr_val[i]; 
attrs[i].attribute_extensions = NULL; 
attr_val[i].type = CSA_VALUE_STRING; 
attr_val[i].item.string_value = argv7; 
i++;

/* オーディオ通知属性。
 * 通知プログラムのリード・タイムは、ISO 8601 規格にある CSA_time_duration の値で
 * 指定します。
 * たとえば、5 分間のリード・タイムは、文字列 +PT300S と表します。
 * マイナス 5 分間のリード・タイムは、-PT300S と表します。
 */ 
attrs[i].name = CSA_ENTRY_ATTR_AUDIO_REMINDER; 
attrs[i].value = &attr_val[i]; 
attrs[i].attribute_extensions = NULL; 
attr_val[i].type = CSA_VALUE_REMINDER; 
attr_val[i].item.reminder_value = &audio; 
memset((void *)&audio, NULL, sizeof(audio)); 
audio.lead_time = "+PT300S"; i++;

/* メール通知属性。
 * 電子メール・アドレスは、reminder_data フィールドに指定します。
 * この通知プログラムのリード・タイムは 1 日。
 */ 
attrs[i].name = CSA_ENTRY_ATTR_MAIL_REMINDER; 
attrs[i].value = &attr_val[i]; 
attrs[i].attribute_extensions = NULL; 
attr_val[i].type = CSA_VALUE_REMINDER; 
attr_val[i].item.reminder_value = &mail; 
memset((void *)&mail, NULL, sizeof(mail)); 
mail.lead_time = "+PT86400S"; 
mail.reminder_data.data = "someuser@somehost"; 
mail.reminder_data.size = strlen(mail.reminder_data.data); 
i++;

/* 指定した属性値でエントリを追加します */
stat = csa_add_entry(cal, i, attrs, &newentry, NULL);  
if (stat == CSA_SUCCESS)
 	csa_free((CSA_buffer)newentry);


カレンダのエントリの検索


例 10-7 カレンダのエントリを検索する/属性値を読み取る

#include <csa/csa.h>  

CSA_return_code		stat; 
CSA_session_handle	cal;
CSA_attribute		attrs[4]; 
CSA_attribute_value	attr_val[4]; 
CSA_enum		ops[4];
CSA_uint32		i; 
CSA_uint32		num_entries;
CSA_entry_handle	*entries;
CSA_uint32		num_attributes; 
CSA_attribute		*entry_attrs;  

/* 次の判断基準ですべてのエントリを検索します。
 * UTC 時間 1996 年 8 月のすべてのアポイント
 * 開始日は、UTC 時間 1996 年 8 月 1 日 00:00:00 以降
 * 開始日は、UTC 時間 1996 年 9 月 1 日 00:00:00 より前
 * タイプは CSA_TYPE_EVENT 
 * サブタイプは CSA_SUBTYPE_APPOINTMENT
 */  

i = 0;  

/* 開始日は、UTC 時間 1996 年 8 月 1 日 00:00:00 以降 */
attrs[i].name = CSA_ENTRY_ATTR_START_DATE; 
attrs[i].value = &attr_val[i]; 
attrs[i].attribute_extensions = NULL; 
attr_val[i].type = CSA_VALUE_DATE_TIME;
attr_val[i].item.date_time_value = "19960801T000000Z"; 
ops[i] = CSA_MATCH_GREATER_THAN_OR_EQUAL_TO; 
i++;

/* 開始日は、UTC 時間 1996 年 9 月 1 日 00:00:00 より前 */
attrs[i].name = CSA_ENTRY_ATTR_START_DATE; 
attrs[i].value = &attr_val[i]; 
attrs[i].attribute_extensions = NULL; 
attr_val[i].type = CSA_VALUE_DATE_TIME; 
attr_val[i].item.date_time_value = "19960901T000000Z" 
ops[i] = CSA_MATCH_LESS_THAN; 
i++;  

/* タイプは CSA_TYPE_EVENT */ 
attrs[i].name = CSA_ENTRY_ATTR_TYPE; 
attrs[i].value = &attr_val[i]; 
attrs[i].attribute_extensions = NULL; 
attr_val[i].type = CSA_VALUE_UINT32; 
attr_val[i].item.sint32_value = CSA_TYPE_EVENT; 
ops[i] = CSA_MATCH_EQUAL_TO; 
i++;

/* サブタイプは CSA_SUBTYPE_APPOINTMENT */
attrs[i].name = CSA_ENTRY_ATTR_SUBTYPE; 
attrs[i].value = &attr_val[i]; 
attrs[i].attribute_extensions = NULL; 
attr_val[i].type = CSA_VALUE_STRING; 
attr_val[i].item.string_value = CSA_SUBTYPE_APPOINTMENT; 
ops[i] = CSA_MATCH_EQUAL_TO; 
i++;

/* 検索の実行 */
stat = csa_list_entries(csa, i, attrs, ops, &num_entries, &entries, NULL);

  if (stat == CSA_SUCCESS) {
     for (i = 0; i < num_entries; i++) {
	/* エントリのすべての属性値を取得します。
	 * number_names に 0 を指定し、attribute_names に NULL を指定すると、
	 * すべての属性値が返されます。
 	 */ 	
   stat = csa_read_entry_attributes(cal, entries[i], 0, NULL,
 					 &num_attributes, &entry_attrs,
 					 NULL); 	if (stat == CSA_SUCCESS) {
	    /* 返された属性値を使用し、終了時にメモリを解放します
 	     */
 	    csa_free(entry_attrs);
 	} else {
	    /* ハンドル・エラー */
 	}
     }
 } else {
     /* ハンドル・エラー */
}   

Example: Change the end time of the returned appointments to be
 	 one hour later.

CSA_attribute_reference	name = CSA_ENTRY_ATTR_END_DATE; 
char			buffer[80]; 
time_t			endtime; 
CSA_entry_handle	new_entry;

for (i = 0; i < num_entries; i++) {
     /* アポイントの終了時間を取得します */
     stat = csa_read_entry_attributes(cal, entries[i], 0, &name,
 				    &num_attributes, &entry_attrs, NULL);
     if (stat == CSA_SUCCESS) {
	/* 終了時間を 1 時間後に変更します */
 	from_iso8601_time(entry_attrs[0].value->item.date_time_value, &endtime);
 	endtime += 60*60 /* 1 時間の秒数 */
 	to_iso8601_time(endtime, buffer);
    attrs[0].name = CSA_ENTRY_ATTR_END_DATE;
    attrs[0].value = &attr_val[i];
    attrs[0].attribute_extensions = NULL;	
    attr_val[0].type = CSA_VALUE_DATE_TIME;
 	attr_val[0].item.date_time_value = buffer;
  	stat = csa_update_entry_attributes(cal, entries[0], CSA_SCOPE_ALL,
 			      	CSA_FALSE, 1, attrs, &new_entry,
 					   NULL);
 	if (stat == CSA_SUCCESS) {
 	    csa_free(new_entry);
 	} else {
 	    /* ハンドル・エラー */
 	}
  	csa_free(entry_attrs);
      } else {
 	    /* ハンドル・エラー */
     } 
}


カレンダのエントリの更新


例 10-8 返されたアポイントの終了時間を 1 時間後に変更する

CSA_attribute_reference	name = CSA_ENTRY_ATTR_END_DATE; 
char			buffer[80]; 
time_t			endtime; 
CSA_entry_handle	new_entry;  

for (i = 0; i < num_entries; i++) {
     /* アポイントの終了時間を取得します */
     stat = csa_read_entry_attributes(cal, entries[i], 0, &name,
 				     &num_attributes, &entry_attrs, NULL);
     if (stat == CSA_SUCCESS) {
	/* 終了時間を 1 時間後に変更します */
 	from_iso8601_time(entry_attrs[0].value->item.date_time_value, &endtime);
 	endtime += 60*60 /* 1 時間の秒数 */
 	to_iso8601_time(endtime, buffer);

  	attrs[0].name = CSA_ENTRY_ATTR_END_DATE;
 	attrs[0].value = &attr_val[i];
 	attrs[0].attribute_extensions = NULL;
 	attr_val[0].type = CSA_VALUE_DATE_TIME;
 	attr_val[0].item.date_time_value = buffer;
  	stat = csa_update_entry_attributes(cal, entries[0], CSA_SCOPE_ALL,
 					   CSA_FALSE, 1, attrs, &new_entry,
 					   NULL); 	if (stat == CSA_SUCCESS) {
 	    csa_free(new_entry);
 	} else {
 	    /* ハンドル・エラー */
 	}
  	csa_free(entry_attrs);
      } else {
 	    /* ハンドル・エラー */
    }
}


コールバックの登録および通知プログラムの保持


例 10-9 コールバックを登録し、通知プログラムを保持する

/* このコーディング例では、csa_register_callback、csa_read_next_reminder、
  * および csa_call_callbacks の使用方法について示します。
  * 基本となるコードでは、イベント CSA_CB_ENTRY_ADDED、CSA_CB_ENTRY_DELETED、
  * および CSA_CB_ENTRY_UPDATED 用のコールバック・ルーチンを登録します。
  * また、別のコールバック・ルーチンを、CSA_CB_CALENDAR_ATTRIBUTE_UPDATE 
  * イベント用に登録します。
  * 通知デリバリ用のタイマを設定する方法も示します。
  * ISO 8601 書式の時間表記を UTC 1970 年 1 月 1 日 00:00:00 からの経過秒数を示す
  * ティック数への変換用の 2 つのユーティリティ・ルーチンも含みます。
  */ 

#include <csa/csa.h> 
#include <time.h> 
#include <unistd.h>  

CSA_session_handle	cal;	 /* カレンダ・セッション */
time_t			run_time; /* 通知プログラムを実行する時間 */ 
CSA_uint32		num_rems; /* 返される通知数 */
CSA_reminder_reference	*rems;	  /* 通知情報の配列 */

void 
set_up_callback_handler() 
{
 	CSA_return_code		stat;
 	CSA_flags		flags;

	/* Xt ベースのアプリケーションは、コールバック・ルーチンが非同期に呼び出せるように
	 * するため、CSA_X_XT_APP_CONTEXT_EXT 拡張を使用して、
	 * Xt アプリケーションのコンテキストを指定できます。
  *
  *	CSA_extension callback_ext;
  *	callback_ext.item_code = CSA_X_XT_APP_CONTEXT_EXT;
  * 	callback_ext.item_data = (CSA_uint32)application_context;
  *	callback_ext.extension_flags = CSA_EXT_LAST_ELEMENT;
  *
  * callback_ext を最後のパラメータとして、csa_register_callback に渡す。
  */

  	flags = CSA_CB_ENTRY_ADDED|CSA_CB_ENTRY_DELETED|CSA_CB_ENTRY_UPDATED;
 	stat = csa_register_callback(cal, flags, entry_update_callback,
 		NULL, NULL);

  	if (stat != CSA_SUCCESS) {
		/* エラー処理コード */
 	}

  	stat = csa_register_callback(cal, CSA_CB_CALENDAR_ATTRIBUTE_UPDATED,
 		calendar_update_callback, NULL, NULL);
  	if (stat != CSA_SUCCESS) {
		/* エラー処理コード */
 	} 
}  

/*  * このルーチンはライブラリをポーリングし、特定のイベントが発生していた場合に、
 * 登録されているコールバックを呼び出します。
 * アプリケーションが CSA_X_XT_APP_CONTEXT_EXT 拡張を使用してコールバックの
 * 呼び出しを非同期に設定していない場合、csa_call_callbacks を呼び出して、
 * コールバックの呼び出しを強制する必要があります。
 */ 

check_events(CSA_flags event)
{
 	csa_call_callbacks(cal, event, NULL); 
}

  /*
  * これは、イベント CSA_CB_ENTRY_ADDED、CSA_CB_ENTRY_ADDED、および 
  * CSA_CB_ENTRY_UPDATED のためのコールバック・ルーチンです。
  */ 
void 
entry_update_callback(
 	CSA_session_handle	cal,
 	CSA_flags		flags,
 	CSA_buffer		call_data,
 	CSA_buffer		client_data,
 	CSA_extension		*ext) 
{
	/* エントリが追加、削除、または更新されます。
	 * このコールバック・ルーチンで行う可能性があるのは次のとおりです。
	 *
	 * 1. カレンダ表示の更新
	 * 2. ユーザ自身のカレンダの場合は、通知情報の更新
	 *
	 * このルーチンのコーディング例は通知情報を更新します。
 	 */ 	reset_reminder();
}
 /*
 * これは CSA_CB_CALENDAR_ATTRIBUTE_UPDATED イベントのための
 * コールバック・ルーチンです。
 */ 
void 
calendar_update_callback(
 	CSA_session_handle	cal,
 	CSA_flags		flags,
 	CSA_buffer		call_data,
 	CSA_buffer		client_data,
 	CSA_extension		*ext) 
{
 	/* カレンダ属性を更新する */
}

   /*
  * このルーチンは通知情報を更新します。
  *	 - 既存の情報がある場合は削除する
  *	 - csa_read_next_reminder() を呼び出して、次に転送する通知を取得する
  *	 - 実行時間をチェックし、タイマーを設定する
  */ 
void 
reset_reminder() {
 	CSA_return_code		stat;
 	time_t			current_time;
 	char			isotime[BUFSIZ];
 	CSA_uint32		number_reminders;
 	CSA_reminder_reference	*reminders;

  	current_time = time(NULL);

	/* 既存の情報を削除する */
 	if (rems) {
		/* この比較の目的は、最後に実行された時刻から、現在の時刻までの間に実行された
		 * 通知が失われていないかを確認することです。
 		 */
 		if (current_time > run_time)
 			current_time = run_time;

  		csa_free((CSA_buffer)rems);
 	}

  	to_iso8601_time(current_time, isotime);
 	stat = csa_read_next_reminder(cal, 0, NULL, isotime,
 		&number_reminders, &reminders, NULL);

  	if (stat == CSA_SUCCESS && num_rems > 0) {
 		num_rems = number_reminders;
 		rems = reminders;

		/* タイマーを設定し、通知を転送する。
		 * sigset() を使用して、SIGALRM シグナルのためのシグナル処理を設定します。
 		 */
 		from_iso8601_time(reminders[0].run_time, &run_time);
 		remain = run_time - time(NULL);
 		alarm((remain > 0) ? remain : 1);

		/* Xt ベースのアプリケーションは、XtAppAddTimeOut を使用して
		 * タイマーを設定できます。
 		 */
 	}
}

/*
  * このルーチンは、ISO 8601 書式の時間表記を、UTC 1970 年 1 月 1 日 00:00:00 
  * からの経過秒数を示すティック数へ変換します。
  * このティックはローカル時間に調整されます。
  */ int from_iso8601_time(char *buf, time_t *tick_out) 
{
 	int		year, month, day, hour, min, sec;
 	struct tm	time_str;

  	sscanf(buf, "%4d%2d%2dT%2d%2d%2dZ",
 	    &year, &month, &day, &hour, &min, &sec);

  	time_str.tm_year	= year - 1900;
 	time_str.tm_mon		= month - 1;
 	time_str.tm_mday	= day;
 	time_str.tm_hour	= hour;
 	time_str.tm_min		= min;
 	time_str.tm_sec		= sec;
 	time_str.tm_isdst	= -1;
  	*tick_out = mktime(&time_str);

  	if (*tick_out != (long)-1) {

		/* ローカル・タイムゾーンに調整 */
 		if (time_str.tm_isdst == 0)
 			*tick_out -= timezone;
 		else
 			*tick_out -= altzone;
  		return(0);
 	} else
 		return(-1); 
}  

/*
  * このルーチンは、UTC 1970 年 1 月 1 日 00:00:00 からの経過秒数を示すティック数を、
  * ISO 8601 書式の時間表記へ変換します。
  */ 
int 
to_iso8601_time(time_t tick, char *buf_out) 
{
 	struct tm	time_str;
  	if (gmtime_r(&tick, &time_str)) {

		/* 書式文字列が固定幅 (ゼロで埋め込み) フィールドを強制する。 */
 		sprintf(buf_out, "%04d%02d%02dT%02d%02d%02dZ",
 			time_str.tm_year + 1900,
 			time_str.tm_mon + 1,
 			time_str.tm_mday,
 			time_str.tm_hour,
 			time_str.tm_min,
 			time_str.tm_sec);
  		return (0);
 	} else {
 		return (-1);
 	} 
}