/*******************************************************************
 * Main routine for the PCM_OP_CUST_POL_VALID_STATUS operation.
 *******************************************************************/
void
op_cust_pol_valid_status(
        cm_nap_connection_t	*connp,
	u_int			opcode,
        u_int			flags,
        pin_flist_t		*i_flistp,
        pin_flist_t		**ret_flistpp,
        pin_errbuf_t		*ebufp)
{
	pcm_context_t		*ctxp = connp->dm_ctx;
	pin_flist_t		*r_flistp = NULL;


	/*
	 * Null out results until we have some.
	 */
	*ret_flistpp = NULL;
	PIN_ERR_CLEAR_ERR(ebufp);

	/*
	 * Insanity check.
	 */
	if (opcode != PCM_OP_CUST_POL_VALID_STATUS) {
		pin_set_err(ebufp, PIN_ERRLOC_FM,
			PIN_ERRCLASS_SYSTEM_DETERMINATE,
			PIN_ERR_BAD_OPCODE, 0, 0, opcode);
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"bad opcode in op_cust_pol_valid_status", ebufp);
		return; 
	}

	/*
	 * Debug: what did we get?
	 */
	PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
		"op_cust_pol_valid_status input flist", i_flistp);

	/*
	 * Call main function to do it
	 */
	fm_cust_pol_valid_status(ctxp, i_flistp, &r_flistp, ebufp);

	/*
	 * Results.
	 */
	if (PIN_ERR_IS_ERR(ebufp)) {
		*ret_flistpp = (pin_flist_t *)NULL;
		PIN_FLIST_DESTROY(r_flistp, NULL);
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"op_cust_pol_valid_status error", ebufp);
	} else {
		*ret_flistpp = r_flistp;
		PIN_ERR_CLEAR_ERR(ebufp);
		PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
			"op_cust_pol_valid_status return flist", r_flistp);
	}

	return;
}
/*******************************************************************
 * Main routine for the PCM_OP_CUST_POL_PRE_COMMIT  command
 *******************************************************************/
void
op_cust_pol_pre_commit(
        cm_nap_connection_t	*connp,
	u_int			opcode,
        u_int			flags,
        pin_flist_t		*in_flistp,
        pin_flist_t		**ret_flistpp,
        pin_errbuf_t		*ebufp)
{
	pcm_context_t		*ctxp = connp->dm_ctx;
	pin_flist_t		*r_flistp = NULL;

	/***********************************************************
	 * Null out results until we have some.
	 ***********************************************************/
	*ret_flistpp = NULL;
	PIN_ERR_CLEAR_ERR(ebufp);

	/***********************************************************
	 * Insanity check.
	 ***********************************************************/
	if (opcode != PCM_OP_CUST_POL_PRE_COMMIT) {
		pin_set_err(ebufp, PIN_ERRLOC_FM,
			PIN_ERRCLASS_SYSTEM_DETERMINATE,
			PIN_ERR_BAD_OPCODE, 0, 0, opcode);
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"bad opcode in op_cust_pol_pre_commit", ebufp);
		return;
	}

	/***********************************************************
	 * We will not open any transactions with Policy FM
	 * since policies should NEVER modify the database.
	 ***********************************************************/

	/***********************************************************
	 * Call main function to do it
	 ***********************************************************/
	fm_cust_pol_pre_commit(ctxp, flags, in_flistp, &r_flistp, ebufp);

	/***********************************************************
	 * Results.
	 ***********************************************************/
	if (PIN_ERR_IS_ERR(ebufp)) {
		*ret_flistpp = (pin_flist_t *)NULL;
		PIN_FLIST_DESTROY(r_flistp, NULL);
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"op_cust_pol_pre_commit error", ebufp);
	} else {
		*ret_flistpp = r_flistp;
		PIN_ERR_CLEAR_ERR(ebufp);
		PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
			"op_cust_pol_pre_commit return flist", r_flistp);
	}

	return;
}
/*******************************************************************
 * Main routine for the PCM_OP_CUST_POL_GET_CONFIG operation.
 *******************************************************************/
void
op_cust_pol_get_config(
        cm_nap_connection_t	*connp,
	u_int			opcode,
        u_int			flags,
        pin_flist_t		*in_flistp,
        pin_flist_t		**ret_flistpp,
        pin_errbuf_t		*ebufp)
{
	pcm_context_t		*ctxp = connp->dm_ctx;
	pin_flist_t		*r_flistp = NULL;

	if (PIN_ERR_IS_ERR(ebufp))
		return;
	PIN_ERR_CLEAR_ERR(ebufp);

	/***********************************************************
	 * Insanity check.
	 ***********************************************************/
	if (opcode != PCM_OP_CUST_POL_GET_CONFIG) {
		pin_set_err(ebufp, PIN_ERRLOC_FM,
			PIN_ERRCLASS_SYSTEM_DETERMINATE,
			PIN_ERR_BAD_OPCODE, 0, 0, opcode);
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"bad opcode in op_cust_pol_get_config",  ebufp);
		return;
	}

	/***********************************************************
	 * Debug: What did we get?
	 ***********************************************************/
	PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
		"op_cust_pol_get_config input flist", in_flistp);

	/***********************************************************
	 * Call main function to do it
	 ***********************************************************/
	fm_cust_pol_get_config(ctxp, in_flistp, &r_flistp, ebufp);

	/***********************************************************
	 * Results.
	 ***********************************************************/
	if (PIN_ERR_IS_ERR(ebufp)) {
		*ret_flistpp = (pin_flist_t *)NULL;
		PIN_FLIST_DESTROY(r_flistp, NULL);
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"op_cust_pol_get_config error", ebufp);
	} else {
		*ret_flistpp = r_flistp;
		PIN_ERR_CLEAR_ERR(ebufp);
		PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
			"op_cust_pol_get_config return flist", r_flistp);
	}

	return;
}
/*******************************************************************
 * Main routine for the PCM_OP_PRICE_POL_PREP_DEPENDENCY  command
 *******************************************************************/
EXPORT_OP void
op_price_pol_prep_dependency(
        cm_nap_connection_t	*connp,
	u_int32			opcode,
        u_int32			flags,
        pin_flist_t		*i_flistp,
        pin_flist_t		**o_flistpp,
        pin_errbuf_t		*ebufp)
{
	pcm_context_t		*ctxp = connp->dm_ctx;
	pin_flist_t		*r_flistp = NULL;

	if (PIN_ERR_IS_ERR(ebufp))
		return;
	PIN_ERR_CLEAR_ERR(ebufp);

	/*
	 * Null out results until we have some.
	 */
	*o_flistpp = NULL;

	/*
	 * Insanity check.
	 */
	if (opcode != PCM_OP_PRICE_POL_PREP_DEPENDENCY) {
		pin_set_err(ebufp, PIN_ERRLOC_FM,
			PIN_ERRCLASS_SYSTEM_DETERMINATE,
			PIN_ERR_BAD_OPCODE, 0, 0, opcode);
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"bad opcode in op_price_pol_prep_dependency", ebufp);
		return;
	}

	/*
	 * Do the actual prep in a lower routine
	 */
	fm_price_pol_prep_dependency(ctxp, flags, i_flistp, &r_flistp, ebufp);

	/*
	 * Results.
	 */
	if (PIN_ERR_IS_ERR(ebufp)) {
		*o_flistpp = (pin_flist_t *)NULL;
		PIN_FLIST_DESTROY(r_flistp, NULL);
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"op_price_pol_prep_dependency error", ebufp);
	} else {
		*o_flistpp = r_flistp;
		PIN_ERR_CLEAR_ERR(ebufp);
		PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
			"op_price_pol_prep_dependency return flist", r_flistp);
	}

	return;
}
Beispiel #5
0
/*******************************************************************
 * Main
 *
 *	This sets up the parameters and then calls the FM.
 *
 *******************************************************************/
int main(
	int		argc,
	char		*argv[])
{
	pcm_context_t	*ctxp;

	pin_flist_t	*flistp = NULL;
	pin_flist_t	*a_flistp = NULL;
	pin_flist_t	*r_flistp = NULL;

	poid_t		*acct_pdp = NULL;
	poid_t		*srvc_pdp = NULL;

	u_int		opcode;

	int64		database;

	void		*vp;

	char		logfile[256];
	char		*c_ptr = (char *)NULL;
	char		*program;
	int32		err;

	pin_errbuf_t	ebuf;

	PIN_ERR_CLEAR_ERR(&ebuf);

	/*
	 * Logging initialization
	 */
	program = basename(argv[0]);
	PIN_ERR_SET_PROGRAM(program);
	PIN_ERR_SET_LEVEL(PIN_ERR_LEVEL_WARNING);

	strcpy(logfile, "default.pinlog");
	pin_conf(program, "logfile", PIN_FLDT_STR, (caddr_t *)&(c_ptr), &err);
	if (c_ptr != (char *)NULL) {
		pin_strlcpy(logfile, c_ptr, sizeof(logfile));
		pin_free(c_ptr);
		c_ptr = (char *)NULL;
	}
	PIN_ERR_SET_LOGFILE(logfile);

	/*
	 * Check the input.
	 */
	if (argc != 3) {
		usage(argv[0]);
		PIN_ERR_LOG_MSG(PIN_ERR_LEVEL_ERROR, "bad # of arguments");
		exit(1);
	}

	/*
	 * Initialize PCM connection.
	 */
	PCM_CONNECT(&ctxp, &database, &ebuf);
	if (PIN_ERR_IS_ERR(&ebuf)) {
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"pcm_connect error", &ebuf);
		exit(2);
	}

	/*
	 * Create the poid prototype.
	 */
	srvc_pdp = PIN_POID_CREATE(database, argv[1], 0, &ebuf);

	/*
	 * Look up the account.
	 */
	flistp = PIN_FLIST_CREATE(&ebuf);

	vp = (void *)srvc_pdp;
	PIN_FLIST_FLD_SET(flistp, PIN_FLD_POID, vp, &ebuf);

	vp = (void *)argv[2];
	PIN_FLIST_FLD_SET(flistp, PIN_FLD_LOGIN, vp, &ebuf);

	opcode = PCM_OP_ACT_FIND;
	PCM_OP(ctxp, opcode, 0, flistp, &a_flistp, &ebuf);

	/*
	 * Did we find anything?
	 */
	acct_pdp = PIN_FLIST_FLD_GET(a_flistp, PIN_FLD_ACCOUNT_OBJ, 0, &ebuf);

	if (!PIN_POID_IS_NULL(acct_pdp)) {

		/*
		 * Advisory (or add confirm?)
		 */
		fprintf(stdout, "Deleting Account:\t");
		pin_poid_print(acct_pdp, 0, &ebuf);
		fprintf(stdout, "\n");

		/*
		 * Put the real account poid on the flist
		 * (The account_obj field will just be ignored)
		 */
		vp = (void *)acct_pdp;
		PIN_FLIST_FLD_SET(a_flistp, PIN_FLD_POID, vp, &ebuf);

		/*
		 * Delete the account.
		 */
		opcode = PCM_OP_CUST_DELETE_ACCT;
		PCM_OP(ctxp, opcode, 0, a_flistp, &r_flistp, &ebuf);

		/*
		 * Did we delete or not?
		 */
		if (PIN_ERR_IS_ERR(&ebuf)) {

			fprintf(stdout, "Account Deletion Error Occurred.\n");
			PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
				"op_cust_delete_acct error", &ebuf);

		} else {

			fprintf(stdout, "Account Deleted.\n");

		}

	} else {

		/*
		 * FIND error.
		 */
		fprintf(stdout, "Unable to locate Account.\n");
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"op_act_find error", &ebuf);

	}

	/*
	 * Close the PCM context.
	 */
	PCM_CONTEXT_CLOSE(ctxp, 0, &ebuf);

	/*
	 * Clean up.
	 */
	/* Free local memory. */
	PIN_FLIST_DESTROY(flistp, NULL);
	PIN_FLIST_DESTROY(a_flistp, NULL);
	PIN_FLIST_DESTROY(r_flistp, NULL);

	/* No errors. */
	return(0);
}
/*******************************************************************
 * Simple search.
 *
 *	Performs a read-object search for the master account
 *	object and displays the results with PIN_FLIST_PRINT.
 *
 *	The "one arg equal" search for /account is 201.
 *
 *	Note: In real life, this isn't particularly useful
 *	since we could use the poid of the account to do a
 *	read-object op directly.
 *
 *******************************************************************/
void
sample_read_obj_search(
	pcm_context_t	*ctxp,
	u_int64		database,
	pin_errbuf_t	*ebufp)
{
	pin_flist_t	*flistp = NULL;
	pin_flist_t	*a_flistp = NULL;
	pin_flist_t	*r_flistp = NULL;

	poid_t		*objp = NULL;
	u_int64		id;


	/***********************************************************
	 * Check the error buffer.
	 ***********************************************************/
	if (PIN_ERR_IS_ERR(ebufp))
		return;
	PIN_ERR_CLEAR_ERR(ebufp);

	/***********************************************************
	 * Allocate the flist for searching.
	 ***********************************************************/
	flistp = PIN_FLIST_CREATE(ebufp);

	/***********************************************************
	 * Allocate the search poid and give it to the flist.
	 ***********************************************************/
	id = (u_int64)201;

	objp = PIN_POID_CREATE(database, "/search", id, ebufp);
	PIN_FLIST_FLD_PUT(flistp, PIN_FLD_POID, (void *)objp, ebufp);

	/***********************************************************
	 * Add a search arguments array.
	 ***********************************************************/
	a_flistp = PIN_FLIST_ELEM_ADD(flistp, PIN_FLD_ARGS, 1, ebufp);

	/***********************************************************
	 * Allocate the master account poid and add as the arg.
	 ***********************************************************/
	id = (u_int64)1;

	objp = PIN_POID_CREATE(database, "/account", id, ebufp);
	PIN_FLIST_FLD_PUT(a_flistp, PIN_FLD_POID, (void *)objp, ebufp);

	/***********************************************************
	 * Add a search results marker.
	 *
	 * Making this NULL forces the read-object result we want.
	 ***********************************************************/
	a_flistp = (pin_flist_t *)NULL;
	PIN_FLIST_ELEM_PUT(flistp, a_flistp, PIN_FLD_RESULTS, 0, ebufp);

	/***********************************************************
	 * Call the DM to do the search.
	 ***********************************************************/
	PCM_OP(ctxp, PCM_OP_SEARCH, 0, flistp, &r_flistp, ebufp);

	/***********************************************************
	 * Get (and show) the results.
	 ***********************************************************/
	a_flistp = PIN_FLIST_ELEM_GET(r_flistp, PIN_FLD_RESULTS, 0, 0, ebufp);

	fprintf(stdout,"\nSimple Search Result Flist:\n");
	PIN_FLIST_PRINT(a_flistp, stdout, ebufp);

	/***********************************************************
	 * Clean up.
	 ***********************************************************/
	/* Free local memory */
	PIN_FLIST_DESTROY(r_flistp, NULL);
	PIN_FLIST_DESTROY(flistp, NULL);

	/* Error? */
	if (PIN_ERR_IS_ERR(ebufp)) {
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"sample_read_obj_search error", ebufp);
	}

	return;
}
/*******************************************************************
 * Step search.
 *
 *	Performs a read-object step search for services with
 *	md5 encrypted passwords. The first 10 such services are
 *	retrieved in two blocks of 5 services each.
 *
 *	The "one arg like" search for /service is 236.
 *
 *******************************************************************/
void
sample_step_search(
	pcm_context_t	*ctxp,
	u_int64		database,
	pin_errbuf_t	*ebufp)
{
	pin_flist_t	*flistp = NULL;
	pin_flist_t	*a_flistp = NULL;
	pin_flist_t	*r_flistp = NULL;

	poid_t		*objp = NULL;
	u_int64		id;
	char		*passwd = "md5|%";
	pin_cookie_t	cookie = NULL;
	int32		rec_id;


	/***********************************************************
	 * Check the error buffer.
	 ***********************************************************/
	if (PIN_ERR_IS_ERR(ebufp))
		return;
	PIN_ERR_CLEAR_ERR(ebufp);

	/***********************************************************
	 * Allocate the flist for searching.
	 ***********************************************************/
	flistp = PIN_FLIST_CREATE(ebufp);

	/***********************************************************
	 * Allocate the search poid and give it to the flist.
	 ***********************************************************/
	id = (u_int64)236;

	objp = PIN_POID_CREATE(database, "/search", id, ebufp);
	PIN_FLIST_FLD_PUT(flistp, PIN_FLD_POID, (void *)objp, ebufp);

	/***********************************************************
	 * Add a search arguments array.
	 ***********************************************************/
	a_flistp = PIN_FLIST_ELEM_ADD(flistp, PIN_FLD_ARGS, 1, ebufp);

	/***********************************************************
	 * Put the password value in element 1 of the args array.
	 ***********************************************************/
	PIN_FLIST_FLD_SET(a_flistp, PIN_FLD_PASSWD, (void *)passwd, ebufp);

	/***********************************************************
	 * Add a search results marker.
	 *
	 * Making this NULL forces the read-object result we want.
	 * The key here is the value 5, which says give me the
	 * first 5 results or objects.
	 ***********************************************************/
	a_flistp = (pin_flist_t *)NULL;
	PIN_FLIST_ELEM_PUT(flistp, a_flistp, PIN_FLD_RESULTS, 5, ebufp);

	/***********************************************************
	 * Call the DM to initiate the step search.
	 ***********************************************************/
	PCM_OP(ctxp, PCM_OP_STEP_SEARCH, 0, flistp, &r_flistp, ebufp);

        /***********************************************************
         * Walk the first results array.
         ***********************************************************/
	fprintf(stdout,"\n** The first 5 objects:\n");
        a_flistp = PIN_FLIST_ELEM_GET_NEXT(r_flistp, PIN_FLD_RESULTS,
                &rec_id, 1, &cookie, ebufp);
        while (a_flistp != (pin_flist_t *)NULL) {

                /***************************************************
                 * Show this result.
                 ***************************************************/
                fprintf(stdout,"\nStep Search Result(%d) Flist:\n", rec_id);
                PIN_FLIST_PRINT(a_flistp, stdout, ebufp);

                /***************************************************
                 * Get the next result.
                 ***************************************************/
                a_flistp = PIN_FLIST_ELEM_GET_NEXT(r_flistp,
                        PIN_FLD_RESULTS, &rec_id, 1, &cookie, ebufp);
        }

	/***********************************************************
	 * Recycle the results flist.
	 ***********************************************************/
	PIN_FLIST_DESTROY(r_flistp, NULL);
	r_flistp = (pin_flist_t *)NULL;

	/***********************************************************
	 * Call the DM to get the next 5 objects using step next.
	 ***********************************************************/
	PCM_OP(ctxp, PCM_OP_STEP_NEXT, 0, flistp, &r_flistp, ebufp);

        /***********************************************************
         * Walk the next results array.
         ***********************************************************/
	fprintf(stdout,"\n** The next 5 objects:\n");
	cookie = NULL;
        a_flistp = PIN_FLIST_ELEM_GET_NEXT(r_flistp, PIN_FLD_RESULTS,
                &rec_id, 1, &cookie, ebufp);
        while (a_flistp != (pin_flist_t *)NULL) {

                /***************************************************
                 * Show this result.
                 ***************************************************/
                fprintf(stdout,"\nStep Search Result(%d) Flist:\n", rec_id);
                PIN_FLIST_PRINT(a_flistp, stdout, ebufp);

                /***************************************************
                 * Get the next result.
                 ***************************************************/
                a_flistp = PIN_FLIST_ELEM_GET_NEXT(r_flistp,
                        PIN_FLD_RESULTS, &rec_id, 1, &cookie, ebufp);
        }

	/***********************************************************
	 * Recycle the results flist.
	 ***********************************************************/
	PIN_FLIST_DESTROY(r_flistp, NULL);
	r_flistp = (pin_flist_t *)NULL;

	/***********************************************************
	 * Call the DM to end step searching.
	 ***********************************************************/
	PCM_OP(ctxp, PCM_OP_STEP_END, 0, flistp, &r_flistp, ebufp);

	/***********************************************************
	 * Clean up.
	 ***********************************************************/
	/* Free local memory */
	PIN_FLIST_DESTROY(r_flistp, NULL);
	PIN_FLIST_DESTROY(flistp, NULL);

	/* Error? */
	if (PIN_ERR_IS_ERR(ebufp)) {
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"sample_step_search error", ebufp);
	}

	return;
}
/*******************************************************************
 * Multi search.
 *
 *	Performs a read-fields search to get the poid, merchant
 *	and status of all non-billable accounts in the database.
 *	We walk	the results array and display each individually.
 *
 *	The "one arg equal" search for /account is 201.
 *
 *******************************************************************/
void
sample_read_flds_search(
	pcm_context_t	*ctxp,
	u_int64		database,
	pin_errbuf_t	*ebufp)
{
	pin_cookie_t	cookie = NULL;
	pin_flist_t	*flistp = NULL;
	pin_flist_t	*a_flistp = NULL;
	pin_flist_t	*r_flistp = NULL;

	poid_t		*objp = NULL;
	u_int64		id;
	u_int		vp;
	int32		rec_id;

	/***********************************************************
	 * Check the error buffer.
	 ***********************************************************/
	if (PIN_ERR_IS_ERR(ebufp))
		return;
	PIN_ERR_CLEAR_ERR(ebufp);

	/***********************************************************
	 * Allocate the flist for searching.
	 ***********************************************************/
	flistp = PIN_FLIST_CREATE(ebufp);

	/***********************************************************
	 * Allocate the search poid and give it to the flist.
	 ***********************************************************/
	id = (u_int64)201;

	objp = PIN_POID_CREATE(database, "/search", id, ebufp);
	PIN_FLIST_FLD_PUT(flistp, PIN_FLD_POID, (void *)objp, ebufp);

	/***********************************************************
	 * Add a search arguments array.
	 ***********************************************************/
	a_flistp = PIN_FLIST_ELEM_ADD(flistp, PIN_FLD_ARGS, 1, ebufp);

	/***********************************************************
	 * Add non-billable (= undefined) as the argument.
	 ***********************************************************/
	vp = PIN_BILL_TYPE_UNDEFINED;
	PIN_FLIST_FLD_SET(a_flistp, PIN_FLD_BILL_TYPE, (void *)&vp, ebufp);

	/***********************************************************
	 * Add a search results array.
	 ***********************************************************/
	a_flistp = PIN_FLIST_ELEM_ADD(flistp, PIN_FLD_RESULTS, 0, ebufp);

	/***********************************************************
	 * Add markers for the fields we want to read.
	 ***********************************************************/
	PIN_FLIST_FLD_SET(a_flistp, PIN_FLD_POID, (void *)NULL, ebufp);
	PIN_FLIST_FLD_SET(a_flistp, PIN_FLD_MERCHANT, (void *)NULL, ebufp);
	PIN_FLIST_FLD_SET(a_flistp, PIN_FLD_STATUS, (void *)NULL, ebufp);

	/***********************************************************
	 * Call the DM to do the search.
	 ***********************************************************/
	PCM_OP(ctxp, PCM_OP_SEARCH, 0, flistp, &r_flistp, ebufp);

	/***********************************************************
	 * Walk the results array.
	 ***********************************************************/
	a_flistp = PIN_FLIST_ELEM_GET_NEXT(r_flistp, PIN_FLD_RESULTS,
		&rec_id, 1, &cookie, ebufp);
	while (a_flistp != (pin_flist_t *)NULL) {

		/***************************************************
		 * Show this result.
		 ***************************************************/
		fprintf(stdout,"\nMulti Search Result(%d) Flist:\n", rec_id);
		PIN_FLIST_PRINT(a_flistp, stdout, ebufp);

		/***************************************************
		 * Get the next result.
		 ***************************************************/
		a_flistp = PIN_FLIST_ELEM_GET_NEXT(r_flistp,
			PIN_FLD_RESULTS, &rec_id, 1, &cookie, ebufp);
	}

	/***********************************************************
	 * Clean up.
	 ***********************************************************/
	/* Free local memory */
	PIN_FLIST_DESTROY(r_flistp, NULL);
	PIN_FLIST_DESTROY(flistp, NULL);

	/* Error? */
	if (PIN_ERR_IS_ERR(ebufp)) {
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"sample_read_flds_search error", ebufp);
	}

	return;
}
//****************************************************
// updateStatus
// Pre:
// Post:
//
bool bs_UpdateStatus::updateStatus(
  pin_Session * pinp,
  poid_t * account_pdp,
  poid_t * service_pdp,
  int status,
  int status_flags,
  string source,
  string description,
  pin_flist_t   **return_flistpp,
  pin_errbuf_t  *ebufp  )
{
  pin_flist_t * x_flistp = NULL;
  pin_flist_t * d_flistp = NULL;
  pin_flist_t * f_flistp = NULL;
  pin_flist_t * f_outflistp = NULL;
  pin_errbuf_t  localebuf;
  int     flag=status_flags;
  poid_t * pdp = NULL;
  void * vp = NULL;
  bool rc;

  const string this_program("updateStatus");
  if ( source.empty() )
  {
    source.assign(this_program);
  }
  if ( description.empty() )
  {
    description.assign(this_program);
  }

  PIN_ERR_CLEAR_ERR(ebufp);

  //--enter function--------------
  PIN_ERR_LOG_MSG(PIN_ERR_LEVEL_DEBUG, (char*)this_program.c_str() );


  /*--- Create set_status ---*/
  if ( status == PIN_STATUS_ACTIVE && status_flags <= 0 )
  {
    PIN_ERR_LOG_MSG(PIN_ERR_LEVEL_ERROR,
      (char*)"This is an activation - get existing flags" );

    PIN_ERR_CLEAR_ERR(&localebuf);
    pdp = ( pin_poid_is_null(service_pdp)) ? account_pdp : service_pdp;

    f_flistp = PIN_FLIST_CREATE(ebufp);
    PIN_FLIST_FLD_SET(f_flistp, PIN_FLD_POID, (void*)pdp, &localebuf);
    PIN_FLIST_FLD_SET(f_flistp, PIN_FLD_STATUS_FLAGS, (void*)NULL, &localebuf);
    if ( pinp->call_opcode( PCM_OP_READ_FLDS, 0, f_flistp, &f_outflistp, &localebuf))
    {
      if ((vp=PIN_FLIST_FLD_GET(
        f_outflistp, PIN_FLD_STATUS_FLAGS, 1, &localebuf )) != NULL )
        status_flags = *(int*)vp;
    }
    if (f_flistp) PIN_FLIST_DESTROY(f_flistp,NULL); f_flistp = NULL;
    if (f_outflistp) PIN_FLIST_DESTROY_EX(&f_outflistp,NULL); f_outflistp = NULL;
  }
  if ( status_flags < 0) {
    status_flags = 0;
  }

  /*--- Create set_status ---*/
  x_flistp = PIN_FLIST_CREATE(ebufp);
  PIN_FLIST_FLD_SET(x_flistp, PIN_FLD_POID, account_pdp, ebufp);
  if ( ! pin_poid_is_null(service_pdp) )
    PIN_FLIST_FLD_SET(x_flistp, PIN_FLD_SERVICE_OBJ, service_pdp, ebufp);
  PIN_FLIST_FLD_SET(x_flistp, PIN_FLD_PROGRAM_NAME, (void*)source.c_str(), ebufp);
  PIN_FLIST_FLD_SET(x_flistp, PIN_FLD_DESCR, (void*)description.c_str(), ebufp);
  d_flistp = PIN_FLIST_ELEM_ADD( x_flistp, PIN_FLD_STATUSES, PIN_ELEMID_ASSIGN, ebufp );
    PIN_FLIST_FLD_SET(d_flistp, PIN_FLD_STATUS, (void*)&status, ebufp);
    PIN_FLIST_FLD_SET(d_flistp, PIN_FLD_STATUS_FLAGS, (void*)&status_flags, ebufp);

  if ( (! pin_poid_is_null(service_pdp)) && (status == PIN_STATUS_CLOSED) ) {
     rc = pinp->call_opcode(
         PCM_OP_CUST_SET_STATUS, 0, x_flistp, return_flistpp, ebufp);
  }
  else {
     rc = pinp->call_opcode(
         UOL_OP_SET_STATUS, 0, x_flistp, return_flistpp, ebufp);
  }

  PIN_ERR_LOG_FLIST(
    PIN_ERR_LEVEL_DEBUG,(char*)"leaving bs_UpdateStatus::updateStatus" , *return_flistpp );

  if (x_flistp) PIN_FLIST_DESTROY(x_flistp,NULL);
  return rc;
}
/*******************************************************************
 * Main routine for the PCM_OP_CUST_POL_GET_POPLIST operation.
 *******************************************************************/
void
op_cust_pol_get_poplist(
        cm_nap_connection_t	*connp,		/* Connection pointer	*/
	u_int			opcode,		/* Opcode in question	*/
        u_int			flags,		/* Standard flags if any*/
        pin_flist_t		*in_flistp,	/* Input flist		*/
        pin_flist_t		**ret_flistpp,	/* Results flist	*/
        pin_errbuf_t		*ebufp)		/* Error buffer		*/
{
	pcm_context_t		*ctxp = connp->dm_ctx;	/* Connection	*/
	pin_flist_t		*r_flistp = NULL;	/* Local flist	*/
	void			*vp = NULL;

	/***********************************************************
	 * Null out results until we have some.
	 ***********************************************************/
	*ret_flistpp = NULL;
	PIN_ERR_CLEAR_ERR(ebufp);

	/***********************************************************
	 * Insanity check.
	 ***********************************************************/
	if (opcode != PCM_OP_CUST_POL_GET_POPLIST) {
		pin_set_err(ebufp, PIN_ERRLOC_FM,
			PIN_ERRCLASS_SYSTEM_DETERMINATE,
			PIN_ERR_BAD_OPCODE, 0, 0, opcode);
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"bad opcode in op_cust_pol_get_poplist", ebufp);
		return;
	}

	/***********************************************************
	 * Debug: what did we get?
	 ***********************************************************/
	PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
		"op_cust_pol_get_poplist input flist", in_flistp);

	/***********************************************************
	 * Create the pop flist & copy the input poid to it.
	 ***********************************************************/
	r_flistp = PIN_FLIST_CREATE(ebufp);

	vp = PIN_FLIST_FLD_GET(in_flistp, PIN_FLD_POID, 0, ebufp);
	PIN_FLIST_FLD_SET(r_flistp, PIN_FLD_POID, vp, ebufp);

	/***********************************************************
	 * Call a sub-function to actually find the pops.
	 ***********************************************************/
	fm_cust_pol_get_poplist(ctxp, in_flistp, r_flistp, ebufp);

	/***********************************************************
	 * Result.
	 ***********************************************************/
	if (PIN_ERR_IS_ERR(ebufp)) {
		*ret_flistpp = (pin_flist_t *)NULL;
		PIN_FLIST_DESTROY(r_flistp, NULL);
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"op_cust_pol_get_poplist error", ebufp);
	} else {
		*ret_flistpp = r_flistp;
		PIN_ERR_CLEAR_ERR(ebufp);
		PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
			"op_cust_pol_get_poplist return flist", r_flistp);
	}

	return;
}	/* op_cust_pol_get_poplist */
/********************************************************************
 * fm_cust_pol_get_poplist()
 *
 *	Obtains a list of pops and adds to the given outflistp.
 *	If no PIN_FLD_ANI is found on the input flist, then the
 *	entire pop list is returned.  Otherwise, only the POP
 *	matching the ANI is returned. 
 *
 ********************************************************************/
static void
fm_cust_pol_get_poplist(
	pcm_context_t	*ctxp,			/* Connection context	*/
	pin_flist_t	*in_flistp,		/* Client's input flist */
	pin_flist_t	*out_flistp,		/* Search results flist */
	pin_errbuf_t	*ebufp)			/* Error buff		*/
{
	u_int64 	database;		/* Requested database 	*/
	poid_t		*poidp = NULL;		/* Input poid		*/
	poid_t		*objp = NULL;		/* New search poid	*/
	poid_t		*type_poidp;		/* Used for full poplist*/
	pin_cookie_t    cookie = NULL;  	/* For getting results	*/
	pin_cookie_t    cookie2 = NULL;  	/* For getting anis	*/
	pin_flist_t	*flistp = NULL;		/* Search flist created	*/
        pin_flist_t	*ani_flistp = NULL;	/* ANI array flist	*/
	pin_flist_t	*a_flistp = NULL;	/* New element pointer	*/
	pin_flist_t	*e_flistp = NULL;	/* Element ptr 4 pop arr*/
	pin_flist_t	*r_flistp = NULL;	/* Search return flist	*/
	pin_flist_t	*sort_flistp = NULL;	/* Sort flist		*/
	u_int64         id;			/* Search id 		*/
	u_int		type = POP_PRIMARY;	/* Only return prime pop*/ 
	int32           rec_id;         	/* PIN_FLD_RESULTS elem	*/
	int32           rec_id2;         	/* ANI results elem	*/
	void		*vp;			/* PIN_FLD_ANI value	*/
	void		*vp2;			/* Returned fields ptr	*/

	/***********************************************************
         * Check the error buffer.
         ***********************************************************/
        if (PIN_ERR_IS_ERR(ebufp))
                return;
        PIN_ERR_CLEAR_ERR(ebufp);

        /***********************************************************
         * Allocate the flist for searching.
         ***********************************************************/
        flistp = PIN_FLIST_CREATE(ebufp);

        /***********************************************************
         * Get the database number.
         ***********************************************************/
	poidp = (poid_t *)PIN_FLIST_FLD_GET(in_flistp, PIN_FLD_POID, 0, ebufp);
	database = PIN_POID_GET_DB(poidp);

        /***********************************************************
         * Allocate the search poid and give it to the flist.  Use
	 * the 2 arg search id if args are found, otherwise use
	 * the 1 arg search which returns all the pops ordered.
         ***********************************************************/
       	vp = PIN_FLIST_FLD_GET(in_flistp, PIN_FLD_ANI, 1, ebufp);
	if (vp == NULL) {
		id = (u_int64)300;
	} else {
		id = (u_int64)301;
	}
        objp = PIN_POID_CREATE(database, "/search/pin", id, ebufp);
        PIN_FLIST_FLD_PUT(flistp, PIN_FLD_POID, (void *)objp, ebufp);

        /***********************************************************
         * Add a search arguments array.
         ***********************************************************/
        a_flistp = PIN_FLIST_ELEM_ADD(flistp, PIN_FLD_ARGS, 1, ebufp);

        /***********************************************************
         * Determine whether the entire poplist should be returned
	 * or an ani to pop match should be done.  The rule is if
	 * there's a PIN_FLD_ANI field, return the entire list,
 	 * otherwise, do a ani to pop match but only return the
	 * primary one.
         ***********************************************************/
        type_poidp = PIN_POID_CREATE(database, "/pop", (int64)-1, ebufp);
	if (vp == NULL) {
		PIN_FLIST_FLD_PUT(a_flistp, PIN_FLD_POID,
			(void *)type_poidp, ebufp);
	} else {
        	/*
         	** 2 arg search, return pop that matches ani and is a
		** primary pop.
         	*/
        	ani_flistp = PIN_FLIST_CREATE(ebufp);
		/*
		** PIN_FLD_ANI for our first arg.
		*/
		PIN_FLIST_FLD_SET(ani_flistp, PIN_FLD_ANI, vp, ebufp );
		PIN_FLIST_ELEM_SET(a_flistp, ani_flistp, PIN_FLD_ANIS,
                	0, ebufp );
		/*
		** PIN_FLD_TYPE for our second arg.
		*/
		a_flistp = PIN_FLIST_ELEM_ADD(flistp, PIN_FLD_ARGS, 2, ebufp);
        	ani_flistp = PIN_FLIST_CREATE(ebufp);
		PIN_FLIST_FLD_SET(ani_flistp, PIN_FLD_TYPE, 
			(void *)&type, ebufp);
		PIN_FLIST_ELEM_SET(a_flistp, ani_flistp, PIN_FLD_ANIS, 1,
			ebufp);
	}

        /***********************************************************
         * Put on the PIN_FLD_RESULTS array for our results.
         ***********************************************************/
        a_flistp = PIN_FLIST_ELEM_ADD(flistp, PIN_FLD_RESULTS, 0, ebufp);
	/*
	** Return the pop, city, state and zip fields if the entire poplist 
	** was requested, otherwise return the same fields including
	** the flags if pop matching was requested.
	*/
	PIN_FLIST_FLD_SET(a_flistp, PIN_FLD_PHONE, (void *)NULL, ebufp); 
	PIN_FLIST_FLD_SET(a_flistp, PIN_FLD_CITY, (void *)NULL, ebufp); 
	PIN_FLIST_FLD_SET(a_flistp, PIN_FLD_STATE, (void *)NULL, ebufp); 
	PIN_FLIST_FLD_SET(a_flistp, PIN_FLD_ZIP, (void *)NULL, ebufp); 
	if (vp != NULL) {
		/*
		** Add the ANIS array if PIN_FLD_ANI arg was passed in.
		*/
        	ani_flistp = PIN_FLIST_CREATE(ebufp);
		PIN_FLIST_FLD_SET(ani_flistp, PIN_FLD_ANI, 
			(void *)NULL, ebufp);
		PIN_FLIST_FLD_SET(ani_flistp, PIN_FLD_TYPE, 
			(void *)NULL, ebufp);
		PIN_FLIST_FLD_SET(ani_flistp, PIN_FLD_FLAGS, 
			(void *)NULL, ebufp);
		PIN_FLIST_ELEM_SET(a_flistp, ani_flistp, PIN_FLD_ANIS, 0,
			ebufp);
	}
	
        /***********************************************************
         * Call the DM to do the search.
         ***********************************************************/
        PCM_OP(ctxp, PCM_OP_SEARCH, 0, flistp, &r_flistp, ebufp);

	/***********************************************************
         * Walk the search results array adding each to the
	 * PIN_FLD_POP's array flist to pass back to the caller. 
         ***********************************************************/
        a_flistp = PIN_FLIST_ELEM_GET_NEXT(r_flistp, PIN_FLD_RESULTS,
                &rec_id, 1, &cookie, ebufp);
	while (a_flistp != (pin_flist_t *)NULL) {

        	e_flistp = PIN_FLIST_ELEM_ADD(out_flistp, PIN_FLD_POP, 
			rec_id, ebufp);

		/*
		** Take the PIN_FLD_PHONE and put it on the PIN_FLD_POP array.
		*/
		vp2 = PIN_FLIST_FLD_TAKE(a_flistp, PIN_FLD_PHONE, 0, ebufp);
		PIN_FLIST_FLD_PUT(e_flistp, PIN_FLD_PHONE, vp2, ebufp);
		/*
		** Take the PIN_FLD_CITY and put it on the PIN_FLD_POP array.
		*/
		vp2 = PIN_FLIST_FLD_TAKE(a_flistp, PIN_FLD_CITY, 0, ebufp);
		PIN_FLIST_FLD_PUT(e_flistp, PIN_FLD_CITY, vp2, ebufp);
		/*
		** Take the PIN_FLD_STATE and put it on the PIN_FLD_POP array.
		*/
		vp2 = PIN_FLIST_FLD_TAKE(a_flistp, PIN_FLD_STATE, 0, ebufp);
		PIN_FLIST_FLD_PUT(e_flistp, PIN_FLD_STATE, vp2, ebufp);
		/*
		** Take the PIN_FLD_ZIP and put it on the PIN_FLD_POP array.
		*/
		vp2 = PIN_FLIST_FLD_TAKE(a_flistp, PIN_FLD_ZIP, 0, ebufp);
		PIN_FLIST_FLD_PUT(e_flistp, PIN_FLD_ZIP, vp2, ebufp);
		/*
		** Walk the ani array (if we're pop matching) to get the 
		** PIN_FLD_FLAGS field, should only be one.
		*/
		if (vp != NULL) {
			ani_flistp = (pin_flist_t *)NULL;
			ani_flistp = PIN_FLIST_ELEM_GET_NEXT(a_flistp, 
				PIN_FLD_ANIS, &rec_id2, 0, &cookie2, ebufp);
			while (ani_flistp != (pin_flist_t *)NULL) {
				vp2 = PIN_FLIST_FLD_TAKE(ani_flistp, 
					PIN_FLD_FLAGS, 0, ebufp);
				PIN_FLIST_FLD_PUT(e_flistp, PIN_FLD_FLAGS, 
					vp2, ebufp);
				ani_flistp = PIN_FLIST_ELEM_GET_NEXT(a_flistp,
					PIN_FLD_ANIS, &rec_id2, 1, &cookie2, 
					ebufp);
			}
		}

		/***************************************************
                 * Get the next result.
                 ***************************************************/
                a_flistp = PIN_FLIST_ELEM_GET_NEXT(r_flistp,
                        PIN_FLD_RESULTS, &rec_id, 1, &cookie, ebufp);
	}

        /***********************************************************
         * Clean up.
         ***********************************************************/
	PIN_FLIST_DESTROY(flistp, NULL);
	PIN_FLIST_DESTROY(r_flistp, NULL);

        if (PIN_ERR_IS_ERR(ebufp)) {
                PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"fm_cust_pol_read_poplist error", ebufp);
        }

        return;
}	/* fm_cust_pol_read_poplist */
//****************************************************
// update_contactinfo
// Pre:
// Post:
//
bool bs_UpdateContactInfo::updateContactInfo(
  pin_Session * pinp,
  poid_t * account_pdp,
  bs_SignupRec * bsrp,
  string source,
  pin_flist_t   **return_flistpp,
  pin_errbuf_t  *ebufp  )
{
    pin_flist_t * c_outflistp = NULL;
    pin_flist_t * c_flistp = NULL;
    pin_flist_t * t1_flistp = NULL;
    pin_flist_t * t2_flistp = NULL;
    pin_flist_t * outflistp = NULL;
  void *  vp = NULL;
  int32 flags = 0;

  /* source name */
  /* source / desc name */
  const string this_program("bs_UpdateContactInfo::updateContactInfo");
  if ( source.empty() )
  {
    source.assign(this_program);
  }
  PIN_ERR_LOG_MSG(PIN_ERR_LEVEL_DEBUG, (char*)this_program.c_str() );


  //--- get appropriate fields ----------
  char * firstname  = bsrp->s_firstName;
  char * lastname   = bsrp->s_lastName;
  char * address    = bsrp->s_caddress;
  char * city   = bsrp->s_ccity;
  char * state    = bsrp->s_cstate;
  char * zip    = bsrp->s_czip;
  char * email_addr = bsrp->s_cemail_addr;
  int32 contact_type  = PIN_NAMEINFO_BILLING;
  const char * country    = "USA";
  const char * program_name = source.c_str();


  PIN_ERR_CLEAR_ERR(ebufp);

  /* create flist */
  c_flistp = PIN_FLIST_CREATE( ebufp );

  /* top level fields */
  PIN_FLIST_FLD_SET(c_flistp, PIN_FLD_POID,(void *)account_pdp, ebufp);
  PIN_FLIST_FLD_SET(c_flistp, PIN_FLD_PROGRAM_NAME,(void *)program_name, ebufp);

  /* nameinfo */
  t1_flistp = PIN_FLIST_ELEM_ADD(c_flistp, PIN_FLD_NAMEINFO, contact_type, ebufp);
  PIN_FLIST_FLD_SET(t1_flistp, PIN_FLD_FIRST_NAME,(void *)firstname, ebufp);
  PIN_FLIST_FLD_SET(t1_flistp, PIN_FLD_LAST_NAME,(void *)lastname, ebufp);
  PIN_FLIST_FLD_SET(t1_flistp, PIN_FLD_ADDRESS,(void *)address, ebufp);
  PIN_FLIST_FLD_SET(t1_flistp, PIN_FLD_CITY,(void *)city, ebufp);
  PIN_FLIST_FLD_SET(t1_flistp, PIN_FLD_STATE,(void *)state, ebufp);
  PIN_FLIST_FLD_SET(t1_flistp, PIN_FLD_ZIP,(void *)zip, ebufp);
  PIN_FLIST_FLD_SET(t1_flistp, PIN_FLD_COUNTRY,(void *)country, ebufp);
  PIN_FLIST_FLD_SET(t1_flistp, PIN_FLD_EMAIL_ADDR,(void *)email_addr, ebufp);

  PIN_ERR_CLEAR_ERR(ebufp);

  bool rc = pinp->call_opcode(
    PCM_OP_CUST_POL_UOL_SET_NAMEINFO, flags, c_flistp, &c_outflistp, ebufp);

  if (c_flistp) PIN_FLIST_DESTROY(c_flistp,ebufp);
  if (c_outflistp) PIN_FLIST_DESTROY_EX(&c_outflistp,ebufp);
  return rc;
}
/*******************************************************************
 * Main routine for the PCM_OP_SUBSCRIPTION_POL_SNOWBALL_DISCOUNT operation.
 *******************************************************************/
void
op_subscription_pol_snowball_discount(
	cm_nap_connection_t	*connp,
	u_int			opcode,
	u_int			flags,
	pin_flist_t		*in_flistp,
	pin_flist_t		**ret_flistpp,
	pin_errbuf_t		*ebufp)
{
	pcm_context_t		*ctxp = connp->dm_ctx;

	pin_cookie_t		cookie = NULL;

	pin_flist_t		*r_flistp = NULL;
	pin_flist_t		*flistp = NULL;

	poid_t			*a_pdp = NULL;

	char			*action;
	char			*cp;

	u_int			rec_id;
	u_int			done = 0;

	if (PIN_ERR_IS_ERR(ebufp))
		return;
	PIN_ERR_CLEAR_ERR(ebufp);

	/***********************************************************
	 * Insanity check.
	 ***********************************************************/
	if (opcode != PCM_OP_SUBSCRIPTION_POL_SNOWBALL_DISCOUNT) {
		pin_set_err(ebufp, PIN_ERRLOC_FM,
			PIN_ERRCLASS_SYSTEM_DETERMINATE,
			PIN_ERR_BAD_OPCODE, 0, 0, opcode);
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"op_subscription_pol_snowball_discount opcode error",
			ebufp);
		return;
	}

	/***********************************************************
	 * Debug: What we got.
	 ***********************************************************/
	PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
		"op_subscription_pol_snowball_discount input flist", 
		in_flistp);

	/***********************************************************
	 * Get the policy return flist.
	 ***********************************************************/
	fm_subs_pol_snowball_discount(ctxp, flags, in_flistp, &r_flistp, ebufp);

	/***********************************************************
	 * Errors?
	 ***********************************************************/
	if (PIN_ERR_IS_ERR(ebufp)) {

		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"op_subscription_pol_snowball_discount error", 
			ebufp);
		PIN_FLIST_DESTROY(r_flistp, NULL);
		*ret_flistpp = NULL;

	} else {

		/***************************************************
		 * Point the real return flist to the right thing.
		 ***************************************************/
		PIN_ERR_CLEAR_ERR(ebufp);
		*ret_flistpp = r_flistp;
		PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
			"op_subscription_pol_snowball_discount return flist",
			*ret_flistpp);
	}

	return;
}
//****************************************************
// adjust_CashBalance
// Pre:
// Post:
//
bool bs_AdjustCashBalance::adjust_CashBalance(
  pin_Session * pinp,
  poid_t * account_pdp,
  pin_decimal_t * amountp,
  string source,
  string description,
  string service_str,
  string reason_id,
  pin_flist_t   **return_flistpp,
  pin_errbuf_t  *ebufp )
{
  pin_flist_t   *input_flistp = NULL;
  poid_t *bal_pdp = NULL;
  int       dollar_currency = 840;
  int       iversion  = DEFAULT_CASH_ADJUSTMENT_VER;
  ostringstream os;
  bool rc = false;

  char 		*service_code = (char *)NULL;
  service_code = (char *)calloc(256, sizeof(char));
  strcpy(service_code,(const char *)GENERIC_SERVICE_ADJUSTMENT_CODE);
  strcat(service_code,reason_id.c_str());

  int	id = atoi(service_code);

  PIN_ERR_CLEAR_ERR(ebufp);

  //--- setup --------------------------
  /* source / desc name */
  const string this_program("adjust_CashBalance");
  if ( description.empty() )
  {
    ostringstream os;
    os << DEFAULT_CASH_ADJUSTMENT_DESCR << "." << getuser(ENV_USER) << "." << this_program;
    description.assign(os.str());
  }
  if ( source.empty() )
  {
    source.assign(this_program);
  }
  PIN_ERR_LOG_MSG(PIN_ERR_LEVEL_DEBUG, (char*)description.c_str() );

  /* retrieving the bal_grp poid associated with a service
   * if the service_str is NULL, then account level bal_grp will be used
   */
  pin_flist_t *r_flistp = NULL;
  r_flistp = bs_AccountInfo::getService_and_BalGrpPoids(pinp, account_pdp, service_str);
  bal_pdp = PIN_FLIST_FLD_TAKE(r_flistp,PIN_FLD_BAL_GRP_OBJ, 1, ebufp);
  if(r_flistp) PIN_FLIST_DESTROY(r_flistp,ebufp);

  if(PIN_POID_IS_NULL(bal_pdp)) {
     PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,(char*)"/balance_group poid is NULL", ebufp );
     return false;
  }

  //--- adjust------------------------------
  input_flistp = PIN_FLIST_CREATE(ebufp);
  PIN_FLIST_FLD_SET(input_flistp, PIN_FLD_PROGRAM_NAME, (void*)source.c_str(), ebufp);
  PIN_FLIST_FLD_SET(input_flistp, PIN_FLD_POID,(void *) account_pdp, ebufp);
  PIN_FLIST_FLD_SET(input_flistp, PIN_FLD_DESCR,  (void *)description.c_str(), ebufp);
  PIN_FLIST_FLD_SET(input_flistp, PIN_FLD_CURRENCY, (void *) &dollar_currency,ebufp);
  PIN_FLIST_FLD_SET(input_flistp, PIN_FLD_AMOUNT, amountp, ebufp);
  PIN_FLIST_FLD_SET(input_flistp, PIN_FLD_STR_VERSION, (void *) &iversion, ebufp);
  PIN_FLIST_FLD_SET(input_flistp, PIN_FLD_STRING_ID, (void *) &id, ebufp);

  /*** Inserting BAL_GRP poid ***/
  PIN_FLIST_FLD_PUT(input_flistp, PIN_FLD_BAL_GRP_OBJ, (void *) bal_pdp, ebufp);

  /*
  * Call opcode
  */
  rc = pinp->call_opcode( PCM_OP_AR_ACCOUNT_ADJUSTMENT, 0, input_flistp,
        return_flistpp, ebufp);

  PIN_FLIST_DESTROY(input_flistp, ebufp);
  return rc;
}