Here are two related code examples. The first one is a C file used to read and write an RMS index file that was used to do session management for a website. The second one is the H file that defines the data scructures used by the C file.
/* */
/* Routines to handle SESDB (session tracking DB) functions */
/* */
#include "sesdb_proto.h"
#include "ttdb_db.h"
#include "ttdb_db_proto.h"
#include "ttdb_msg.h"
#include
#include
#include
struct DGS_SESDB_REC Sesdb_rec;
/* */
/* Create a new sesdb rec. Check to see if the passed in id is in use */
/* if not, then create one. If the id is in use, then this routine does */
/* nothing but a successful get. */
/* */
ulong sesdb_create_new
(
char *new_id
)
{
time_t now;
ulong status;
if ( new_id == NULL) return( TTDB__SESNULLINP);
if ( strlen( new_id) > SESDB_K_MAXIDLEN) return( TTDB__SESTOOLONG);
status = tt_db_lookup( DBF_K_SESDB_IDX, DBF_K_DB_KEY_PRI,
new_id, DBF_K_DB_MAT_EQ);
if LSB_CLR( status)
{
if ( status != TTDB__DBRNF)
return( status);
now = time( 0);
status = tt_db_set_sesdb_rec( new_id, NULL, NULL,
&now, &now, NULL, TRUE);
if LSB_CLR( status) return( status);
status = tt_db_put( DBF_K_SESDB_IDX);
}
return( status);
}
/* */
/* Update the user_id associated with this session. Also, since they are */
/* changing something in the sesdb rec for this session update last_time */
/* */
ulong sesdb_update_user_id
(
char *id, /* session id to update */
ulong new_user_id /* new value for user_id */
)
{
time_t now;
ulong status;
status = sesdb_find( id);
if LSB_CLR( status) return( status);
now = time( 0);
status = tt_db_set_sesdb_rec( id, &new_user_id, NULL,
NULL, (ulong *) &now, NULL, FALSE);
if LSB_CLR( status) return( status);
status = tt_db_update( DBF_K_SESDB_IDX);
return( status);
}
/* */
/* Update the logged_in field for this session record. Also, since they */
/* updating the record, update the last_time field, too. */
/* */
ulong sesdb_update_logged_in
(
char *id, /* session id to update */
ulong new_logged_in /* new value for logged_in */
)
{
time_t now;
ulong status;
status = sesdb_find( id);
if LSB_CLR( status) return( status);
now = time( 0);
status = tt_db_set_sesdb_rec( id, NULL, &new_logged_in,
NULL, (ulong *) &now, NULL, FALSE);
if LSB_CLR( status) return( status);
status = tt_db_update( DBF_K_SESDB_IDX);
return( status);
}
/* */
/* Update the init_time field for this session record. In this case we */
/* will also update the last_time to match to keep from having a situation */
/* where last_time is less than init_time. */
/* */
ulong sesdb_update_init_time
(
char *id, /* session id to update */
ulong new_init_time /* new value for init_time */
)
{
ulong status;
status = sesdb_find( id);
if LSB_CLR( status) return( status);
status = tt_db_set_sesdb_rec( id, NULL, NULL,
&new_init_time, &new_init_time, NULL, FALSE);
if LSB_CLR( status) return( status);
status = tt_db_update( DBF_K_SESDB_IDX);
return( status);
}
/* */
/* Update the last_time field for the sesdb record. We'll ignore the */
/* SESEXPIRED error, since we're updating the last_time field anyway, */
/* which may cause the session to be unexpired. */
/* */
ulong sesdb_update_last_time
(
char *id, /* session id to update */
ulong new_last_time /* new value for last_time */
)
{
ulong status;
status = sesdb_find( id);
if ( LSB_CLR( status) && ( status != TTDB__SESEXPIRED)) return( status);
status = tt_db_set_sesdb_rec( id, NULL, NULL,
NULL, &new_last_time, NULL, FALSE);
if LSB_CLR( status) return( status);
status = tt_db_update( DBF_K_SESDB_IDX);
return( status);
}
/* */
/* Update the iter field for the session record, as well as the last_time */
/* field. */
/* */
ulong sesdb_update_iter
(
char *id, /* session id to update */
ulong new_iter /* new value for iter */
)
{
time_t now;
ulong status;
status = sesdb_find( id);
if LSB_CLR( status) return( status);
now = time( 0);
status = tt_db_set_sesdb_rec( id, NULL, NULL,
NULL, (ulong *) &now, &new_iter, FALSE);
if LSB_CLR( status) return( status);
status = tt_db_update( DBF_K_SESDB_IDX);
return( status);
}
/* */
/* */
/* */
ulong sesdb_get_user_id
(
char *id, /* session id to find */
ulong *user_id /* return value for user_id */
)
{
ulong status;
status = sesdb_find( id);
if LSB_CLR( status) return( status);
status = tt_db_get_sesdb_rec( &Sesdb_rec);
if LSB_CLR( status) return( status);
*user_id = Sesdb_rec.user_id;
return( status);
}
/* */
/* */
/* */
ulong sesdb_get_logged_in
(
char *id, /* session id to find */
ulong *logged_in /* return value for logged_in */
)
{
ulong status;
status = sesdb_find( id);
if LSB_CLR( status) return( status);
status = tt_db_get_sesdb_rec( &Sesdb_rec);
if LSB_CLR( status) return( status);
*logged_in = Sesdb_rec.logged_in;
return( status);
}
/* */
/* */
/* */
ulong sesdb_get_init_time
(
char *id, /* session id to find */
ulong *init_time /* return value for init_time */
)
{
ulong status;
status = sesdb_find( id);
if LSB_CLR( status) return( status);
status = tt_db_get_sesdb_rec( &Sesdb_rec);
if LSB_CLR( status) return( status);
*init_time = Sesdb_rec.init_time;
return( status);
}
/* */
/* */
/* */
ulong sesdb_get_last_time
(
char *id, /* session id to find */
ulong *last_time /* return value for last_time */
)
{
ulong status;
status = sesdb_find( id);
if LSB_CLR( status) return( status);
status = tt_db_get_sesdb_rec( &Sesdb_rec);
if LSB_CLR( status) return( status);
*last_time = Sesdb_rec.last_time;
return( status);
}
/* */
/* */
/* */
ulong sesdb_get_iter
(
char *id, /* session id to find */
ulong *iter /* return value for iter */
)
{
ulong status;
status = sesdb_find( id);
if LSB_CLR( status) return( status);
status = tt_db_get_sesdb_rec( &Sesdb_rec);
if LSB_CLR( status) return( status);
*iter = Sesdb_rec.iter;
return( status);
}
/* */
/* Lookup the record for this session based on the id passed in. Since */
/* the protocol is stateless, we can't count on having a global variable */
/* to play with to maintain information. If the record isn't there */
/* return SESNOTFOUND. Is there, then check for a timeout. */
/* */
ulong sesdb_find
(
char *id
)
{
time_t now;
ulong status;
long elapsed;
if ( id == NULL) return( TTDB__SESNULLINP);
if ( strlen( id) > SESDB_K_MAXIDLEN) return( TTDB__SESTOOLONG);
status = tt_db_lookup( DBF_K_SESDB_IDX, DBF_K_DB_KEY_PRI,
id, DBF_K_DB_MAT_EQ);
if ( status == TTDB__DBRNF) return( TTDB__SESNOTFOUND);
if LSB_CLR( status) return( status);
status = tt_db_get_sesdb_rec( &Sesdb_rec);
if LSB_CLR( status) return( status);
now = time( 0);
elapsed = now - Sesdb_rec.last_time;
if ( elapsed > SESDB_K_TIMEOUTS) return( TTDB__SESEXPIRED);
return( SUCCESS);
}
#ifndef __TTDB_DB
#define __TTDB_DB 1
#include
#include "general_c_defs.h"
/* */
/* */
/* Define constants for the database files */
/* */
#define DBF_K_DB_IDX_MIN 0 /* min index for the _DBF array */
#define DBF_K_MATDB_IDX 0 /* mail addr track idx in _DBF */
#define DBF_K_MATDB_KEY 2 /* 2 keys: db_id, email */
#define DBF_K_MATDB_NAM "MTS_MATDB" /* matdb logical name for dbf */
#define DBF_K_MATDB_MRS 128 /* record size */
#define DBF_K_MATDB_SIG "*MATDB V1*" /* sig in email field, size=56 */
#define DBF_K_MAUIDB_IDX 1 /* mail unique id in _DBF array */
#define DBF_K_MAUIDB_KEY 1 /* number of keys in name db */
#define DBF_K_MAUIDB_NAM "MTS_MAUIDB" /* mail addr unique id db */
#define DBF_K_MAUIDB_MRS 512 /* record size */
#define DBF_K_MAUIDB_SIG "*MAUIDB V1*" /* sig goes in signature, size=11 */
#define DBF_K_UIDB_IDX 2 /* uidb db index in _DBF array */
#define DBF_K_UIDB_KEY 1 /* number of keys in uidb db */
#define DBF_K_UIDB_NAM "MTS_UIDB" /* uidb db name */
#define DBF_K_UIDB_MRS 64 /* record size */
#define DBF_K_UIDB_SIG "*UIDBV1*" /* sig goes in fill, size=8 */
#define DBF_K_UCTDB_IDX 3 /* uct db index in _DBF array */
#define DBF_K_UCTDB_KEY 1 /* number of keys in uct db */
#define DBF_K_UCTDB_NAM "MTS_UCTDB" /* uct db name */
#define DBF_K_UCTDB_MRS 64 /* record size */
#define DBF_K_UCTDB_SIG "*UCTDB V1*" /* sig is in fill field */
#define DBF_K_SRCDB_IDX 4 /* src db index in _DBF array */
#define DBF_K_SRCDB_KEY 1 /* number of keys in src db */
#define DBF_K_SRCDB_NAM "MTS_SRCDB" /* src db name */
#define DBF_K_SRCDB_MRS 64 /* record size */
#define DBF_K_SRCDB_SIG "*SRCDB V1*" /* sig is in description field */
#define DBF_K_UPIDB_IDX 5 /* upi db index in _DBF array */
#define DBF_K_UPIDB_KEY 1 /* number of keys in upi db */
#define DBF_K_UPIDB_NAM "MTS_UPIDB" /* upi db name */
#define DBF_K_UPIDB_MRS 640 /* record size */
#define DBF_K_UPIDB_SIG "*UPIDB V1*" /* sig is in fill field */
#define DBF_K_LPSDB_IDX 6 /* lps db index in _DBF array */
#define DBF_K_LPSDB_KEY 1 /* number of keys in lps db */
#define DBF_K_LPSDB_NAM "MTS_LPSDB" /* lps db name */
#define DBF_K_LPSDB_MRS 32 /* record size */
#define DBF_K_LPSDB_SIG "*LPSDB V1*" /* sig is in fill field */
#define DBF_K_SESDB_IDX 7 /* ses db index in _DBF array */
#define DBF_K_SESDB_KEY 1 /* number of keys in ses db */
#define DBF_K_SESDB_NAM "MTS_SESDB" /* ses db name */
#define DBF_K_SESDB_MRS 64 /* record size */
#define DBF_K_SESDB_SIG "*SESDB V1*" /* sig is in sessid field */
#define DBF_K_CCIDB_IDX 8 /* cci db index in _DBF array */
#define DBF_K_CCIDB_KEY 1 /* number of keys in cci db */
#define DBF_K_CCIDB_NAM "MTS_CCIDB" /* cci db name */
#define DBF_K_CCIDB_MRS 256 /* record size */
#define DBF_K_CCIDB_SIG "*CCIDB V1*" /* sig is in the fill field */
#define DBF_K_DB_IDX_MAX 8 /* max index for the _DBF array */
#define DBF_K_DB_MAT_MIN 0 /* min match type for keyed get */
#define DBF_K_DB_MAT_EQ 0 /* key value should be equal */
#define DBF_K_DB_MAT_GTE 1 /* key value should be >= */
#define DBF_K_DB_MAT_GT 2 /* key value should be > */
#define DBF_K_DB_MAT_MAX 2 /* max match type for keyed get */
#define DBF_K_DB_KEY_PRI 0 /* handy constant for key index */
#define DBF_K_DB_KEY_SEC 1 /* secondary key */
#define DBF_K_DB_KEY_TER 2 /* tertiary key */
#pragma __member_alignment __save
#pragma __nomember_alignment
/* */
/* Database File Def Struct */
/* */
static struct DBF
{
ushort dbf_idx; /* file index number */
ushort dbf_key_cnt; /* number of keys */
ushort dbf_open; /* is it open? */
ushort dbf_opencnt; /* how many times has it been opened?*/
ushort dbf_recset; /* is the record ready for put/upd? */
char *dbf_name; /* database logical name */
char *dbf_signature; /* signature string to match in db */
void *dbf_rec; /* ptr to current record struct */
} ;
/* */
/* Database Global Struct */
/* */
struct DGS
{
ulong dgs_inited; /* has dgs struct been inited? */
ulong dgs_prev_db_id; /* last get db_id used */
struct DBF dgs_dbf[DBF_K_DB_IDX_MAX+1]; /* database file array */
} ;
/* */
/* Mail Address Tracking Database layout. Main database of email addresses */
/* The db_id is kept in the MAUIDB (see below). Since we expect to have > */
/* than 100M email addresses, the aim is to keep this small. If email lens */
/* >= 88 are encountered, split them into another file. */
/* */
#define MATDB_K_MAXELEN 88 /* maximum acceptable email address length */
struct DGS_MATDB_REC
{
ulong db_id; /* key 0, no dup, insert cnt */
ulong init_status; /* initial delivery status */
ulong last_status; /* last delivery status, see values below */
ulong source; /* where'd we get this email address? */
uquad init_time; /* when was the initial send done? */
uquad last_time; /* when was last_status updated? */
ulong flag; /* handy flag that might be used later */
ulong back_link; /* set to the db_id of previous email rec if */
/* this is a changed email address */
char email[MATDB_K_MAXELEN]; /* key 1, nodup, len > max rejected */
} ;
/* */
/* Mail Address Tracking delivery status values */
/* */
#define MATDB_K_NOACTION 0 /* no attempt has been made to this addr */
#define MATDB_K_SENT_OK 1 /* no error occured during initial send */
#define MATDB_K_RELAY_REJECT 2 /* rejected for relay reasons */
#define MATDB_K_SPAM_REJECT 3 /* rejected for spam reasons */
#define MATDB_K_NOHOST_REJECT 4 /* host name invalid */
#define MATDB_K_INVADDR_REJECT 5 /* user address invalid, host OK */
#define MATDB_K_TIMEOUT_REJECT 6 /* connection to host timed out */
#define MATDB_K_REMOVE_REQ 7 /* explicit remove request received */
#define MATDB_K_RESTART_REQ 8 /* explicit restart req rcvd (unremove) */
#define MATDB_K_UNSOLICITED 9 /* added by request, set init_status to */
/* this so sender pgm will skip them */
#define MATDB_K_UNKNOWN_ERROR 10 /* There was an error sending that didn't*/
/* fit 2 through 6, above. */
#define MATDB_K_MAX_STATUS_VAL 10 /* maximum status value */
#define MATDB_K_FLAG_HOLD 1 /* on hold for what ever reason */
#define MATDB_K_FLAG_MGMT 2 /* this email is a tinseltrash manager */
#define MATDB_K_FLAG_ISALIAS 4 /* this is an alias use backlink info */
#define MATDB_K_MAX_FLAG_VAL 4 /* maximum flag value */
/* */
/* Mail Address Unique ID Tracking Database layout. Instead of flailing */
/* the MATDB to figure out what the next db_id is, we'll just keep it in */
/* this file. This file only has the one record, no key, just read and upd */
/* Mass updates can be done by putting an exclusive lock on this file so */
/* that other programs can't do updates. That way the mass update only has */
/* to update the MAUIDB at the end of the update. */
/* */
struct DGS_MAUIDB_REC
{
ulong db_id; /* Next unique matdb id number */
char signature[12]; /* signature */
char fill[496]; /* fill */
} ;
/* */
/* User Information Database layout. The "username" so to speak is the */
/* email address for the user. That is kept in the matdb file, so all we */
/* need to do is copy the db_id in the matdb file into user_id for keying */
/* purposes. */
/* */
#define UIDB_K_MAXPWD 32 /* maximum acceptable password length */
#define UIDB_K_MINPWD 4 /* minimum acceptable password length */
struct DGS_UIDB_REC
{
ulong user_id; /* key 0, no dup, unique user identifier */
char pwd[UIDB_K_MAXPWD]; /* password associated with the user */
uquad add_date; /* when the record was added */
uword mail_pref; /* mail preference (currently unused) */
uword gender; /* male/female/unknown */
uword age_group; /* age range (see below) */
uword confirmed; /* did they confirm their email address? */
ulong conf_number; /* conf number generated when record is */
char fill[8]; /* fill to 64 */
} ;
#define UIDB_K_MP_UNKN 0 /* mail preference is unknown */
#define UIDB_K_MP_TEXT 1 /* mail preference is plain text */
#define UIDB_K_MP_HTML 2 /* mail preference is HTML */
#define UIDB_K_MP_WORD 3 /* mail preference is WORD attachement */
#define UIDB_K_MP_MAX 3 /* max mail preference value */
#define UIDB_K_GE_UNKN 0 /* Gender field not specified */
#define UIDB_K_GE_MALE 1 /* gender set to male */
#define UIDB_K_GE_FEMALE 2 /* gender set to female */
#define UIDB_K_GE_MAX 2 /* gender MAX setting */
#define UIDB_K_AG_UNKN 0 /* Age group unknown */
#define UIDB_K_AG_UN18 1 /* Age group under 18 */
#define UIDB_K_AG_1824 2 /* Age group 18-24 */
#define UIDB_K_AG_2530 3 /* Age group 25-30 */
#define UIDB_K_AG_3140 4 /* Age group 31-40 */
#define UIDB_K_AG_4150 5 /* Age group 41-50 */
#define UIDB_K_AG_OV50 6 /* Age group over 50 */
#define UIDB_K_AG_MAX 6 /* max age group */
/* */
/* User Chapter Tracking Database layout. Primary key is a segmented key */
/* of sorts, it is the user_id combined with the req number. The req_date */
/* will track when the chapter was requested, and we'll calc the rel_date */
/* from that (only one chapter per weekday, ya know). */
/* */
struct DGS_UCTDB_REC
{
union uctdb_key0_union
{
uquad key0;
struct
{
ulong req; /* chapter requested, second half of pri key */
ulong user_id; /* pri key is UIDB id plus the chapter requested */
} usr_req;
} ku;
uquad req_date; /* requested date, when we received the request */
uquad rel_date; /* release date, when we can release the chapter */
uquad pay_date; /* when this chapter was run through pay system */
ulong send_flag; /* send chapter, need to pay msg, or what? */
ulong dstatus; /* status of delivery, see MATDB values above */
char fill[24]; /* fill to 64. */
} ;
#define uctdb_key0 ku.key0
#define uctdb_user_id ku.usr_req.user_id
#define uctdb_req ku.usr_req.req
/* Send flag values */
#define UCTDB_K_SF_OK 1 /* Billing OK; send this chapter */
#define UCTDB_K_SF_NEEDPAY 2 /* needpay; card isn't there, or bad*/
#define UCTDB_K_SF_MAX 2 /* max value for the send flag */
#define UCTDB_K_LAST_FREE_CHAPTER 5 /* Last free chapter (11/16/01 2->5)*/
/* */
/* Source Description Database layout. Where'd we get this email address? */
/* */
#define SRCDB_K_MAXSRCDSC 48 /* maximum acceptable description length */
#define SRCDB_K_INCOMING 1 /* requested via incoming email source */
struct DGS_SRCDB_REC
{
ulong src_id; /* pri key, no dup, unique source code */
uquad add_date; /* when this src code was added */
ulong referrer; /* if not 0, then matdb.db_id of referrer */
char dsc[SRCDB_K_MAXSRCDSC]; /* source description */
} ;
/* */
/* User Payment Info layout. Keeping track of user payment information. */
/* This tracks the fields that BofA payment services are passing back to us */
/* when we pass them an order. We'll be passing them info from the ccidb, */
/* along with other info. It may be that all these fields are not filled */
/* as some are exclusively based on transaction status. */
/* */
#define UPIDB_K_SIDLEN 42
#define UPIDB_K_ACLEN 6
#define UPIDB_K_AVRLEN 10
#define UPIDB_K_INVLEN 200
#define UPIDB_K_REJLEN 100
#define UPIDB_K_CVVLEN 1
struct DGS_UPIDB_REC
{
union upidb_key0_union
{
uquad key0;
struct
{
ulong order; /* order number is generated by us */
ulong user_id; /* pri key is UIDB id plus the order number */
} usr_ord;
} ku;
ulong amount; /* amount, in cents, of the order */
char shopper_id[UPIDB_K_SIDLEN]; /* ioc_shopper_id */
ulong auth_amount; /* ioc_authorization_amount */
char auth_code[UPIDB_K_ACLEN]; /* ioc_authorization_code */
char avs_result[UPIDB_K_AVRLEN]; /* ioc_avs_result */
char order_id[UPIDB_K_AVRLEN]; /* ioc_order_id */
ulong resp_code; /* ioc_response_code */
ulong cvv_indicator; /* ioc_cvv_indicator = 1,2 or 9 */
char cvv_resp_code[UPIDB_K_CVVLEN]; /* ecom_payment_card_verification_rc */
char inv_fields[UPIDB_K_INVLEN]; /* ioc_invalid_fields */
char mis_fields[UPIDB_K_INVLEN]; /* ioc_missing_fields */
char reject_desc[UPIDB_K_REJLEN]; /* ioc_reject_description */
char fill[48]; /* fill to 640 */
} ;
#define upidb_key0 ku.key0
#define upidb_user_id ku.usr_ord.user_id
#define upidb_order ku.usr_ord.order
/* */
/* Last Paid Status Info layout. Last time we asked for payment, what was */
/* the response? */
/* */
struct DGS_LPSDB_REC
{
ulong user_id; /* user id from matdb */
uword ptype; /* payment type; comp, card, ? */
uword pstatus; /* payment status last time we checked */
uquad cdate; /* when did we check? */
char fill[16]; /* fill to 32 */
} ;
#define LPSDB_K_PT_UNK 0 /* unknown payment type */
#define LPSDB_K_PT_COMP 1 /* payment type complimentary, free for them*/
#define LPSDB_K_PT_CARD 2 /* paying with a credit card */
#define LPSDB_K_PT_MAX 2 /* maximum payment type */
#define LPSDB_K_PS_UNK 0 /* Pay status not set yet */
#define LPSDB_K_PS_OK 1 /* Last payment status was OK */
#define LPSDB_K_PS_BAD_CARD 2 /* Invalid credit card info */
#define LPSDB_K_PS_CANCEL 3 /* card deleted or cancelled */
#define LPSDB_K_PS_COMPCAN 4 /* comp status cancelled */
#define LPSDB_K_PS_MAX 4 /* maximum pay status */
/* */
/* Session tracking DB. Keep track of who is online at the moment. */
/* */
#define SESDB_K_MAXIDLEN 20 /* maximum acceptable session id length */
#define SESDB_K_TIMEOUTS 600 /* seconds until a session times out */
struct DGS_SESDB_REC
{
char sessid[SESDB_K_MAXIDLEN]; /* unique id from server at first hit */
ulong user_id; /* user id looked up in matdb via email address */
ulong logged_in; /* logged in or not */
ulong init_time; /* when did they start (time_t not vms uquad time)*/
ulong last_time; /* when was the last time they hit the site */
ulong iter; /* handy counter */
char fill[24]; /* fill to 64 */
} ;
/* */
/* Credit Card Information DB. This is the minimum information needed for */
/* a users credit card as defined by BofA. */
/* */
/* */
#define CCIDB_K_NAMELEN 50
#define CCIDB_K_NUMLEN 19
#define CCIDB_K_PCLEN 20
#define CCIDB_K_CCLEN 2
#define CCIDB_K_CVVLEN 3
struct DGS_CCIDB_REC
{
ulong user_id; /* primary key is the user id */
char card_name[CCIDB_K_NAMELEN]; /* ecom_payment_card_name */
/* name as it is on credit card */
char card_number[CCIDB_K_NUMLEN]; /* ecom_payment_card_number */
char street1[CCIDB_K_NAMELEN]; /* ecom_billto_postal_street_line1 */
char street2[CCIDB_K_NUMLEN]; /* optional street addr 2 */
char city[CCIDB_K_NUMLEN]; /* optional city info */
char state[CCIDB_K_CCLEN]; /* optional state info */
char postcode[CCIDB_K_PCLEN]; /* ecom_billto_postal_postalcode */
char countrycode[CCIDB_K_CCLEN]; /* ecom_billto_postal_countrycode */
char card_CVV2[CCIDB_K_CVVLEN]; /* ecom_payment_card_verification */
ulong card_type; /* Visa, MC, ? */
ulong expdate_mo; /* ecom_payment_card_expdate_month */
ulong expdate_yr; /* ecom_payment_card_expdate_year */
ulong bill_ok; /* set if ok to bill checked */
ulong age_confirm; /* did they check the age ok button? */
ulong deleted; /* set when user "deletes" info */
char fill[44]; /* fill to 256 */
} ;
#define CCIDB_K_CT_UNKN 0 /* Credit card type is Unknown */
#define CCIDB_K_CT_VISA 1 /* Credit card type is Visa */
#define CCIDB_K_CT_MC 2 /* Credit card type is MC */
#define CCIDB_K_CT_MAX 2 /* Maximum value for credit card type field */
#define CCIDB_K_EM_UNKN 0 /* Expiration Date, Month, */
#define CCIDB_K_EM_JAN 1 /* Expiration Date, Month, January */
#define CCIDB_K_EM_FEB 2 /* Expiration Date, Month, February */
#define CCIDB_K_EM_MAR 3 /* Expiration Date, Month, March */
#define CCIDB_K_EM_APR 4 /* Expiration Date, Month, April */
#define CCIDB_K_EM_MAY 5 /* Expiration Date, Month, May */
#define CCIDB_K_EM_JUN 6 /* Expiration Date, Month, June */
#define CCIDB_K_EM_JUL 7 /* Expiration Date, Month, July */
#define CCIDB_K_EM_AUG 8 /* Expiration Date, Month, August */
#define CCIDB_K_EM_SEP 9 /* Expiration Date, Month, September */
#define CCIDB_K_EM_OCT 10 /* Expiration Date, Month, October */
#define CCIDB_K_EM_NOV 11 /* Expiration Date, Month, November */
#define CCIDB_K_EM_DEC 12 /* Expiration Date, Month, December */
#define CCIDB_K_EM_MAX 12
#define CCIDB_K_EY_UNKN 0 /* Expiration Date, Year, Unknown */
#define CCIDB_K_EY_2001 1 /* Expiration Date, Year */
#define CCIDB_K_EY_2002 2 /* Expiration Date, Year */
#define CCIDB_K_EY_2003 3 /* Expiration Date, Year */
#define CCIDB_K_EY_2004 4 /* Expiration Date, Year */
#define CCIDB_K_EY_2005 5 /* Expiration Date, Year */
#define CCIDB_K_EY_2006 6 /* Expiration Date, Year */
#define CCIDB_K_EY_2007 7 /* Expiration Date, Year */
#define CCIDB_K_EY_2008 8 /* Expiration Date, Year */
#define CCIDB_K_EY_2009 9 /* Expiration Date, Year */
#define CCIDB_K_EY_2010 10 /* Expiration Date, Year */
#define CCIDB_K_EY_MAX 10
#pragma __member_alignment __restore
#endif /* __TTDB_DB */