Next Previous Contents

3.6 Overview of rules required for clients

This sections covers the mechanisms used for:

Consider text of this section as recommendations. This rules does not have the common warning that you may loss compatibility with future versions of libsurprise if you don't follow it. The fact is that you may loss compatibility in any case as libsurprise currently does not plan to be backward compatible.

Required linking of clients

Place the following text to your "configure.in" script:


dnl Checks for libraries.
SURPRISE_INIT
CFLAGS="$CFLAGS SURPRISE_CFLAGS"
LIBS="$LIBS $SURPRISE_LIBS"
LDFLAGS="$LDFLAGS $SURPRISE_LDFLAGS"
AC_SUBST(CFLAGS)

Macro SURPRISE_INIT will be found automatically from "surprise.m4" placed in your "/usr/share/aclocal/" during installation.

SURPRISE_LIBS will (besides libsurprise itself) contain also all the libraries required by Partition Surprise library. There is only one caveat for Gnome-linked projects: Surprise also requires libpopt -- the library for parsing of command-linr arguments. Unfortunately Gnome by default supplies its own libpopt hidden inside its libgnomesupport. This Gnome version of libpopt is too dumb to be used by Surprise. The solution is to override Gnome supplied version with original libpopt:


LIBS += $(GNOMEUI_LIBS)

*_LDADD specified libraries are unfortunately applied after LIBS so using someclient_LDADD wouldn't help us. You can equivalently discard LIBS="$LIBS $SURPRISE_LIBS" line from "configure.in" and use:


someclient_LDADD = $(SURPRISE_LIBS) $(GNOMEUI_LIBS)

Parsing of command-line arguments of clients

Surprise provides various command-line options available to all its clients, such options start with --surprise prefix. One such example can be --surprise-server, you can look it up all in section "Partition Surprise" of help by using standard --help option to any Surprise client.

Such functionality is ensured by libpopt (automatically linked by calling SURPRISE_INIT macro from your "configure.in"). We include here only code samples appropriate for usage with Surprise. You should really read popt(3) manual page first, please.

Sample for non-Gnome (standard) client, stored in file "docs/sgml/popt-plain.c". This file will get generated by "cd docs/sgml;make popt-plain.c":


#include <stdlib.h>
#include <popt.h>

#include <surprise/lib.h> /* for SURPRISE_POPT_INCLUDE */

#define N_`'(x) x        /* I18N implementation missing here */
#define  _`'(x) x        /* I18N implementation missing here */
#define VERSION "0.1"  /* config.h missing here */

enum myPOPT {
        myPOPT_EMPTY /* prevent value 0 */,
        myPOPT_VERSION,

/* This "verbose" parameter is provided only as sample! */
        myPOPT_VERBOSE,

        };

static const struct poptOption popt_table[]={
        SURPRISE_POPT_INCLUDE,
                {
                        longName: "version",
                        shortName: 'V',
                        argInfo: POPT_ARG_NONE,
                        arg: NULL,
                        val: myPOPT_VERSION,
                        descrip: N_("Display version string"),
                        argDescrip: NULL
                },

/* This "verbose" parameter is provided only as sample! */
                {
                        longName: "verbose",
                        shortName: 'v',
                        argInfo: POPT_ARG_NONE,
                        arg: NULL,
                        val: myPOPT_VERBOSE,
                        descrip: N_("Increase verbosity by 1, maximum value is 99"),
                        argDescrip: NULL 
                },

        POPT_AUTOHELP { /* NULLs*/ }
        };

static int verbose=0;

/* Parse commandline options */
static void parse_options(int argcnt, const char **argstr)
{
poptContext context;
int val;

        context=poptGetContext("client_program_name"/*name*/,argcnt,argstr,popt_table,0/*flags*/);
        poptReadDefaultConfig(context,TRUE/*useEnv*/);
        while (-1/*proper end*/ != (enum myPOPT)(val=poptGetNextOpt(context)))
                switch (val) {
                        case myPOPT_VERSION:
                                printf(_("\
some program name - \"Partition Surprise client\" substring welcomed, version %s\n\
\tSome copyright, if preferred etc.\n\
"),VERSION);
                                exit(EXIT_SUCCESS);

/* This "verbose" parameter is provided only as sample! */
                        case myPOPT_VERBOSE:
                                if (++verbose>=99) {
                                        fprintf(stderr,_("%s: Too much verbosity!\n"),poptGetInvocationName(context));
                                        exit(EXIT_FAILURE);
                                        }
                                break;

                        default:
                                printf(_("Error on option %s: %s.\nRun '%s --help' to see a full list of available command line options.\n"),
                                        poptBadOption(context,0),poptStrerror(val),poptGetInvocationName(context));
                                exit(EXIT_FAILURE);
                        }
        poptFreeContext(context);
}

int main(int argc,char **argv)
{
  parse_options(argc,(const char **)argv);

/* This "verbose" parameter is provided only as sample! */
        printf("Verbosity: %d\n",verbose);

        return(EXIT_SUCCESS);
}

Sample for Gnome client, stored in file "docs/sgml/popt-gnome.c". This file will get generated by "cd docs/sgml;make popt-gnome.c":


#include <stdlib.h>
#include <popt.h> /* always include <popt.h> BEFORE <gnome.h> */
#include <gnome.h>

#include <surprise/lib.h> /* for SURPRISE_POPT_INCLUDE */

#define VERSION "0.1"  /* config.h missing here */

/* poptCallbackType popt_callback */
static void popt_callback(poptContext context,
                enum poptCallbackReason reason,
                const struct poptOption *opt,const char *arg,const void *data);

static const struct poptOption popt_table[]={
        SURPRISE_POPT_INCLUDE,
        { argInfo:POPT_ARG_CALLBACK, arg:(void *)popt_callback },
#define POPT_OFFSET 2

/* This "verbose" parameter is provided only as sample! */
                { /* corresponds to value '0' in switch/case below */
                        longName: "verbose",
                        shortName: 'v',
                        argInfo: POPT_ARG_NONE,
                        arg: NULL,
                        val: 0,
                        descrip: N_("Increase verbosity by 1, maximum value is 99"),
                        argDescrip: NULL 
                },

        { /* NULLs*/ } /* POPT_AUTOHELP _not_ included as we use Gnome! */
        };

/* This "verbose" parameter is provided only as sample! */
static int verbose=0;

static void popt_callback(poptContext context,
                enum poptCallbackReason reason,
                const struct poptOption *opt,const char *arg,const void *data)
{
        switch (opt-(popt_table+POPT_OFFSET)) {

/* This "verbose" parameter is provided only as sample! */
                case 0:
                        if (++verbose>=99) {
                                fprintf(stderr,_("%s: Too much verbosity!\n"),poptGetInvocationName(context));
                                exit(EXIT_FAILURE);
                                }
                        break;
                }
}

int main(int argc,char **argv)
{
        gnome_init_with_popt_table("client_program_name"/*app_id*/,VERSION/*app_version*/,
                        argc,argv,popt_table,0/*flags*/,NULL/*return_ctx*/);

/* This "verbose" parameter is provided only as sample! */
        printf("Verbosity: %d\n",verbose);

        return(EXIT_SUCCESS);
}

Displaying client and library version/revision

This issue was touched a bit in popt code samples above. You will have to differentiate between clients and library versions. In surpise package it is a bit messy as the clients share with library the same version/revision (as they have common sources/repository).

As authors of third-party clients you should know only the following three variables:

surprise_version

String with the version of the library

surprise_revision

Number representing the revision of the library

surprise_about

Localized string containing surprise_version, surprise_revision and copyright information. Don't touch this string before you call poptGetContext() or gnome_init_with_popt_table() otherwise this string will not yet be initialized!

Any use of VERSION symbol in your client will represent the version of the client (as in normal case) without any relations to Surprise library!

Don't bother with displaying library version during standard --version or -V command-line option, this will be done automatically by popt mechanism. On the other hand if you want to display some version information during the run of aplication (as in some "About..." box etc.), you should display surprise_about string and only this string (for Surprise).

Don't look at cmdline, curses or Gnome client sources supplied in Surprise package - they are not a goot example of versioning stuff for you.

To be more specific: During compilation of libsurprise will surprise_version get value of Surprise VERSION, surprise_revision the value of SURPRISE_REVISION (from "revision.h").


Next Previous Contents