bdfp1m0w | Programming Concepts and Reference |
This section shows how you might code this example using the TPFDF C language functions.
You must ensure that there is a structure defined for each file that the C language application program will access. Figure 13 shows the structure of the member file used in this example.
Figure 13. ir00df.h-Passenger Record Structure Declaration
1 /*-------------------------------------------------------------------* 2 * Passenger Record Structure Declaration * 3 *-------------------------------------------------------------------*/ 4 #define _IR00DFI "S0" /* File ID */ 5 6 #define _IR00K80 0x80 /* logical record keys */ 7 #define _IR00K90 0x90 8 #define _IR00KA0 0xA0 9 #define _IR00KB0 0xB0 10 #define _IR00KC0 0xC0 11 #define _IR00KD0 0xD0 12 13 #define _IR00L80 sizeof(struct ir00psgr) /* passenger name */ 14 #define _IR00L90 sizeof(struct ir00addr) /* passenger address */ 15 #define _IR00LA0 sizeof(struct ir00info) /* meal, seat, pay */ 16 #define _IR00LB0 sizeof(struct ir00stat) /* membership status */ 17 #define _IR00LC0 sizeof(struct ir00rnum) /* reusable number */ 18 #define _IR00LD0 sizeof(struct ir00cnum) /* consecutive number */ 19
20 struct ir00df 21 *{ 22 | short ir00siz; /* LREC size */ 23 | dft_pky ir00key; /* primary key */ 24 | union 25 | *{ 26 | | struct ir00psgr 27 | | *{ 28 | | | char ir00nam[20]; /* surname */ 29 | | | char ir00int[6]; /* initials */ 30 | | *} psgr; 31 | | 32 | | struct ir00addr 33 | | *{ 34 | | | char ir00adr[43]; /* address */ 35 | | *} addr; 36 | | 37 | | struct ir00info 38 | | *{ 39 | | | char ir00sp0; /* spare for alignment */ 40 | | | char ir00mpr[2]; /* meal preference */ 41 | | | char ir00spr[2]; /* seat preference */ 42 | | | char ir00pay[2]; /* payment method */ 43 | | *} info; 44 | | 45 | | struct ir00stat 46 | | *{ 47 | | | char ir00sp1; /* spare for alignment */ 48 | | | int ir00mls; /* current mileage credit */ 49 | | | short ir00exy; /* expiration year */ 50 | | | short ir00exm; /* expiration month */ 51 | | *} stat; 52 | | 53 | | struct ir00rnum 54 | | *{ 55 | | | char ir00num[10]; /* reusable member number */ 56 | | *} rnum; 57 | | 58 | | struct ir00cnum 59 | | *{ 60 | | | char ir00nuc[10]; /* consecutive member number */ 61 | | *} cnum; 62 | *} lrec; 63 *};
Figure 14 shows how you can redefine TPFDF functions so that you can code them more simply in the application program.
Figure 14. psgr.h-Member File Definitions Header
1 /*--------------------------------------------------------------------* 2 * MEMBER FILE DEFINITIONS HEADER * 3 * * 4 * This file contains definitions to support use of the * 5 * Gold Club Passenger (member) file. * 6 *--------------------------------------------------------------------*/ 7 #include "ir00df.h" 8 9 #define HOLD DFOPN_HOLD 10 #define NOHOLD DFOPN_NOHOLD 11 #define RELFC DFCLS_RELFC 12 #define REUSE DFCLS_REUSE 13 14 #define open_psgr(opts) dfopn("PSGRFILE",_IR00DFI,opts) 15 #define create_psgr(file,alg) (void) dfcre_alg(file,0,alg) 16 #define read_psgr(file,alg) dfred_acc(file,DFRED_ALG,0,alg) 17 #define add_psgr(file,rcd) (void) dfadd(file,DFADD_NEWLREC,0,rcd) 18 #define replace_psgr(file,rcd) (void) dfrep(file,DFREP_NEWLREC,rcd) 19 #define modify_psgr(file) (void) dfmod(file) 20 #define close_psgr(file,opts) dfcls(file,opts) 21 #define display_psgr(file) dfdsp_str(file,DFDSP_NOKEY, \ 22 offsetof(struct ir00df,ir00key)) 23 #define open_del_nbr(opts) dfopn_acc("DELNBRS ",_IR00DFI,DFOPN_ALG, \ 24 DFOPN_DETAC|opts, \ 25 "9999999999") 26 #define read_del_nbr(file) dfred_acc(file,DFRED_ALG,DFRED_NOKEY, \ 27 "9999999999") 28 #define add_del_nbr(file,rcd) (void) dfadd(file,DFADD_NEWLREC,0,rcd) 29 #define delete_del_nbr(file) (void) dfdel(file,0) 30 #define modify_del_nbr(file) (void) dfmod(file) 31 #define close_del_nbr(file) dfcls(file,0) 32 33 #define MEM_NUM_SIZE member_size(struct ir00df,lrec.rnum.ir00num) 34 #define MAX_NAME_SIZE member_size(struct ir00df,lrec.psgr.ir00nam) 35 #define MAX_ADDR_SIZE member_size(struct ir00df,lrec.addr.ir00adr) 36 #define MEAL_SIZE member_size(struct ir00df,lrec.info.ir00mpr) 37 #define SEAT_SIZE member_size(struct ir00df,lrec.info.ir00spr) 38 #define PMNT_SIZE member_size(struct ir00df,lrec.info.ir00pay)
The member file requires the following types of processing:
Figure 15 shows the file maintenance procedure.
Figure 16 shows the departure control interface.
Figure 17 shows the monthly maintenance procedure.
Figure 15. sam0.c-File Maintenance Program
1 /*--------------------------------------------------------------------* 2 * MEMBERSHIP FILE MAINTENANCE * 3 * Display a member's record : *member-nbr * 4 * Delete a member's number : Dmember-nbr * 5 * Add a new member : Amember-name * 6 * Change members details : Cmember-nbr/Xinfo * 7 * where X is: - A address * 8 * - M meal preference * 9 * - S seat preference * 10 * - P payment method * 11 *--------------------------------------------------------------------*/ 12 #include <stdlib.h> /* standard include files */ 12A #include <time.h> 13 #include <cdf.h> /* TPFDF include files */ 13A #include <psgr.h> 14 15 #define op_msg(prefix,text) \ 16 ((void) time(<ime), \ 17 printf("%s %s %s\n",prefix,ctime(<ime),text)) 18 19 #define read_psgr_lrec(file,alg,pky) \ 20 (df_nbrkeys(&psgr_keys,1), \ 21 psgr_pky = pky, \ 22 df_setkey(&psgr_keys,1, \ 23 offsetof(struct ir00df,ir00key), \ 24 1,DF_EQ,&psgr_pky,0,DF_UPORG), \ 25 read_psgr(file,alg)) 26 27 static time_t ltime; /* used for time conversion in op_msg */ 28 29 static dft_kyl psgr_keys; /* passenger file key area */ 30 static dft_pky psgr_pky; /* passenger file primary key */ 31 32 static char in_msg[128]; /* activation message buffer */ 33 static dft_fil *psgr_file; /* passenger file pointer */ 34 static dft_fil *del_nbr_file; /* 'deleted numbers' subfile */ 35 36 static void action_delete(void); 37 static void action_display(void); 38 static void action_add(void); 39 static void action_change(void); 40 static void subfile_error(void); 41 static void new_error(void); 42 static void data_base_full(void); 43 static void update_next_available_number(struct ir00df *); 44 static void change_address(void); 45 static void change_info(char); 46
47 /*--------------------------------------------------------------------* 48 * Open the Passenger File and Determine the Required Action * 49 *--------------------------------------------------------------------*/ 50 void samp(void) 51 *{ 52 | /* local variables */ 53 | unsigned msg_len; 54 | 55 | /* Read the activation message and remove any EOM character. */ 56 | (void) gets(in_msg); 57 | msg_len = strlen(in_msg); 58 | 59 | if (in_msg[msg_len]== _EOM) 60 | in_msg[msg_len]= 0x00; 61 | 62 | /* If it is not a display request, the passenger */ 63 | /* file must be open with the HOLD option. */ 64 | psgr_file = open_psgr(in_msg[0]== '*' ? NOHOLD : HOLD); 65 | 66 | /* Determine the required action. */ 67 | switch (in_msg[0]) 68 | *{ 69 | | /* Delete Passenger Subfile. */ 70 | | case 'D': 71 | | action_delete(); 72 | | break; 73 | | 74 | | /* Display Passenger Subfile. */ 75 | | case '*': 76 | | action_display(); 77 | | break; 78 | | 79 | | /* Add New Passenger Subfile. */ 80 | | case 'A': 81 | | action_add(); 82 | | break; 83 | | 84 | | /* Change Passenger Information. */ 85 | | case 'C': 86 | | action_change(); 87 | | break; 88 | | 89 | | /* Invalid Input. */ 90 | | default: 91 | | op_msg("SAM005E","UNRECOGNIZED ACTION CODE"); 92 | | break; 93 | *} 94 | 95 | /* Close the passenger file, use the RELFC option */ 96 | /* if the action was delete (dfcls with RELFC */ 97 | /* has implied de-index and DBDEL_ALL). */ 98 | close_psgr(psgr_file,in_msg[0]== 'D' ? RELFC : 0); 99 | 100 | exit(0); 101 *} 102
103 /*--------------------------------------------------------------------* 104 * Read Passenger Record and Verify its Existence * 105 * * 106 * Returns pointer to record if subfile found, * 107 * otherwise returns NULL * 108 *--------------------------------------------------------------------*/ 109 static struct ir00df *verify_number() 110 *{ 111 | /* local variables */ 112 | static struct ir00df *psgr_lrec; /* passenger record */ 113 | 114 | /* Read a record from the passenger subfile referenced by the */ 115 | /* member number supplied in the input message. If the subfile */ 116 | /* does not exist, then the member number is incorrect. */ 117 | psgr_lrec = read_psgr(psgr_file,&in_msg[1]); 118 | 119 | if (DF_ERX(psgr_file)) /* if error from read */ 120 | subfile_error(); /* doesn't return */ 121 | 122 | if (DF_TEST(psgr_file,DFC_ALG)) /* if subfile doesn't exist */ 123 | op_msg("SAM001E","INVALID NUMBER"); /* send message to operator */ 124 | 125 | return (psgr_lrec); 126 *} 127 128 /*--------------------------------------------------------------------* 129 * Delete Passenger Subfile * 130 *--------------------------------------------------------------------*/ 131 static void action_delete(void) 132 *{ 133 | /* Verify that the supplied member number exists. */ 134 | if (verify_number()) 135 | *{ 136 | | /* local variables */ 137 | | /* partially initialized 'deleted number' LREC */ 138 | | struct ir00df del_nbr_lrec = { _IR00LC0, _IR00KC0 }; 139 | | 140 | | /* Open the 'deleted numbers' subfile. */ 141 | | del_nbr_file = open_del_nbr(HOLD); 142 | | 143 | | /* Build a new LREC for the deleted membership number */ 144 | | /* and add it to the 'deleted numbers' subfile. */ 145 | | (void) strncpy(del_nbr_lrec.lrec.rnum.ir00num, 146 | | &in_msg[1], 147 | | sizeof(del_nbr_lrec.lrec.rnum.ir00num)); 148 | | add_del_nbr(del_nbr_file,&del_nbr_lrec); 149 | | 150 | | if (DF_ER(del_nbr_file)) /* if error from add */ 151 | | subfile_error(); /* doesn't return */ 152 | *} 153 | return; 154 *} 155
156 /*--------------------------------------------------------------------* 157 * Display Passenger Subfile * 158 *--------------------------------------------------------------------*/ 159 static void action_display(void) 160 *{ 161 | /* Verify that the supplied member number exists. */ 162 | if (verify_number()) 163 | *{ 164 | | /* This is just an example of the use of dfdsp. Its use is not */ 165 | | /* appropriate here as some of the data is not in displayable */ 166 | | /* format. dfdsp automatically skips the size field. */ 167 | | display_psgr(psgr_file); 168 | | 169 | | if (DF_ER(psgr_file)) /* if error from display */ 170 | | subfile_error(); /* doesn't return */ 171 | *} 172 | return; 173 *} 174 175 /*--------------------------------------------------------------------* 176 * Add New Passenger Subfile * 177 *--------------------------------------------------------------------*/ 178 static void action_add(void) 179 *{ 180 | /* local variables */ 181 | 182 | /*------------------------------------------------------------------* 183 | * LREC to initialize the 'deleted numbers' subfile. The first * 184 | * number to be added is 2, since this subfile will only be * 185 | * initialized when member number 1 is issued. * 186 | *------------------------------------------------------------------*/ 187 | struct ir00df del_nbr_init = { _IR00LD0, _IR00KD0 }; 188 | 189 | struct ir00df new_psgr_lrec; /*build area for psgr LREC */ 190 | struct tm *tp; /*current time structure */ 191 | char next_num[MEM_NUM_SIZE+1]; /*next member number to use */ 192 | const char done_msg[]= "NEW MEMBER FILECREATED - "; 193 | char msg_text[MEM_NUM_SIZE+sizeof(done_msg)+1]; 194 | 195 | /* Verify the length of the input message. */ 196 | if (strlen(&in_msg[1]) > MAX_NAME_SIZE) 197 | op_msg("SAM002E","NAME TOO LONG"); /* send message to operator */ 198 | else 199 |
200 | /* Message length is OK, so continue. */ 201 | *{ 202 | | /* local variables */ 203 | | struct ir00df *del_nbr_rcd; 204 | | 205 | | /* Get new membership number. */ 206 | | del_nbr_file = open_del_nbr(HOLD); 207 | | del_nbr_rcd = read_del_nbr(del_nbr_file); 208 | | 209 | | if (DF_ERX(del_nbr_file)) /* if error from read */ 210 | | subfile_error(); /* doesn't return */ 211 | | 212 | | if (DF_TEST(del_nbr_file,DFC_ALG)) /* if subfile doesn't exist */ 213 | | *{ 214 | | | /* The 'deleted numbers' subfile doesn't exist, so create it. */ 215 | | | (void) strncpy(del_nbr_init.lrec.rnum.ir00num,"0000000002",10); 216 | | | add_del_nbr(del_nbr_file,&del_nbr_init); 217 | | | 218 | | | if (DF_ER(del_nbr_file)) /* if error from read */ 219 | | | subfile_error(); /* doesn't return */ 220 | | | 221 | | | (void) strcpy(next_num,"0000000001"); /* new number */ 222 | | *} 223 | | else 224 | | *{ 225 | | | /* 'deleted numbers' subfile exists, */ 226 | | | /* so find an available number */ 227 | | | 228 | | | /* If the found record is a deleted number, use the number */ 229 | | | /* and delete the record from the 'deleted numbers' file. */ 230 | | | if (del_nbr_rcd->ir00key == _IR00KC0) 231 | | | *{ 232 | | | | (void) strncpy(next_num, 233 | | | | del_nbr_rcd->lrec.rnum.ir00num, 234 | | | | MEM_NUM_SIZE); 235 | | | | delete_del_nbr(del_nbr_file); 236 | | | *} 237 | | | else 238 | | | *{ 239 | | | | /* The found record is a consecutive number, */ 240 | | | | /* so use it and increment it in the file. */ 241 | | | | (void) strncpy(next_num, 242 | | | | del_nbr_rcd->lrec.cnum.ir00nuc, 243 | | | | MEM_NUM_SIZE); 244 | | | | update_next_available_number(del_nbr_rcd); 245 | | | | modify_del_nbr(del_nbr_file); 246 | | | *} 247 | | *} 248 | |
249 | | /* Close the 'deleted numbers' subfile. */ 250 | | close_del_nbr(del_nbr_file); 251 | | 252 | | /* Create a new subfile using the new member */ 253 | | /* number as the algorithm argument. */ 254 | | close_psgr(psgr_file,REUSE); 255 | | psgr_file = open_psgr(HOLD); 256 | | create_psgr(psgr_file,next_num); 257 | | 258 | | if (DF_ER(psgr_file)) /* if error from create */ 259 | | new_error(); /* doesn't return */ 260 | | 261 | | /* Build the name LREC from the input */ 262 | | /* message and add it to the file. */ 263 | | new_psgr_lrec.ir00siz = (short) (strlen(&in_msg[1]) + 264 | | sizeof(new_psgr_lrec.ir00siz) + 265 | | sizeof(new_psgr_lrec.ir00key)); 266 | | new_psgr_lrec.ir00key = _IR00K80; 267 | | (void) strncpy(new_psgr_lrec.lrec.psgr.ir00nam, 268 | | &in_msg[1], 269 | | MAX_NAME_SIZE); 270 | | 271 | | add_psgr(psgr_file,&new_psgr_lrec); 272 | | 273 | | if (DF_ER(psgr_file)) 274 | | new_error(); 275 | | 276 | | /* Build the status LREC, which contains the current */ 277 | | /* mileage credit (0), and the expiration date */ 278 | | /* (today + one year). */ 279 | | new_psgr_lrec.ir00siz = _IR00LB0; 280 | | new_psgr_lrec.ir00key = _IR00KB0; 281 | | new_psgr_lrec.lrec.stat.ir00mls = 0; /* mileage credit */ 282 | | (void) ctime(<ime); 283 | | tp = gmtime(<ime); /* get date info */ 284 | | new_psgr_lrec.lrec.stat.ir00exy = tp->tm_year + 1; /* exp. year */ 285 | | new_psgr_lrec.lrec.stat.ir00exm = tp->tm_mon; /* exp. month */ 286 | | 287 | | add_psgr(psgr_file,&new_psgr_lrec); 288 | | 289 | | if (DF_ER(psgr_file)) 290 | | new_error(); 291 | | 292 | | (void) sprintf(msg_text,"%s%s",done_msg,next_num); 293 | | op_msg("SAM006I",msg_text); 294 | *} 295 | return; 296 *} 297
298 /*--------------------------------------------------------------------* 299 * Change Passenger Information * 300 *--------------------------------------------------------------------*/ 301 static void action_change(void) 302 *{ 303 | /* A slash must follow the action code */ 304 | /* and the 10-character member number. */ 305 | if (in_msg[11]!= '/') 306 | op_msg("SAM004E","INCORRECT FORMAT FOR CHANGE COMMAND"); 307 | else 308 | 309 | /* Input format is OK, determine what is to change. */ 310 | *{ 311 | | switch (in_msg[12]) 312 | | *{ 313 | | | /* Change Passenger Address. */ 314 | | | case 'A': 315 | | | change_address(); 316 | | | break; 317 | | | 318 | | | /* Change Meal, Seat, or Payment Preference Information. */ 319 | | | case 'M': 320 | | | case 'S': 321 | | | case 'P': 322 | | | change_info(in_msg[12]); 323 | | | break; 324 | | | 325 | | | /* Invalid Input. */ 326 | | | default: 327 | | | op_msg("SAM003E","UNRECOGNIZED CHANGE CODE"); 328 | | | break; 329 | | *} 330 | *} 331 | return; 332 *} 333
334 /*--------------------------------------------------------------------* 335 * Change Passenger Address * 336 *--------------------------------------------------------------------*/ 337 static void change_address(void) 338 *{ 339 | /* local variables */ 340 | struct ir00df *psgr_lrec, new_psgr_lrec; 341 | const unsigned addr_size = strlen(&in_msg[13]); /* size of address */ 342 | 343 | /* Verify the length of the address from the input message. */ 344 | if (addr_size > MAX_ADDR_SIZE) 345 | op_msg("SAM007E","ADDRESS TOO LONG"); /* send message to operator */ 346 | else 347 | 348 | /* Message length is OK, so continue. */ 349 | *{ 350 | | /* Read any existing passenger address record. */ 351 | | psgr_lrec = read_psgr_lrec(psgr_file,&in_msg[1],_IR00K90); 352 | | 353 | | if (DF_ER(psgr_file)) /* if error from read */ 354 | | subfile_error(); /* doesn't return */ 355 | | 356 | | /* Build the new Passenger Address LREC. */ 357 | | new_psgr_lrec = *psgr_lrec; /* copy old LREC */ 358 | | new_psgr_lrec.ir00siz = (short) (addr_size + 359 | | sizeof(new_psgr_lrec.ir00siz) + 360 | | sizeof(new_psgr_lrec.ir00key)); 361 | | (void) strncpy(new_psgr_lrec.lrec.addr.ir00adr, 362 | | &in_msg[13], 363 | | addr_size); 364 | | 365 | | /* Add or replace the Passenger Address LREC. */ 366 | | if (DF_NR(psgr_file)) 367 | | *{ 368 | | | add_psgr(psgr_file,&new_psgr_lrec); 369 | | *} 370 | | else 371 | | *{ 372 | | | replace_psgr(psgr_file,&new_psgr_lrec); 373 | | *} 374 | | 375 | | if (DF_ER(psgr_file)) /* if error from add or replace */ 376 | | subfile_error(); /* doesn't return */ 377 | *} 378 | return; 379 *} 380
381 /*--------------------------------------------------------------------* 382 * Change Miscellaneous Passenger Information (meal, seat, pay). * 383 *--------------------------------------------------------------------*/ 384 static void change_info(char info_code) 385 *{ 386 | /* local variables */ 387 | struct ir00df *psgr_lrec, new_psgr_lrec; 388 | unsigned data_size; /* expected size of data */ 389 | const unsigned actual_data_size = strlen(&in_msg[13]); 390 | char *data_ptr; /* location of data */ 391 | 392 | /* Set up for specific information. */ 393 | switch (info_code) 394 | *{ 395 | | case 'M': 396 | | data_size = MEAL_SIZE; 397 | | data_ptr = new_psgr_lrec.lrec.info.ir00mpr; 398 | | break; 399 | | 400 | | case 'S': 401 | | data_size = SEAT_SIZE; 402 | | data_ptr = new_psgr_lrec.lrec.info.ir00spr; 403 | | break; 404 | | 405 | | case 'P': 406 | | data_size = PMNT_SIZE; 407 | | data_ptr = new_psgr_lrec.lrec.info.ir00pay; 408 | | break; 409 | | 410 | | default: 411 | | break; 412 | *} 413 | 414 | /* Verify the length of the information from the input message. */ 415 | if (actual_data_size != data_size) 416 | op_msg("SAM008E","INFORMATION INCORRECT LENGTH"); 417 | else 418 |
419 | /* Message length is OK, so continue. */ 420 | *{ 421 | | /* Read any existing passenger information record. */ 422 | | psgr_lrec = read_psgr_lrec(psgr_file,&in_msg<1>,_IR00KA0); 423 | | 424 | | if (DF_ER(psgr_file)) /* if error from read */ 425 | | subfile_error(); /* doesn't return */ 426 | | 427 | | /* If a record exists, copy it to the record build */ 428 | | /* area, otherwise build a new, empty record. */ 429 | | if (!DF_NR(psgr_file)) 430 | | new_psgr_lrec = *psgr_lrec; 431 | | else 432 | | *{ 433 | | | new_psgr_lrec.ir00key = _IR00KA0; 434 | | | new_psgr_lrec.ir00siz = member_size(struct ir00df,lrec.info) 435 | | | + member_size(struct ir00df,ir00siz) 436 | | | + member_size(struct ir00df,ir00key); 437 | | | (void) memset(new_psgr_lrec.lrec.info.ir00mpr,' ',MEAL_SIZE); 438 | | | (void) memset(new_psgr_lrec.lrec.info.ir00spr,' ',SEAT_SIZE); 439 | | | (void) memset(new_psgr_lrec.lrec.info.ir00pay,' ',PMNT_SIZE); 440 | | *} 441 | | 442 | | /* Move the new data into the record build area. */ 443 | | (void) memcpy(data_ptr,&in_msg<13>,data_size); 444 | | 445 | | /* Add or replace the Passenger Information LREC. */ 446 | | if (DF_NR(psgr_file)) 447 | | *{ 448 | | | add_psgr(psgr_file,&new_psgr_lrec); 449 | | *} 450 | | else 451 | | *{ 452 | | | replace_psgr(psgr_file,&new_psgr_lrec); 453 | | *} 454 | | 455 | | if (DF_ER(psgr_file)) /* if error from add or replace */ 456 | | subfile_error(); /* doesn't return */ 457 | | 458 | | op_msg("SAM009I","DETAILS MODIFIED"); 459 | *} 460 | return; 461 *} 462
463 /*--------------------------------------------------------------------* 464 * Increment Consecutive Member Number. * 465 *--------------------------------------------------------------------*/ 466 static void update_next_available_number(struct ir00df *del_nbr_rcd) 467 *{ 468 | /* local variables */ 469 | long bin_num; /* binary version of number */ 470 | char str_num<11>; /* string version of number */ 471 | 472 | /* Verify that a number is available. */ 473 | if (strncmp(del_nbr_rcd->lrec.cnum.ir00nuc,"9999999999",10) == 0) 474 | data_base_full(); /* no number available */ 475 | 476 | /* Convert number to binary and increment it. */ 477 | (void) strncpy(str_num,del_nbr_rcd->lrec.cnum.ir00nuc,10); 478 | str_num<10>= 0x00; 479 | bin_num = strtol(str_num,NULL,10) + 1; 480 | 481 | /* Convert it back to a string and store it back. */ 482 | (void) sprintf(str_num,"%.10ld",bin_num); 483 | (void) strncpy(del_nbr_rcd->lrec.cnum.ir00nuc,str_num,10); 484 | 485 | return; 486 *} 487 488 /*--------------------------------------------------------------------* 489 * Error Handling * 490 *--------------------------------------------------------------------*/ 491 static void subfile_error(void) 492 *{ 493 | op_msg("SAM010E","ERROR IN SUBFILE"); 494 | exit(12); 495 *} 496 497 static void new_error(void) 498 *{ 499 | op_msg("SAM011E","ERROR IN NEW SUBFILE"); 500 | exit(12); 501 *} 502 503 static void data_base_full(void) 504 *{ 505 | op_msg("SAM012E","NO MEMBER NUMBERS AVAILABLE"); 506 | exit(12); 507 *} 508
Figure 16. sam1.c-Departure Control Interface
1 /*--------------------------------------------------------------------* 2 * DEPARTURE CONTROL INTERFACE * 3 * Updates the mileage flown and adjusts the expiration * 4 * date of the membership based on an extra month's * 5 * membership for each 1000 miles flown. No errors are * 6 * issued from this program. Indicators are returned * 7 * as shown below. * 8 *--------------------------------------------------------------------* 9 * Input Parameters: * 10 * char mem_num[10] - membership number * 11 * short miles - miles to be credited * 12 * * 13 * Return Values (int): * 14 * NO_SUBFILE - no subfile for specified member number * 15 * NO_MILEAGE - no mileage lrec in member's subfile * 16 * PSGR_ERROR - serious error on read * 17 * 0 - no error * 18 *--------------------------------------------------------------------*/ 19 #include <cdf.h> 20 #include <psgr.h> 22 #define NO_SUBFILE 4 23 #define NO_MILEAGE 8 24 #define PSGR_ERROR 16 25 26 #define read_psgr_lrec(file,alg,pky) \ 27 (df_nbrkeys(&psgr_keys,1), \ 28 psgr_pky = pky, \ 29 df_setkey(&psgr_keys,1, \ 30 offsetof(struct ir00df,ir00key), \ 31 1,DF_EQ,&psgr_pky,0,DF_UPORG), \ 32 read_psgr(file,alg)) 33 34 static dft_kyl psgr_keys; /* passenger file key area */ 35 static dft_pky psgr_pky; /* passenger file primary key */ 36 37 static dft_fil *psgr_file; /* passenger file pointer */ 38
39 /*--------------------------------------------------------------------* 40 * Update the Passenger File Mileage and Expiration Information. * 41 *--------------------------------------------------------------------*/ 42 int sam1(char *mem_num, short miles) 43 *{ 44 | /* local variables */ 45 | static struct ir00df *psgr_lrec; /* passenger record */ 46 | int rc = 0; /* return code */ 47 | 48 | /* Passenger subfile must be opened with the HOLD option. */ 49 | psgr_file = open_psgr(HOLD); 50 | 51 | /* Search for this member's mileage lrec. */ 52 | psgr_lrec = read_psgr_lrec(psgr_file,mem_num,_IR00KB0); 53 | 54 | if (DF_ERX(psgr_file)) /* if error on read */ 55 | rc = PSGR_ERROR; 56 | if (DF_TEST(psgr_file,DFC_ALG)) /* if subfile doesn't exist */ 57 | rc = NO_SUBFILE; 58 | else if (DF_NR(psgr_file)) /* if mileage LREC not found */ 59 | rc = NO_MILEAGE; 60 | else 61 | *{ 62 | | /* Update the membership expiration date based on the mileage. */ 63 | | psgr_lrec->lrec.stat.ir00mls +=miles; /* update miles */ 64 | | /* add 1 month per 1000 miles */ 65 | | psgr_lrec->lrec.stat.ir00exm +=psgr_lrec->lrec.stat.ir00mls / 1000; 66 | | psgr_lrec->lrec.stat.ir00mls %=1000; /* adjust mileage */ 67 | | /* add 1 year per 12 months */ 68 | | psgr_lrec->lrec.stat.ir00exy +=psgr_lrec->lrec.stat.ir00exm / 12; 69 | | psgr_lrec->lrec.stat.ir00exm %=12; /* adjust months */ 70 | | 71 | | modify_psgr(psgr_file); 72 | *} 73 | 74 | /* Close the member file and return to */ 75 | /* the caller with the return code. */ 76 | close_psgr(psgr_file,0); 77 | 78 | return (rc); 79 *}
Figure 17. sam2.c-Monthly Maintenance Program
1 /*--------------------------------------------------------------------* 2 * MONTHLY MAINTENANCE PROGRAM * 3 * Deletes members records that have expired and adds * 4 * the membership number to a subfile so it can be * 5 * reissued. * 6 *--------------------------------------------------------------------*/ 7 #include <stdlib.h> 8 #include <time.h> 9 #include <cdf.h> 10 #include <psgr.h> 11 12 #define op_msg(prefix,text) \ 13 ((void) time(<ime), \ 14 printf("%s %s %s\n",prefix,ctime(<ime),text)) 15 16 #define close_all() dfcls(NULL,DFCLS_ALL|DFCLS_ABORT) 17 18 #define read_psgr_lrec(file,pky,area) \ 19 (df_nbrkeys(&psgr_keys,1), \ 20 psgr_pky = pky, \ 21 df_setkey(&psgr_keys,1, \ 22 offsetof(struct ir00df,ir00key), \ 23 1,DF_EQ,&psgr_pky,0,DF_UPORG), \ 24 read_psgr_full(file,area)) 25 26 static time_t ltime; /* used for time conversion */ 27 28 static dft_kyl psgr_keys; /* passenger file key area */ 29 static dft_pky psgr_pky; /* passenger file primary key */ 30 31 static dft_fil *psgr_file; /* passenger file pointer */ 32 static dft_fil *del_nbr_file; /* 'deleted numbers' subfile */ 33 34 static void update_free_slot(char *); 35 static void add_error(void); 36 static void read_error(void); 37
38 /*--------------------------------------------------------------------* 39 * Perform Monthly Maintenance on the Member File. * 40 *--------------------------------------------------------------------*/ 41 void sam2(void) 42 *{ 43 | /* local variables */ 44 | struct ir00df *psgr_lrec; /* passenger record */ 45 | struct tm *tp; /* current time structure */ 46 | char mem_num.<MEM_NUM_SIZE>; /* member number */ 47 | 48 | /* Restrict operation of this program to the 1st day of the month. */ 49 | (void) ctime(<ime); 50 | tp = gmtime(<ime); /* get date info */ 51 | 52 | if (tp->tm_mday != 1) /* if not first of month... */ 53 | *{ 54 | | op_msg("SAM201E","NOT FIRST OF MONTH - UNABLE TO PROCESS"); 55 | *} 56 | else 57 | *{ 58 | | /* Open the member file and the 'deleted numbers' subfile. */ 59 | | psgr_file = open_psgr(HOLD); 60 | | del_nbr_file = open_del_nbr(HOLD); 61 | | 62 | | /* Read the member file until the end. */ 63 | | while (1) 64 | | *{ 65 | | | /* Read each status lrec for the expiration date. */ 66 | | | /* The 'area' parameter provides the member number. */ 67 | | | psgr_lrec = read_psgr_lrec(psgr_file,_IR00KB0,mem_num); 68 | | | 69 | | | /* Check for error or end of file. */ 70 | | | if (DF_ERX(psgr_file)) 71 | | | read_error(); 72 | | | 73 | | | if (DF_EF(psgr_file)) 74 | | | break; 75 | | | 76 | | | /* If the membership has expired, delete the subfile and add */ 77 | | | /* the deleted number to the 'deleted numbers' subfile. */ 78 | | | if ((psgr_lrec->lrec.stat.ir00exm < tp->tm_mon && 79 | | | psgr_lrec->lrec.stat.ir00exy <= tp->tm_year) || 80 | | | psgr_lrec->lrec.stat.ir00exy < tp->tm_year) 81 | | | *{ 82 | | | | delete_psgr(psgr_file,mem_num); 83 | | | | update_free_slot(mem_num); 84 | | | *} 85 | | *} 86 | |
87 | | op_msg("SAM202I","PROCESSING COMPLETED"); 88 | | 89 | | /* Close both files. */ 90 | | close_psgr(psgr_file,0); 91 | | close_del_nbr(del_nbr_file); 92 | *} 93 | 94 | exit(0); 95 *} 96 97 static void update_free_slot(char*mem_num) 98 *{ 99 | static struct ir00df free_slot ={ _IR00LC0, _IR00KC0 }; 100 | 101 | /* Copy the member number into the free slot LREC. */ 102 | (void) memcpy(free_slot.lrec.rnum.ir00num, 103 | mem_num, 104 | member_size(struct ir00rnum,ir00num)); 105 | 106 | /* Add the free slot LREC to the deleted numbers subfile. */ 107 | add_del_nbr(del_nbr_file,&free_slot); 108 | 109 | if (DF_ER(del_nbr_file)) 110 | add_error(); 111 | 112 | return; 113 *} 114 115 /*--------------------------------------------------------------------* 116 * Error Handling * 117 *--------------------------------------------------------------------*/ 118 static void add_error(void) 119 *{ 120 | op_msg("SAM203E","ADD ERROR ON FILE IR00DF - JOB TERMINATED"); 121 | close_all(); 122 | exit(12); 123 *} 124 125 static void read_error(void) 126 *{ 127 | op_msg("SAM204E","READ ERROR ON FILE IR00DF - JOB TERMINATED"); 128 | close_all(); 129 | exit(12); 130 *} 131