x400_msrcv.c

00001 /*  Copyright (c) 2003-2007, Isode Limited, London, England.
00002  *  All rights reserved.
00003  *                                                                       
00004  *  Acquisition and use of this software and related materials for any      
00005  *  purpose requires a written licence agreement from Isode Limited,
00006  *  or a written licence from an organisation licenced by Isode Limited
00007  *  to grant such a licence.
00008  *
00009  */
00010 
00011 /* $RCSfile: x400_msrcv.c,v $ $Revision: 1.37 $ $Date: 2007/09/25 14:16:12 $ $State: Exp $
00012  *
00013  * $Log: x400_msrcv.c,v $
00014  * Revision 1.37  2007/09/25 14:16:12  paga
00015  * T070925E - #define out dl expansion history and security label code.
00016  *
00017  * Revision 1.36  2007/08/31 12:52:55  ir
00018  * T070831G - Fetch and display attachements as BodyParts.
00019  *            Fetch and display forwarded messge after extracting from BodyPart.
00020  *            Add functions get_body_parts(), get_bp(), get_msgbp(), do_xmsg_headers(),
00021  *            do_xmsg_content_as_bp(), do_xrep_headers(), do_xmsg_headers().
00022  *            Add call to test X400msMsgCountRecip().
00023  *            Get the envelope recipients (in addition to the headers).
00024  *            Add call to test X400msDLExpHistGet().
00025  *
00026  * Revision 1.35  2007/08/29 15:35:48  paga
00027  * T070829J - Add in security label examples.
00028  *
00029  * Revision 1.34  2007/08/28 15:29:52  paga
00030  * T070828E - No longer delete the DL Expansion list structure explicity.
00031  *            (It's now deleted when the message is deleted).
00032  *
00033  * Revision 1.33  2007/08/21 16:38:31  ldv
00034  * T070821K - Correct typo in Usage message, for the -7 flag
00035  *
00036  * Revision 1.32  2007/08/02 15:05:46  paga
00037  * T070801H - Add a "\n" to a message.
00038  *
00039  * Revision 1.31  2007/07/31 16:25:33  paga
00040  * T070730F - Add example DL history expansion code
00041  *
00042  * Revision 1.30  2007/07/24 12:45:36  dbw
00043  * T070724D - Fix warnings
00044  *
00045  * Revision 1.29  2007/07/11 11:02:39  kurt
00046  * T070615E - %* requires int
00047  *
00048  * Revision 1.28  2007/05/15 13:11:05  dbw
00049  * T070515D - Update/Add copyright
00050  *
00051  * Revision 1.27  2007/04/27 14:50:28  dbw
00052  * T070427F - Three possible connection types
00053  *
00054  * Revision 1.26  2006/09/11 09:43:26  ir
00055  * T060825A - Add switch which accepts defaults (as overridden on the command line)
00056  *            stopping the prompts so that the programs can be run unattended.
00057  *
00058  * Revision 1.25  2006/07/28 09:05:16  ir
00059  * T060728A - Add -u switch to example progs to accept cmd line args without
00060  *            prompting.
00061  *
00062  * Revision 1.24  2006/02/25 17:00:35  brs
00063  * T060224E - Change types to conform to function prototypes (between char*
00064  *            and u_char*, and int* and size_t*, primarily).
00065  *
00066  * Revision 1.23  2005/11/25 11:50:40  ldv
00067  * T051125A - Correct the meaning of the -W flag in the usage message
00068  *
00069  * Revision 1.22  2005/11/17 10:38:37  ldv
00070  * T051110B - Remove double call to X400msClose(sp) (core dumps!)
00071  *
00072  * Revision 1.21  2005/11/03 11:55:03  tc
00073  * T051103A - Delete unnecessary Doxygen text.
00074  *
00075  * Revision 1.20  2005/10/12 10:42:58  ir
00076  * T051012A - Move otherwise unused variable into conditional compilation.
00077  *            Include <stdlib.h> for exit() prototype.
00078  *
00079  * Revision 1.19  2005/10/10 07:57:12  ir
00080  * T051007C - Call get_args() to parse cmdline args.
00081  *
00082  * Revision 1.18  2005/09/23 12:30:15  ldv
00083  * T050922E - Set up logging from the file x400api.xml
00084  *
00085  * Revision 1.17  2005/09/08 14:05:48  tc
00086  * T050908C - Add example of setting of Wait interval.
00087  *            Don't register auto-forwarding by default.
00088  *
00089  * Revision 1.16  2005/09/06 14:22:40  tc
00090  * T050906C - Add examples of how to set AutoForward and AutoAlert autoactions.
00091  *
00092  * Revision 1.15  2005/05/25 16:23:34  dbw
00093  * T050525C - Files updated in 2004
00094  *
00095  * Revision 1.14  2004/07/09 09:20:25  ldv
00096  * T040708C - Handle Delivery Reports
00097  *
00098  * Revision 1.13  2004/06/30 09:31:15  ldv
00099  * T040625G - Improve the examples to use the new API functionality
00100  *
00101  * Revision 1.12  2004/06/29 09:07:49  tc
00102  * T040629A - Delete include of cmd_srch.h.
00103  *
00104  * Revision 1.11  2004/05/27 12:01:40  dbw
00105  * T040527A - user_name becomes user_addr and user_dn
00106  *            Change in X400msOpen argument.
00107  *
00108  * Revision 1.10  2004/05/11 10:23:59  tc
00109  * T040511B - Print a warning message and delete message if report retrieved.
00110  *
00111  * Revision 1.9  2004/05/06 09:26:33  tc
00112  * T040505C - Replace use of X400Message with X400msMessage.
00113  *            Call common 'do_tailoring' function to get data from x400tailor file.
00114  *            Rearrange data input code.
00115  *            Call common 'set_defaults' routine.
00116  *
00117  * Revision 1.8  2004/02/19 15:09:15  tc
00118  * T040219A - Update X400msOpen call to include user orname parameter. Add code
00119  *            to read user orname from stdin. Improve output messages. Report
00120  *            error codes returned from API functions.
00121  *
00122  * Revision 1.7  2003/10/20 09:14:49  tc-local
00123  * T031017B - Rename amhs->x400 throughout.
00124  *
00125  * Revision 1.6  2003/09/30 15:32:08  tc
00126  * T030930A - Correct call to exit().
00127  *
00128  * Revision 1.5  2003/09/29 16:36:31  ir
00129  * T030929C - Tidy up use of return codes.
00130  *
00131  * Revision 1.4  2003/09/26 13:31:15  tc-local
00132  * T030925E - Add code to allow choice of P7 or P3 connection and option of specifying
00133  *            presentation address. Do not exit if messages_waiting = 0. Call AMHSmsWait()
00134  *            before trying to read a message.
00135  *
00136  * Revision 1.3  2003/09/11 11:01:15  ir
00137  * T030911A - Use AMHSMessage and AMHSRecipient over AMHS API.
00138  *
00139  * Revision 1.2  2003/09/10 15:59:16  tc-local
00140  * T030910C - Change AMHSmsRecipient to AMHSRecipient. Add call to AMHSmsClose().
00141  *
00142  * Revision 1.1  2003/08/27 15:21:57  ir
00143  * T030819A - Initial checkin of AMHS module.
00144  *
00145  *
00146  * Simple example program for receiving a message from a store.
00147  */
00148 #include <stdio.h>
00149 #include <stdlib.h>
00150 #include <x400_msapi.h>
00151 #include <seclabel_api.h> /* For security labels */
00152 #include "example.h"
00153 
00154 static char *optstr = "u371m:d:p:w:M:D:P:W:";
00155 
00156 static void usage(void);
00157 
00158 
00159 #ifdef WANT_DL_EXP_HIST
00160 static int do_dl_hist (
00161     struct X400msMessage *mp
00162 );
00163 #endif
00164 
00165 static int get_body_parts(
00166     struct X400msMessage *mp
00167 );
00168 
00169 static int get_bp(
00170     struct X400msMessage *mp,
00171     struct X400Bodypart **bp,
00172     int att_num
00173 );
00174 
00175 static int get_msgbp(
00176     struct X400msMessage *mp,
00177     struct X400Message **x400_mp,
00178     int att_num
00179 );
00180 
00181 static int do_xmsg_headers(
00182     struct X400Message *x400_mp
00183 );
00184 
00185 static int do_xmsg_content_as_bp(
00186     struct X400Message *x400_mp
00187 );
00188 
00189 static int do_xrep_headers(
00190     struct X400Message *x400_mp
00191 );
00192 
00193 static int do_xmsg_headers(
00194     struct X400Message *x400_mp
00195 );
00196 
00197 static int do_xrep_content_as_bp(
00198     struct X400Message *x400_mp
00199 );
00200 
00201 static int get_recips(
00202     struct X400Message  *x400_mp,
00203     int                 type
00204 );
00205 
00206 static int do_redirection_hist (
00207     struct X400Recipient *rp
00208 );
00209 
00210 static int do_redirection_hist_env (
00211     struct X400msMessage *mp
00212 );
00213 
00214 static int do_trace_info (
00215     struct X400msMessage *mp
00216 );
00217 
00218 static int do_internal_trace_info (
00219     struct X400msMessage *mp
00220 );
00221 
00222 static int do_orig_and_dl (
00223     struct X400msMessage *mp
00224 );
00225 
00229 int
00230 main(
00231     int argc,
00232     char **argv)
00233 {
00234     char buffer[BUFSIZ];
00235     char pa[BUFSIZ];
00236     char orn[BUFSIZ];
00237     int status;
00238     int nummsg;
00239     int type;
00240     int seqn;
00241     struct X400msSession *sp;
00242     struct X400msMessage *mp;
00243     struct X400Recipient *rp;
00244     int n;
00245     size_t length;
00246     int contype;
00247     char *def_oraddr;
00248     char *def_dn;
00249     char *def_pa;
00250     int intparam;
00251     char recipient_str[BUFSIZ];
00252     int num_recips = -1;
00253 
00254     if (get_args(argc, argv, optstr)) {
00255         usage();
00256         exit(-1);
00257     }
00258 
00259     printf("Connection type (0 = P7, 1 = P3 submit only, 2 = P3 both directions) [%d]: ", x400_contype);
00260     contype = ic_fgetc(x400_contype, stdin);
00261     if (contype != 10)
00262         ic_fgetc(x400_contype, stdin);
00263 
00264     if ( contype < '0' || '2' < contype )
00265         contype = x400_contype;
00266     else
00267         contype -= '0';
00268 
00269     if (contype == 0) {
00270         def_oraddr = x400_ms_user_addr;
00271         def_dn = x400_ms_user_dn;
00272         def_pa = x400_ms_presentation_address;
00273     }
00274     else {
00275         def_oraddr = x400_mta_user_addr;
00276         def_dn = x400_mta_user_dn;
00277         def_pa = x400_mta_presentation_address;
00278     }
00279 
00280     printf("Your ORAddress [%s] > ", def_oraddr);
00281     ic_fgets(orn, sizeof orn, stdin);
00282 
00283     if (orn[strlen(orn) - 1] == '\n')
00284         orn[strlen(orn) - 1] = '\0';
00285 
00286     if (orn[0] == '\0')
00287         strcpy(orn, def_oraddr);
00288 
00289     /* Prompt for password; note: reflected. */
00290     printf("Password [%s]: ",
00291            contype == 0 ? x400_p7_password : x400_p3_password);
00292     if (ic_fgets(buffer, sizeof buffer, stdin) == NULL)
00293         exit(1);
00294 
00295     if (buffer[strlen(buffer) - 1] == '\n')
00296         buffer[strlen(buffer) - 1] = '\0';
00297     if (buffer[0] == '\0')
00298         strcpy(buffer, contype == 0 ? x400_p7_password : x400_p3_password);
00299 
00300     printf("Presentation Address [%s] > ", def_pa);
00301     ic_fgets(pa, sizeof pa, stdin);
00302 
00303     if (pa[strlen(pa) - 1] == '\n')
00304         pa[strlen(pa) - 1] = '\0';
00305 
00306     if (pa[0] == '\0')
00307         strcpy(pa, def_pa);
00308 
00309     if (talking_to_marben_ms)
00310         X400msSetConfigRequest(0);
00311 
00312     status = X400msOpen(contype, orn, def_dn, buffer, pa, &nummsg, &sp);
00313     if (status != X400_E_NOERROR) {
00314         fprintf(stderr, "Error in Open: %s\n", X400msError(status));
00315         exit(status);
00316     }
00317 
00318     if (talking_to_marben_ms)
00319         X400msSetIntDefault(sp, X400_N_STRICT_P7_1988, 1);
00320 
00321 #ifdef USING_ALERTS
00322     /* If we register the alert auto-action, we will get an alert indication
00323        when a message is delivered. So there is no need to poll at
00324        short intervals within X400ms_Wait - we can do a slow background
00325        poll and rely on the Alert indication to wake the code up instead */
00326     X400msSetIntDefault(sp, X400_N_WAIT_INTERVAL, 1000);
00327 #endif
00328 
00329     /* setup logging from $(ETCDIR)x400api.xml or $(SHAREDIR)x400api.xml */
00330     X400msSetStrDefault(sp, X400_S_LOG_CONFIGURATION_FILE, "x400api.xml", 0);
00331 
00332     if (contype == 0) {
00333 #ifdef WANT_AUTOFORWARDING
00334         struct X400msAutoActionParameter *aa_param;
00335 
00336         /* Register an Autoforwarding Autoaction. */
00337         aa_param = X400msNewAutoActionParameter();
00338 
00339         /* Add mandatory things to AutoAction parameter for auto-forwarding:
00340            i.e. recipient address */
00341         X400RecipNew(0, &rp);
00342 
00343         X400RecipAddStrParam(rp, X400_S_OR_ADDRESS, def_oraddr,
00344                              strlen(def_oraddr));
00345 
00346         X400msAutoActionParameterAddRecip(aa_param, X400_RECIP_STANDARD, rp);
00347 
00348         X400msAutoActionParameterAddStrParam(aa_param,
00349                                              X400_S_CONTENT_IDENTIFIER,
00350                                              "AF contentid", -1);
00351 
00352         X400msAutoActionParameterAddIntParam(aa_param, X400_N_DISCLOSURE, 1);
00353 
00354         X400msAutoActionParameterAddIntParam(aa_param,
00355                                              X400_N_IMPLICIT_CONVERSION_PROHIBITED,
00356                                              1);
00357 
00358         X400msAutoActionParameterAddIntParam(aa_param,
00359                                              X400_N_ALTERNATE_RECIPIENT_ALLOWED,
00360                                              1);
00361 
00362         X400msAutoActionParameterAddIntParam(aa_param,
00363                                              X400_N_CONTENT_RETURN_REQUEST,
00364                                              1);
00365 
00366         X400msAutoActionParameterAddIntParam(aa_param, X400_N_PRIORITY, 2);
00367 
00368         X400msAutoActionParameterAddStrParam(aa_param,
00369                                              X400_S_AUTO_FORWARDING_COMMENT,
00370                                              "This message was autoforwarded",
00371                                              -1);
00372 
00373         X400msAutoActionParameterAddStrParam(aa_param,
00374                                              X400_S_COVER_NOTE,
00375                                              "This is a cover note", -1);
00376 
00377         X400msAutoActionParameterAddStrParam(aa_param,
00378                                              X400_S_THIS_IPM_PREFIX,
00379                                              "AutoForwarded:", -1);
00380 
00381         status = X400msRegisterAutoAction(sp, X400_AUTO_FORWARDING,
00382                                           4, aa_param);
00383         if (status != X400_E_NOERROR) {
00384             fprintf(stderr,
00385                     "Error in RegisterAutoAction: %s\n", X400msError(status));
00386             /* tidily close the session */
00387             status = X400msClose(sp);
00388             exit(status);
00389         }
00390         printf("Registered AutoForwarding autoaction (id = 4) OK\n");
00391         X400msFreeAutoActionParameter(aa_param);
00392 #endif
00393 
00394 #ifdef USING_ALERTS
00395         /* No parameter needed for Alert autoaction - we do not support 
00396            configuration of requested-attributes in this API yet. */
00397         status = X400msRegisterAutoAction(sp, X400_AUTO_ALERT, 9, NULL);
00398         if (status != X400_E_NOERROR) {
00399             fprintf(stderr, "Error in RegisterAutoAction: %s\n",
00400                     X400msError(status));
00401             /* tidily close the session */
00402             status = X400msClose(sp);
00403             exit(status);
00404         }
00405         printf("Registered AutoAlert autoaction (id = 9) OK\n");
00406 #endif
00407 
00408         /* Just test the register and deregister functions */
00409         status = X400msRegisterAutoAction(sp, X400_AUTO_ALERT, 10, NULL);
00410         if (status != X400_E_NOERROR) {
00411             fprintf(stderr, "Error in RegisterAutoAction: %s\n",
00412                     X400msError(status));
00413             /* tidily close the session */
00414             status = X400msClose(sp);
00415             exit(status);
00416         }
00417         printf("Registered AutoAlert autoaction (id = 10) OK\n");
00418 
00419         /* Lets do a deregistration of the action we just registered */
00420         status = X400msDeregisterAutoAction(sp, X400_AUTO_ALERT, 10);
00421         if (status != X400_E_NOERROR) {
00422             fprintf(stderr, "Error in DeregisterAutoAction: %s\n",
00423                     X400msError(status));
00424             /* tidily close the session */
00425             status = X400msClose(sp);
00426             exit(status);
00427         }
00428         printf("Deregistered AutoAlert autoaction (id = 10) OK\n");
00429     }
00430 
00431     if (nummsg == 0) {
00432         printf ("no messages - waiting 60 seconds for a message to be delivered.....\n");
00433     }
00434     else {
00435         printf("%d messages waiting\n", nummsg);
00436     }
00437 
00438     status = X400msWait(sp, 1, &nummsg);
00439     if (status != X400_E_NOERROR) {
00440         fprintf(stderr, "Error from Wait: %s\n", X400msError(status));
00441         /* tidily close the session */
00442         status = X400msClose(sp);
00443         exit(status);
00444     }
00445 
00446     if (x400_default_recipient != NULL) 
00447     printf("Getting message\n");
00448     status = X400msMsgGet(sp, 0, &mp, &type, &seqn);
00449     switch (status) {
00450     case X400_E_NOERROR:
00451         fprintf(stderr, "MsgGet successfully got message\n");
00452         break;
00453     default :
00454         fprintf(stderr, "Error from MsgGet: %s\n", X400msError(status));
00455         /* tidily close the session */
00456         status = X400msClose(sp);
00457         exit(status);
00458         break;
00459     }
00460 
00461     if (type != X400_MSG_MESSAGE) {
00462         fprintf(stderr, "Got a report (printing only some attributes)\n");
00463 
00464         /* The ORADDRESS in the message is the (envelope) originator */
00465         status = X400msMsgGetStrParam(mp, X400_S_SUBJECT_IDENTIFIER,
00466                                       buffer, sizeof buffer, &length);
00467         if (status != X400_E_NOERROR) {
00468             fprintf(stderr, "Error from MsgGetStrParam: %s\n",
00469                     X400msError(status));
00470             /* tidily close the session */
00471             status = X400msClose(sp);
00472             exit(status);
00473         }
00474         printf("Subject Identifier: %.*s\n", (int)length, buffer);
00475 
00476         /* Get hold of the Originator and DL history*/
00477         status = do_orig_and_dl (mp);
00478         if (status != X400_E_NOERROR &&
00479             status != X400_E_MISSING_ATTR) {
00480             fprintf(stderr,"Failed to fetch originator and dl history: %s\n",
00481                     X400msError (status));
00482         }
00483         
00484         /* Get the primary recipients */
00485         for (n = 1;; n++) {
00486             status = X400msRecipGet(mp, X400_RECIP_REPORT, n, &rp);
00487             if (status == X400_E_NO_RECIP)
00488                 break;
00489             if (status != X400_E_NOERROR) {
00490                 fprintf(stderr, "Error from RecipGet: %s\n",
00491                         X400msError(status));
00492                 /* tidily close the session */
00493                 status = X400msClose(sp);
00494                 exit(status);
00495             }
00496 
00497             /* Note: recipient may not actually have an O/R address */
00498             status = X400msRecipGetStrParam(rp, X400_S_OR_ADDRESS,
00499                                             recipient_str,
00500                                             sizeof recipient_str, &length);
00501             if (status != X400_E_NOERROR) {
00502                 fprintf(stderr, "Error from RecipGetStrParam: %s\n",
00503                         X400msError(status));
00504                 /* tidily close the session */
00505                 status = X400msClose(sp);
00506                 exit(status);
00507             }
00508 
00509             /* The original message delivery time, if this attribute exists, 
00510              * then the report is a positive Delivery Report */
00511             status = X400msRecipGetStrParam(rp, X400_S_MESSAGE_DELIVERY_TIME,
00512                                             buffer, sizeof buffer, &length);
00513             if (status == X400_E_NOERROR) {
00514                 /* Positive Delivery Report */
00515                 printf("Positive Delivery Report for recipient %d: %s\n", n,
00516                        recipient_str);
00517                 printf("Delivery Time: %.*s\n", (int)length, buffer);
00518             }
00519             else {
00520                 /* Negative Delivery Report */
00521                 printf("Negative Delivery Report for recipient %d: %s\n", n,
00522                        recipient_str);
00523 
00524                 /* Supplementary Info to the report */
00525                 status = X400msRecipGetStrParam(rp, X400_S_SUPPLEMENTARY_INFO,
00526                                                 buffer, sizeof buffer,
00527                                                 &length);
00528                 if (status != X400_E_NOERROR) {
00529                     fprintf(stderr, "Error from RecipGetStrParam: %s\n",
00530                             X400msError(status));
00531                     buffer[0] = '\0';
00532                 }
00533                 printf("Supplementary Info: %.*s\n", (int)length, buffer);
00534 
00535                 /* The reason why the message was not delivered */
00536                 status =
00537                     X400msRecipGetIntParam(rp, X400_N_NON_DELIVERY_REASON,
00538                                            &intparam);
00539                 if (status != X400_E_NOERROR) {
00540                     fprintf(stderr, "Error from MsgGetIntParam: %s\n",
00541                             X400msError(status));
00542                 }
00543                 printf("Non-Delivery Reason: %d\n", intparam);
00544 
00545                 /* The diagnostics of the report for this recipient */
00546                 status =
00547                     X400msRecipGetIntParam(rp, X400_N_NON_DELIVERY_DIAGNOSTIC,
00548                                            &intparam);
00549                 if (status != X400_E_NOERROR) {
00550                     fprintf(stderr, "Error from MsgGetIntParam: %s\n",
00551                             X400msError(status));
00552                 }
00553                 printf("Non-Delivery Diagnostic: %d\n", intparam);
00554             }
00555         }
00556 
00557         status = X400msMsgDelete(mp, 0);
00558         status = X400msClose(sp);
00559         exit(status);
00560     }
00561 
00562 
00563     /* The message identifier */
00564     status = X400msMsgGetStrParam(mp, X400_S_MESSAGE_IDENTIFIER,
00565                                   buffer, sizeof buffer, &length);
00566     if (status != X400_E_NOERROR) {
00567         fprintf(stderr, "Error from MsgGetStrParam: %s\n",
00568                 X400msError(status));
00569         /* tidily close the session */
00570         status = X400msClose(sp);
00571         exit(status);
00572     }
00573     printf("Message Identifier: %.*s\n", (int)length, buffer);
00574 
00575     /* The ORADDRESS in the message is the (envelope) originator */
00576     status = X400msMsgGetStrParam(mp, X400_S_OR_ADDRESS,
00577                                   buffer, sizeof buffer, &length);
00578     if (status != X400_E_NOERROR) {
00579         fprintf(stderr, "Error from MsgGetStrParam: %s\n",
00580                 X400msError(status));
00581         /* tidily close the session */
00582         status = X400msClose(sp);
00583         exit(status);
00584     }
00585     printf("Originator: %.*s\n", (int)length, buffer);
00586 
00587     status = X400msMsgCountRecip(mp, X400_RECIP_PRIMARY, &num_recips);
00588     if (status != X400_E_NOERROR) {
00589         fprintf(stderr, "Error from MsgCountRecip: %s\n",
00590                 X400msError(status));
00591         /* tidily close the session */
00592         status = X400msClose(sp);
00593         exit(status);
00594     }
00595 
00596     printf("There are %d recipients\n", num_recips);
00597 
00598     /* Get the envelope recipients */
00599     for (n = 1;; n++) {
00600         status = X400msRecipGet(mp, X400_RECIP_ENVELOPE, n, &rp);
00601         if (status == X400_E_NO_RECIP)
00602             break;
00603         if (status != X400_E_NOERROR) {
00604             fprintf(stderr, "Error from RecipGet: %s\n", X400msError(status));
00605             /* tidily close the session */
00606             status = X400msClose(sp);
00607             exit(status);
00608         }
00609 
00610         /* Note: recipient may not actually have an O/R address */
00611         status = X400msRecipGetStrParam(rp, X400_S_OR_ADDRESS,
00612                                         buffer, sizeof buffer, &length);
00613         if (status == X400_E_NOERROR) {
00614             printf("Envelope Recipient %d: %.*s\n", n, (int)length, buffer);
00615         }
00616     }
00617 
00618     /* Get the primary recipients */
00619     for (n = 1;; n++) {
00620         status = X400msRecipGet(mp, X400_RECIP_PRIMARY, n, &rp);
00621         if (status == X400_E_NO_RECIP)
00622             break;
00623         if (status != X400_E_NOERROR) {
00624             fprintf(stderr, "Error from RecipGet: %s\n", X400msError(status));
00625             /* tidily close the session */
00626             status = X400msClose(sp);
00627             exit(status);
00628         }
00629 
00630         /* Note: recipient may not actually have an O/R address */
00631         status = X400msRecipGetStrParam(rp, X400_S_OR_ADDRESS,
00632                                         buffer, sizeof buffer, &length);
00633         if (status == X400_E_NOERROR) {
00634             printf("Primary Recipient %d: %.*s\n", n, (int)length, buffer);
00635         }
00636     }
00637 
00638 #ifdef WANT_DL_EXP_HIST
00639     /* DL Expansion history */
00640     {
00641 
00642         status = do_dl_hist(hist);
00643 
00644         /* Normally the status is "X400_E_NO_VALUE" If there is no
00645          * DL Expansion history.
00646          * Or X400_E_MISSING_ATTR if the DL Expansion history entry is missing
00647          * (so end of loop)
00648          */
00649         if ( status == X400_E_NO_VALUE) {
00650             /* do nothing */
00651         } else if (status == X400_E_MISSING_ATTR ) {
00652             printf("There is no DL expansion history\n");
00653         } else {
00654             /* There has been an error fetching the DL expansion history*/
00655              printf("error getting DL Expansion History\n");
00656              fprintf (stderr, "Error in X400mtDLExpHistGet: %s\n", 
00657                       X400msError (status));
00658             return status;
00659         }
00660     }
00661 #endif
00662 
00663 #define WANT_TRACE_INFO 1    
00664 #ifdef WANT_TRACE_INFO
00665  {
00666 
00667      status = do_trace_info(mp);
00668      if ( status == X400_E_NO_VALUE) {
00669          
00670      } else if (status == X400_E_MISSING_ATTR ) {
00671          printf("There is no Trace Info\n");
00672      } else {
00673          printf("error getting Trace Info\n");
00674          fprintf (stderr, "Error fetching trace info: %s\n", 
00675                   X400msError (status));
00676          return status;
00677      }
00678          
00679  }
00680     
00681 #endif
00682 
00683 #define USE_INTERNAL_TRACE_INFO 1
00684 #ifdef  USE_INTERNAL_TRACE_INFO
00685  {
00686 
00687      status = do_internal_trace_info(mp);
00688      if ( status == X400_E_NO_VALUE) {
00689          /* do nothing */
00690      } else if (status == X400_E_MISSING_ATTR ) {
00691          printf("There is no internal Trace Info\n");
00692      } else {
00693          printf("error getting int Trace Info\n");
00694          fprintf (stderr, "Error fetching int trace info: %s\n", 
00695                   X400msError (status));
00696          return status;
00697      }
00698          
00699  }  
00700 #endif
00701   
00702 
00703     
00704 #define USE_REDIRECTION_HISTORY 1
00705 #ifdef  USE_REDIRECTION_HISTORY
00706  {
00707      status = do_redirection_hist_env(mp);
00708      if ( status == X400_E_NO_VALUE ) {
00709          /* do nothing */
00710      } else if (status == X400_E_MISSING_ATTR ) {
00711          printf("There is no Redirection History\n");
00712      } else {
00713          printf("error getting Redirection History\n");
00714          fprintf (stderr, "Error fetching Redirection History: %s\n", 
00715                   X400msError (status));
00716          return status;
00717      }  
00718  }
00719 #endif   
00720     /* Security Label */
00721 
00722 #ifdef USE_SEC_LABEL
00723     
00724 #define XML_BUFSIZE 1024
00725  {
00726      char  xml_buffer[XML_BUFSIZE];
00727      unsigned char slab_buffer[XML_BUFSIZE];
00728      
00729      status = X400msMsgGetStrParam(mp,
00730                                    X400_S_SECURITY_LABEL,
00731                                    (char*)slab_buffer,
00732                                    XML_BUFSIZE,
00733                                    &length);
00734     if (status == X400_E_NO_VALUE) {
00735         printf("No security label\n");
00736     } else if (status !=  X400_E_NOERROR) {
00737         fprintf(stderr,"Failed to fetch security label: %d",status);
00738         exit(1);
00739     } else {
00740         int sec_status = 0;
00741         
00742         sec_status = SecLabelInit("Example program");
00743         if (status != SECLABEL_E_NOERROR) {
00744             fprintf(stderr, "SecLabelInit returned error %d\n", status);
00745             exit(1);
00746         }
00747 
00748         status =  SecLabelPrint(slab_buffer,
00749                                 length,
00750                                 xml_buffer,
00751                                 XML_BUFSIZE);
00752         
00753         if (status != SECLABEL_E_NOERROR) {
00754             fprintf(stderr, "SecLabelParse returned error %d\n", status);
00755             exit(1);
00756         }
00757         
00758         /* You could now write out the XML file, or parse it in memory..*/
00759         printf("Got security label:%s\n",xml_buffer);
00760     }
00761 
00762     
00763  }
00764     
00765 #endif
00766 
00767 
00768  
00769     /* Subject is optional */
00770     status = X400msMsgGetStrParam(mp, X400_S_SUBJECT,
00771                                   buffer, sizeof buffer, &length);
00772     if (status == X400_E_NOERROR)
00773         printf("Subject: %.*s\n", (int)length, buffer);
00774 
00775     /* And message text (or it could be another type) */
00776     status = X400msMsgGetStrParam(mp, X400_T_IA5TEXT,
00777                                   buffer, sizeof buffer, &length);
00778     if (status == X400_E_NOERROR)
00779         printf("Text:\n%.*s\n", (int)length, buffer);
00780 
00781     /* get all the attachments */
00782     status = get_body_parts(mp);
00783 
00784     /* Deletes message in message store as well as internal copy */
00785     status = X400msMsgDelete(mp, 0);
00786 
00787     status = X400msClose(sp);
00788     return(status);
00789 }
00790 
00791 #ifdef WANT_DL_EXP_HIST
00792 static int do_dl_hist (
00793     struct X400msMessage *mp
00794 )
00795 {
00796     char    DLORAddress[BUFSIZ];
00797     char    DLORDN[BUFSIZ];
00798     char    DLExpTime[BUFSIZ];
00799     size_t  length;
00800     int n;
00801     int status;
00802     struct X400DLExpHist *hist = NULL;
00803 
00804     /* Loop through the entries, pulling out the OR Address, DN, and expansion
00805      * time for each entry.
00806      * Stop looping when there is no n entry
00807      */
00808     for ( n=1; ;n++ ) {
00809 
00810         status = X400msDLExpHistGet (mp,n,&hist);
00811         if (status != X400_E_NOERROR) {
00812             return status;
00813         }
00814         
00815         status = X400DLGetStrParam (hist, X400_S_OR_ADDRESS,
00816                                       DLORAddress, BUFSIZ , &length);
00817         if (status == X400_E_NO_VALUE) {
00818             return X400_E_NO_VALUE;
00819         }
00820         if ( status == X400_E_NOERROR ) {
00821             DLORAddress[length] = '\0';
00822             printf ("DLExpansion List entry %d OR Address:%s\n",
00823                     n,DLORAddress);
00824         } else {
00825             fprintf (stderr, "Error in :X400mtDLGetStrParam OR %s\n",
00826                      X400msError (status));
00827         }
00828 
00829         
00830         
00831         status = X400DLGetStrParam (hist, X400_S_DIRECTORY_NAME,
00832                                     DLORDN, BUFSIZ , &length);
00833         if ( status == X400_E_NOERROR ) {
00834             DLORDN[length] = '\0';
00835             printf ("DLExpansion List entry %d DN :%s\n",n,DLORDN);
00836         } else {
00837             fprintf (stderr, "Error in :X400mtDLGetStrParam DN %s\n",
00838                      X400msError (status));
00839         }
00840             
00841         status = X400DLGetStrParam (hist, X400_S_DLEXP_TIME,
00842                                     DLExpTime, BUFSIZ , &length);
00843         if ( status == X400_E_NOERROR ) {
00844             DLExpTime[length] = '\0';
00845             printf ("DLExpansion List entry %d Time :%s\n",n,DLExpTime);
00846         } else {
00847             fprintf (stderr, "Error in :X400mtDLGetStrParam Time %s\n",
00848                      X400msError (status));
00849         }
00850             
00851     }
00852     if (n == 1) {
00853         printf("No DLEH found in message");
00854     } else {
00855         printf("%d DLEH entries found in message", n - 1);
00856     }
00857     return X400_E_NOERROR;
00858 }
00859 #endif
00860 
00861 static int get_body_parts(
00862     struct X400msMessage *mp
00863 )
00864 {
00865 #define INIT_BUFFER_SIZE 10000
00866     int         status;
00867     int         num_atts = 0;
00868     int         type;
00869     char        *buf;
00870     size_t      buflen;
00871     size_t      ret_len;
00872     int         i;
00873     size_t      j;
00874     struct X400Message *x400_mp;
00875     struct X400Bodypart *bp;
00876 
00877 
00878     status = X400msMsgGetIntParam (mp, X400_N_NUM_ATTACHMENTS, &num_atts);
00879     if ( status != X400_E_NOERROR ) {
00880         fprintf (stderr, "Error in X400msMsgGetIntParam attachments %s\n",
00881                  X400msError (status));
00882         return status;
00883     }
00884     printf ("Number of attachments is %d\n", num_atts);
00885 
00886     buf = (char *) malloc(INIT_BUFFER_SIZE);
00887     if (buf == NULL) {
00888         fprintf(stderr, "can't alloc %d bytes\n", INIT_BUFFER_SIZE);
00889         return X400_E_NOMEMORY;
00890     }
00891     buflen = INIT_BUFFER_SIZE;
00892 
00893     for (i = 1; i <= num_atts ; i++) {
00894         printf ("Get attachment %d\n", i);
00895         status = X400msMsgGetAttachment(mp, i, &type, buf, buflen, &ret_len);
00896         if (status == X400_E_NOSPACE) {
00897             fprintf(stderr, "realloc %d bytes\n", ret_len);
00898             buf = (char *) realloc(buf, ret_len + 1);
00899             if (buf == NULL) {
00900                 fprintf(stderr, "can't alloc %d bytes\n", INIT_BUFFER_SIZE);
00901                 return X400_E_NOMEMORY;
00902             }
00903             buflen = ret_len;
00904             status = X400msMsgGetAttachment(
00905                 mp, i, &type, buf, buflen, &ret_len);
00906             /* fall through with status set */
00907         }
00908         /* for some attachments you must use the BodyPart functions */
00909         if (status == X400_E_COMPLEX_BODY) {
00910             printf("got complex bodypart\n");
00911             status = get_bp(mp, &bp, i);
00912             if (status != X400_E_NOERROR ) {
00913                 return status;
00914             }
00915         }
00916         /* for forwarded messages you must use the BodyPart functions */
00917         else if (status == X400_E_MESSAGE_BODY) {
00918             printf("got forwarded message bodypart\n");
00919             status = get_msgbp(mp, &x400_mp, i);
00920             if (status != X400_E_NOERROR ) {
00921                 return status;
00922             }
00923         }
00924         else if (status == X400_E_NOERROR) {
00925             /* process text or binary attachment */
00926             printf("got text or binary attachment\n");
00927             switch (type) {
00928                 case X400_T_BINARY:
00929                 case X400_T_FTBP:
00930                     printf("First 1000 bytes of Binary Data for %s BP is:",
00931                         type == X400_T_BINARY ? "Binary" : "FTBP");
00932                     for (j = 0; j < ret_len && j < 1000; j++)
00933                         printf("%x ", buf[j]);
00934                     printf("\n");
00935                     break;
00936                 default: 
00937                     printf("Printable Data for BP is:\n %s", buf);
00938                     break;
00939             }
00940         }
00941         else {
00942             /* got an error */
00943             fprintf (stderr, "Error in X400msMsgGetAttachment %s\n",
00944                      X400msError (status));
00945             break;
00946         }
00947     }
00948     return status;
00949 }
00950 
00951 static int get_bp(
00952     struct      X400msMessage *mp,
00953     struct      X400Bodypart **bpp,
00954     int         att_num
00955 )
00956 {
00957     int         status;
00958     int         type;
00959     int         bp_type;
00960     size_t      j;
00961     char        *buf;
00962     size_t      buflen;
00963     size_t      ret_len;
00964 
00965 #define INIT_BUFFER_SIZE 10000
00966     printf ("Get Bodypart %d\n", att_num);
00967 
00968     /* firstly get the Bodypart */
00969     status = X400msMsgGetBodypart(mp, att_num, &type, bpp);
00970     if (status != X400_E_NOERROR) {
00971         fprintf(stderr, "X400msMsgGetBodypart %d failed %s\n", att_num,
00972                  X400msError (status));
00973         return status;
00974     }
00975     printf("got Bodypart %d, type = %d\n", att_num, type);
00976 
00977     /* What kind of Bodypart using a attribute of the BP */
00978     status = X400BodypartGetIntParam(*bpp, X400_N_BODY_TYPE, &bp_type);
00979     if (status != X400_E_NOERROR) {
00980         fprintf(stderr, "X400msMsgGetBodypart failed %s\n",
00981                  X400msError (status));
00982         return status;
00983     }
00984     printf("got Bodypart %d, type = %s\n", att_num, 
00985             bp_type == X400_T_IA5TEXT ? "IA5" : 
00986             bp_type == X400_T_ISO8859_1 ? "ISO8859-1" :
00987             bp_type == X400_T_ISO8859_2 ? "ISO8859_2" :
00988             bp_type == X400_T_BINARY ? "Binary" : 
00989             bp_type == X400_T_MESSAGE ? "Message" : 
00990             bp_type == X400_T_FTBP ? "File Transfer BP" :
00991             bp_type == X400_T_GENERAL_TEXT ? "General Text" : "Unknown"
00992             );
00993 
00994     /* setup buffer to use to return BP data */
00995     buf = (char *) malloc(INIT_BUFFER_SIZE);
00996     if (buf == NULL) {
00997         fprintf(stderr, "can't alloc %d bytes\n", INIT_BUFFER_SIZE);
00998         return X400_E_NOMEMORY;
00999     }
01000     buflen = INIT_BUFFER_SIZE;
01001     /* Read data from the Bodypart */
01002     status = X400BodypartGetStrParam(*bpp, X400_S_BODY_DATA, buf, 
01003         buflen, &ret_len);
01004     if (status == X400_E_NOSPACE) {
01005         fprintf(stderr, "realloc %d bytes\n", ret_len);
01006         buf = (char *) realloc(buf, ret_len + 1);
01007         if (buf == NULL) {
01008             fprintf(stderr, "can't alloc %d bytes\n", INIT_BUFFER_SIZE);
01009             return X400_E_NOMEMORY;
01010         }
01011         buflen = ret_len;
01012         status = X400BodypartGetStrParam(*bpp, X400_S_BODY_DATA, buf, 
01013             buflen, &ret_len);
01014         /* fall through with status set */
01015     }
01016     if (status != X400_E_NOERROR) {
01017         fprintf(stderr, "X400msMsgGetBodypart failed %s\n",
01018                  X400msError (status));
01019         return status;
01020     }
01021     printf("got %d bytes of Bodypart data\n", ret_len);
01022     switch (bp_type) {
01023         case X400_T_BINARY:
01024         case X400_T_FTBP:
01025             printf("First 1000 bytes of Binary Data for %s BP is:",
01026                 type == X400_T_BINARY ? "Binary" : "FTBP");
01027             for (j = 0; j < ret_len && j < 1000; j++)
01028                 printf("%x ", buf[j]);
01029             printf("\n");
01030             break;
01031         default: 
01032             printf("Printable Data for BP is:\n %s", buf);
01033             break;
01034     }
01035 
01036 
01037 
01038     return X400_E_NOERROR;
01039 
01040 }
01041 
01042 /*
01043  * Extract and return a Bodypart from an MS Message
01044  */
01045 static int get_msgbp(
01046     struct X400msMessage *mp,
01047     struct X400Message **x400_mpp,
01048     int bp_num
01049 )
01050 {
01051     struct X400Message *x400_mp;
01052     int         status;
01053     char        buf[INIT_BUFFER_SIZE];
01054     int         buflen = sizeof buf;
01055     size_t      ret_len;
01056 
01057     status = X400msMsgGetMessageBody(mp, bp_num, x400_mpp);
01058     if (status != X400_E_NOERROR) {
01059         fprintf(stderr, "X400MsgGetMessageBody (%d) failed %s\n",
01060                  bp_num, X400msError (status));
01061         return status;
01062     }
01063     printf("Got Message BP from BP %d\n", bp_num);
01064     x400_mp = *x400_mpp;
01065 
01066     status = X400MsgGetStrParam(x400_mp, X400_S_OBJECTTYPE, buf, buflen, 
01067             &ret_len);
01068     if (status != X400_E_NOERROR) {
01069         fprintf(stderr, "X400MsgGetStrParam (%d) failed %s\n",
01070                  X400_S_OBJECTTYPE, X400msError (status));
01071         return status;
01072     }
01073     printf("Message BP from BP is '%.*s'\n", ret_len, buf);
01074     if (strncmp(buf, "message", ret_len) == 0 ) {
01075         status = do_xmsg_headers(x400_mp);
01076         if (status != X400_E_NOERROR) 
01077             return status;
01078         status = do_xmsg_content_as_bp(x400_mp);
01079         if (status != X400_E_NOERROR) 
01080             return status;
01081     }
01082     else if (strncmp(buf, "report", ret_len) == 0 ) {
01083         status = do_xrep_headers(x400_mp);
01084         if (status != X400_E_NOERROR) 
01085             return status;
01086         status = do_xrep_content_as_bp(x400_mp);
01087         if (status != X400_E_NOERROR) 
01088             return status;
01089     }
01090     else if (strncmp(buf, "probe", ret_len) == 0 ) {
01091         status = do_xmsg_headers(x400_mp);
01092         if (status != X400_E_NOERROR) 
01093             return status;
01094     }
01095     else {
01096         fprintf(stderr, "got unknown object: %s\n", buf);
01097         return X400_E_BADPARAM;
01098     }
01099 
01100 
01101     return X400_E_NOERROR;
01102 }
01103 
01104 static int do_xmsg_headers(
01105     struct X400Message *x400_mp
01106 )
01107 {
01108     int         status;
01109     char        buf[INIT_BUFFER_SIZE];
01110     int         buflen = sizeof buf;
01111     size_t      ret_len;
01112     int         num_atts;
01113 
01114     printf("do_xmsg_headers\n");
01115     status = X400MsgGetStrParam(x400_mp, X400_S_IPM_IDENTIFIER, buf, buflen, 
01116             &ret_len);
01117     if (status != X400_E_NOERROR) {
01118         fprintf(stderr, "X400MsgGetStrParam (%d) failed %s\n",
01119                  X400_S_OBJECTTYPE, X400msError (status));
01120         return status;
01121     }
01122     printf("IPM Identifier from Message BP '%.*s'\n", ret_len, buf);
01123 
01124     status = X400MsgGetStrParam(x400_mp, X400_S_SUBJECT, buf, buflen, 
01125             &ret_len);
01126     if (status != X400_E_NOERROR) {
01127         fprintf(stderr, "X400MsgGetStrParam (%d) failed %s\n",
01128                  X400_S_OBJECTTYPE, X400msError (status));
01129         return status;
01130     }
01131     printf("Subject from Message BP '%.*s'\n", ret_len, buf);
01132 
01133     status = X400MsgGetIntParam(x400_mp, X400_N_NUM_ATTACHMENTS, &num_atts);
01134     if (status != X400_E_NOERROR) {
01135         fprintf(stderr, "X400MsgGetStrParam (%d) failed %s\n",
01136                  X400_S_OBJECTTYPE, X400msError (status));
01137         return status;
01138     }
01139     printf("Number of attachments in Message BP %d'\n", num_atts);
01140 
01141     status = get_recips(x400_mp, X400_ORIGINATOR);
01142     if (status != X400_E_NOERROR) {
01143         return status;
01144     }
01145 
01146     status = get_recips(x400_mp, X400_RECIP_PRIMARY);
01147     if (status != X400_E_NOERROR) {
01148         return status;
01149     }
01150 
01151 
01152     return X400_E_NOERROR;
01153 }
01154 
01155 
01156 static int get_recips(
01157     struct X400Message  *x400_mp,
01158     int                 type
01159 )
01160 {
01161 
01162     struct X400Recipient        *rp;
01163     int                         status;
01164     int                         recip_num;
01165 
01166     for (recip_num = 1; ; recip_num++ ) {
01167 
01168         char    buf[INIT_BUFFER_SIZE];
01169         int             buflen = sizeof buf;
01170         size_t  ret_len;
01171 
01172         status = X400MsgGetRecip(x400_mp, type, recip_num, &rp);
01173         if (status == X400_E_NO_RECIP) {
01174             if (recip_num == 1) {
01175                 printf("no recips of type %x\n", type);
01176                 return X400_E_NOERROR;
01177             } else {
01178                 printf("no more recips of type %x\n", type);
01179             }
01180             return X400_E_NOERROR;
01181         }
01182         else if (status != X400_E_NOERROR) {
01183             fprintf(stderr, "X400MsgGetRecip (%d) failed %s\n",
01184                      X400_S_OBJECTTYPE, X400msError (status));
01185             return status;
01186         }
01187         printf("got recip number %d of type %s (%x)\n", recip_num,
01188                 type == X400_RECIP_PRIMARY ? "Primary" : 
01189                 type == X400_RECIP_CC ? "CC" : 
01190                 type == X400_RECIP_BCC ? "BCC" : 
01191                 type == X400_ORIGINATOR ? "Originator" : 
01192                 type == X400_AUTH_ORIG ? "Auth Orig" : 
01193                 type == X400_RECIP_REPLY ? "Reply" : 
01194                 type == X400_RECIP_REPORT ? "Reported Recip" : 
01195                 type == X400_RECIP_INTENDED ? "Intended" : 
01196                 type == X400_RECIP_ENVELOPE ? "Envelope" : 
01197                 "Unknown",
01198                 type);
01199         if (type == X400_RECIP_ENVELOPE) {
01200             // These aren't expected as the message will be forwarded
01201             // message with no envelope
01202             status = X400RecipGetStrParam(rp, X400_S_OR_ADDRESS, buf, buflen, 
01203                     &ret_len);
01204             if (status != X400_E_NOERROR) {
01205                 fprintf(stderr, "X400MsgGetStrParam (%d) failed %s\n",
01206                          X400_S_OBJECTTYPE, X400msError (status));
01207             } else {
01208                 printf("Originator OR Address'%.*s'\n", ret_len, buf);
01209             }
01210         } else {
01211             status = X400RecipGetStrParam(rp, X400_S_OR_ADDRESS, buf, buflen, 
01212                     &ret_len);
01213             if (status != X400_E_NOERROR) {
01214                 fprintf(stderr, "X400MsgGetStrParam (%d) failed %s\n",
01215                          X400_S_OBJECTTYPE, X400msError (status));
01216             } else {
01217                 printf("Originator OR Address'%.*s'\n", ret_len, buf);
01218             }
01219 
01220         }
01221 
01222 #define USE_REDIRECTION_HISTORY 1
01223 #ifdef  USE_REDIRECTION_HISTORY
01224  {
01225      status = do_redirection_hist(rp);
01226      if ( status == X400_E_NO_VALUE ) {
01227          /* do nothing */
01228      } else if (status == X400_E_MISSING_ATTR ) {
01229          printf("There is no Redirection History\n");
01230      } else {
01231          printf("error getting Redirection History\n");
01232          fprintf (stderr, "Error fetching Redirection History: %s\n", 
01233                   X400msError (status));
01234          return status;
01235      }  
01236  }
01237 #endif
01238     }
01239 
01240 }
01241 static int do_xmsg_content_as_bp(
01242     struct X400Message *x400_mp
01243 )
01244 {
01245     printf("do_xmsg_content_as_bp NYI\n");
01246     return X400_E_NOERROR;
01247 }
01248 
01249 
01250 static int do_xrep_headers(
01251     struct X400Message *x400_mp
01252 )
01253 {
01254     printf("do_xrep_headers NYI\n");
01255     return X400_E_NOERROR;
01256 }
01257 
01258 
01259 static int do_xrep_content_as_bp(
01260     struct X400Message *x400_mp
01261 )
01262 {
01263     printf("do_xrep_content_as_bp NYI\n");
01264     return X400_E_NOERROR;
01265 }
01266 
01267 
01268 static void usage(void) {
01269     printf("usage: %s\n", optstr);
01270     printf("\t where:\n");
01271     printf("\t -u : Don't prompt to override defaults \n");
01272     printf("\t -3 : Use P3 connection \n");
01273     printf("\t -7 : Use P7 connection \n");
01274     printf("\t -m : OR Address in P7 bind arg \n");
01275     printf("\t -d : DN in P7 bind arg \n");
01276     printf("\t -p : Presentation Address of P7 Store \n");
01277     printf("\t -w : P7 password of P7 user \n");
01278     printf("\t -M : OR Address in P3 bind arg \n");
01279     printf("\t -D : DN in P3 bind arg \n");
01280     printf("\t -P : Presentation Address of P3 server\n");