bdfp1m0wProgramming Concepts and Reference

C Language Application Program Example

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.

Note:
This type of header is not required; you can code the TPFDF functions directly in your application program if you prefer.

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)

Processing the Member File Using TPFDF C Functions

The member file requires the following types of processing:

File Maintenance Program

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(&ltime), \
 17    printf("%s %s %s\n",prefix,ctime(&ltime),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(&ltime);
283 | |  tp = gmtime(&ltime);                        /* 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

Departure Control Interface Program

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 *}

Monthly Maintenance Program

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(&ltime), \
 14    printf("%s %s %s\n",prefix,ctime(&ltime),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(&ltime);
 50 |  tp = gmtime(&ltime);                  /* 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