PMDF popstore & MessageStore Manager's Guide
PMDF-POP-6.0


Previous | Contents


Chapter 12
Application Program Interface (API)

The popstore provides an application program interface (API). With this interface, sites may write their own code to directly create, manipulate, and delete user accounts as well as interface the popstore to billing utilities and other management interfaces.

12.1 Fundamentals

The popstore API is a re-entrant, thread-safe API. User and message contexts are shared between API client code and the API so as to facilitate the handling of multiple accounts and messages simultaneously from either single or multi-threaded programs. Note that writers of multi-threaded API client code should read Section 12.9 .

Access to the underlying profile and message files is controlled and coordinated by the API subroutines. Programs must not attempt to access those files directly. The contexts used by the API are not opaque: clients of the API are provided with structure definitions for those contexts and can view the individual data fields in them. However, these fields must be treated as read only data and must not be changed. Indeed, changes to them generally will not affect the actual on-disk data. To change the actual, underlying on-disk data, call the appropriate API subroutines to effect the desired change.

For C programmers, a C header file declaring basic constants, data types, structures, and API subroutines in provided. This header file is the popstore.h header file and is, on UNIX and NT platforms, located in the /pmdf/include/ directory. On OpenVMS platforms, it is located in the PMDF_COM: directory.

In order to use the popstore API, you must first call the POPSTORE_init subroutine so as to initialize the API. When finished with the API, be sure to call POPSTORE_end. The Sections 12.2 --12.8 provide information and code examples for performing common tasks. Section 12.12 provides complete descriptions for each API subroutine. See Section 12.10 for information on linking programs against the API.

12.2 Creating accounts

There are two approaches to creating accounts: either create an account from scratch with no default settings for fields in the account's profile, or create the account by copying fields from another account profile and then subsequently changing desired fields in the new account. Either approach is acceptable; both methods are described below. The advantage to the latter approach is that by copying the default account, the site's default account settings are used as an initial basis for the new account.

12.2.1 From scratch

The subroutines POPSTORE_user_create_set and POPSTORE_user_create are used to create an account from scratch. With a variable of type
POPSTORE_user_context *user_context 
initialized to NULL, make successive calls to POPSTORE_user_create_set to set values for the account to be created. The username field must be set, and it is always a good idea to set a password too unless you genuinely want the account to require no password to access it. After setting the desired fields, call POPSTORE_user_create to actually create the account and dispose of the context created by the first call to POPSTORE_user_create_set. That call will write to disk the profile file for the account and create an entry in the user database. If the username for the account conflicts with another existing account, the account will not be created and a POPSTORE_USEREXISTS error will be returned.

Note that the POPSTORE_user_create_set subroutine will not allow the MANAGE usage flag to be set or cleared without first calling POPSTORE_manage to explicitly authorize such actions. (cleared). Note further that regardless of any value set for the last billing field, that field will be set to the current date and time when POPSTORE_user_create is called.

An example program which creates the profile

# pmdf popstore show joe
Username:           joe 
Owner:              Joe User 
Group:              staff 
 
Usage flags: 
Last connect:       No time recorded 
Last disconnect:    No time recorded 
Total connect time: 0 00:00:00 
Total connections:  0 
Past block days:    0 
Last billing:       Tue Jun 24 10:25:18 1997 
 
Message count:              0 (0 total messages received) 
Quota used:              0.00 Kbytes 
Primary quota:          90.00 Kbytes 
Overdraft quota:        10.00 Kbytes 
is shown in

Examples

12-1
. The following items of note are identified with callouts in the sample program:
  1. check is a subroutine used to check the return status from each call to the popstore API. In the event of an error, an error message is output, the API shutdown, and the program exited.
  2. Before making any other API calls, the API is first initialized with a call to POPSTORE_initialize.
  3. Values for fields in the structure are set as desired.
  4. The account is created with a call to POPSTORE_user_add.
  5. Finally, the API is shutdown.

Examples

12-1 Creating a new account from scratch
/****************************************************************** 
 *                                                                * 
 *  create_sample.c                                               * 
 *  Sample subroutine to create a popstore account from scratch.  * 
 *                                                                * 
 ******************************************************************/ 
 
#include <stdio.h> 
#include <stdlib.h> 
#ifdef __VMS 
#  include "pmdf_com:popstore.h" 
#else 
#  include "/pmdf/include/popstore.h" 
#endif 
 
void check (int stat) (1)
{ 
  if (stat == POPSTORE_SUCCESS) return; 
  fprintf (stderr, "Error %d: %s\n", stat, POPSTORE_error_to_text (stat)); 
  (void) POPSTORE_end (); 
  exit (1); 
} 
 
main () 
{ 
  POPSTORE_user_context *ctx; 
 
  /* 
   *  Initialize the popstore 
   */ 
  check (POPSTORE_init (1, NULL, "create_sample", 13)); (2)
 
  /* 
   *  Set values for various fields 
   */ 
  ctx = NULL; 
  check (POPSTORE_user_create_set (&ctx, POPSTORE_SET_USERNAME, 3, "joe")); (3)
  check (POPSTORE_user_create_set (&ctx, POPSTORE_SET_GROUP_NAME, 5, "staff")); 
  check (POPSTORE_user_create_set (&ctx, POPSTORE_SET_OWNER, 10, "Joe User")); 
  check (POPSTORE_user_create_set (&ctx, POPSTORE_SET_PASSWORD, 6, "secret")); 
  check (POPSTORE_user_create_set (&ctx, POPSTORE_SET_QUOTA,     1024*90)); 
  check (POPSTORE_user_create_set (&ctx, POPSTORE_SET_OVERDRAFT, 1024*10)); 
 
  /* 
   *  Create the account 
   */ 
  check (POPSTORE_user_create (&ctx)); (4)
 
  /* 
   *  All done 
   */ 
  (void) POPSTORE_end (); (5)
} 

12.2.2 By copying

New accounts may also be created by copying an old account with the POPSTORE_user_copy_d subroutine and then changing the value of fields with POPSTORE_user_update. For instance, both of the popstore management interfaces create new accounts by copying the default account to the new account and then changing the requested fields in the new account.

Note that the POPSTORE_user_update subroutine will not allow the MANAGE usage flag may not be set or cleared without first calling POPSTORE_manage to explicitly authorize such actions.

The code in

Examples

12-2 creates the account joe by first copying the default account and then changing fields in the newly created joe account with POPSTORE_user_update. The account so created is identical to that created from scratch in

Examples

12-1
. The following items of note are identified with callouts in the example program:
  1. check is a subroutine used to check the return status from each call to the popstore API. In the event of an error, an error message is output, the API shutdown, and the program exited.
  2. A macro to help construct an item list.
  3. Before making any other API calls, the API is first initialized with a call to POPSTORE_initialize.
  4. Values for entries in the item list are set. These entries describe settings to make for fields in the new account.
  5. The new account is created. It is identical to the default account except for the username and password fields.
  6. Fields in the new account are changed to reflect the desired values for those fields.
  7. Finally, the API is shutdown.

Examples

12-2 Creating a new account by copying thedefaultaccount
/**************************************************************** 
 *                                                              * 
 *  copy_sample.c                                               * 
 *  Sample subroutine to create a popstore account by copying   * 
 *  the default account.                                        * 
 *                                                              * 
 ****************************************************************/ 
 
#include <stdio.h> 
#include <stdlib.h> 
 
#ifdef __VMS 
#  include "pmdf_com:popstore.h" 
#else 
#  include "/pmdf/include/popstore.h" 
#endif 
 
static POPSTORE_user_context *user_context = NULL; 
 
void check (int stat) (1)
{ 
  if (stat == POPSTORE_SUCCESS) return; 
  fprintf (stderr, "Error %d: %s\n", stat, POPSTORE_error_to_text (stat)); 
  if (user_context) (void) POPSTORE_user_end (user_context); 
  (void) POPSTORE_end (); 
  exit (1); 
} 
 
#define PUSH(list,code,addr,len) \ (2)
  list[item_index].item_code      = (code); \
  list[item_index].item_address   = (addr); \
  list[item_index++].item_length  = (len); 
 
main () 
{ 
  POPSTORE_item_list item_list[5]; 
  int item_index   = 0; 
  char group[]     = "staff"; 
  char owner[]     = "Joe User"; 
  uint32 quota     = 1024*90; 
  uint32 overdraft = 1024*10; 
 
  /* 
   *  Initialize the popstore 
   */ 
  check (POPSTORE_init (1, NULL, "copy_sample", 11)); (3)
 
  /* 
   *  Build an item list describing the fields to set new values for 
   */ 
  PUSH (item_list, POPSTORE_SET_GROUP_NAME, group,      strlen (group)); (4)
  PUSH (item_list, POPSTORE_SET_OWNER,      owner,      strlen (owner)); 
  PUSH (item_list, POPSTORE_SET_QUOTA,      &quota,     0); 
  PUSH (item_list, POPSTORE_SET_OVERDRAFT,  &overdraft, 0); 
  PUSH (item_list, POPSTORE_SET_END,        NULL,       0); 
 
  /* 
   *  Create the new account as a duplicate of the default account but 
   *  with the desired new username and password 
   */ 
  check (POPSTORE_user_copy_d (NULL, 0, "default", 7,  (5)
                               NULL, 0, "joe", 3, 
                               "secret", 6, 0)); 
 
  /* 
   *  Change the account settings 
   */ 
  check (POPSTORE_user_begin_d (NULL, 0, &user_context, "joe", 3, 
                                POPSTORE_NOACCOUNTING, "copy_sample", 11)); 
  check (POPSTORE_user_update (user_context, item_list)); (6)
  check (POPSTORE_user_end (user_context)); 
  user_context = NULL; 
 
  /* 
   *  All done 
   */ 
  POPSTORE_end (); 
} 

12.3 Modifying accounts

Fields in an existing account may be modified using the POPSTORE_user_update subroutine. This subroutine accepts as input a user context created by POPSTORE_user_begin_d and an item list describing the fields to change and the new values to use for those fields. Before making any changes, the validity of the entries in the item list is first determined. Only if the entries are all correct, are any changes then made. The changes are made atomically: the profile is locked, read, all changes made, written back to disk, and then unlocked. In the event of an unexpected error, the old profile data is restored if possible.

An example of using POPSTORE_user_update is given in

Examples

12-2 . When modifying accounts, keep the following notes in mind: