⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usedir.c

📁 sybase数据库ct library的开发,使用了所以有函数
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
**  usedir.c -- Demonstrates how to use Client-Library to query the
**   directory service for available servers.
**
**   This program searches for Sybase server entries in the directory,
**   prints a description of each entry found, and lets the user choose
**   a server to connect to.
**
** Inputs
** -------
**   None. The program relies on the directory driver configuration
**   to specify the directory source and the subtree (DIT-Base) to
**   search.
**
**   If no directory driver is configured, the SYBASE interfaces file
**   (or SQL.INI file for Windows and OS/2 machines) is searched.
**   Directory drivers are configured in the driver configuration
**   file (libtcl.cfg in the main Sybase installation directory).
**
**   The username and password defined in example.h are used to
**   connect to the chosen server.
**
** Outputs
** -------
**   Displays each server's information until the user picks a server to
**   connect to.
**
** Routines Used
** -------------
**   ct_ds_dropobj
**   ct_ds_lookup
**   ct_ds_objinfo
**   ct_callback
**   ct_con_alloc, ct_con_drop
**   ct_con_props
*/

/*
** C Standard libraries.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

/*
** Include the Client-Library header file.
*/
#include <ctpublic.h>

/*
** Example header files.
**  - example.h defines the user name, the password, and some global
**     macros.
**  - exutils.h prototypes the exutils.c utility routines. Any routine
**    called here that begins with ex_ is defined in exutils.c
*/
#include "example.h"
#include "exutils.h"

/*
** Global data and structures.
*/

/*
** Login property values for connecting to the server.
*/
CS_STATIC CS_CHAR  *Ex_appname = "Directory search example";
CS_STATIC CS_CHAR  *Ex_user = EX_USERNAME;
CS_STATIC CS_CHAR  *Ex_password = EX_PASSWORD;

/*
** AttributesToDisplay is a read-only static array used by
** the show_server_info() function. It contains the Object
** Identifier (OID) strings for the server attributes to
** display, in the order that they are to be displayed.
*/
typedef struct
{
	CS_CHAR             type_string[CS_MAX_DS_STRING];
	CS_CHAR             english_name[CS_MAX_DS_STRING];
} AttrForDisplay;

#define N_ATTRIBUTES 7
CS_STATIC AttrForDisplay AttributesToDisplay[N_ATTRIBUTES + 1] =
{
	{CS_OID_ATTRSERVNAME, "Server name"},
	{CS_OID_ATTRSERVICE, "Service type"},
	{CS_OID_ATTRVERSION, "Server entry version"},
	{CS_OID_ATTRSTATUS, "Server status"},
	{CS_OID_ATTRADDRESS, "Network addresses"},
	{CS_OID_ATTRRETRYCOUNT, "Connection retry count"},
	{CS_OID_ATTRLOOPDELAY, "Connection retry loop delay"},
	{"", ""}
};

/*
** (SERVER_INFO_LIST *) is the abstract data type that we use
** to collect a list of servers from the directory. The sil_
** routines operate on the list type.
*/
#define MAX_SERVER_LIST 256
typedef struct _server_info
{
	CS_DS_OBJECT       *object;
} SERVER_INFO;
typedef struct _server_info_list
{
	SERVER_INFO        *servers;	/* Array of size MAX_SERVER_LIST */
	CS_INT              len;/* Current length of list        */
} SERVER_INFO_LIST;

/*
** Private defines.
*/
#define STRLEN(s)  ((s) == NULL ? 0 : strlen(s))
#define CHOOSE_SERVER_MAX_INPUT 128

/*
** Private prototypes.
*/
CS_RETCODE provider_setup PROTOTYPE((
    CS_CONNECTION *conn
    ));
CS_RETCODE get_servers PROTOTYPE((
    CS_CONNECTION *conn,
    SERVER_INFO_LIST **servers
    ));
CS_RETCODE CS_PUBLIC directory_cb PROTOTYPE((
    CS_CONNECTION *conn,
    CS_INT reqid,
    CS_RETCODE status,
    CS_INT numentries,
    CS_DS_OBJECT *ds_object,
    CS_VOID *userdata
    ));
CS_RETCODE choose_server PROTOTYPE((
    CS_CONNECTION *conn,
    SERVER_INFO_LIST *slp,
    CS_CHAR server_name [],
    CS_INT buflen,
    CS_INT *outlen
    ));
CS_RETCODE show_server_info PROTOTYPE((
    CS_DS_OBJECT *ds_object,
    FILE *outfile
    ));
CS_RETCODE attr_get_by_type PROTOTYPE((
    CS_DS_OBJECT *ds_object,
    CS_CHAR *attr_type_str,
    CS_ATTRIBUTE *attr_metadata,
    CS_ATTRVALUE **p_attrvals
    ));
CS_RETCODE attr_display_values PROTOTYPE((
    CS_ATTRIBUTE *attr_meta,
    CS_ATTRVALUE attr_vals[],
    FILE *outfile
    ));
CS_RETCODE attr_val_as_string PROTOTYPE((
    CS_ATTRIBUTE *attr_metadata,
    CS_ATTRVALUE *val,
    CS_CHAR *buf,
    CS_INT buflen,
    CS_INT *outlen
    ));
CS_RETCODE attr_enum_english_name PROTOTYPE((
    CS_INT enum_val,
    CS_OID *attr_type,
    CS_CHAR *buffer,
    CS_INT buflen,
    CS_INT *outlen
    ));
int match_OID       PROTOTYPE((
    CS_OID *oid,
    CS_CHAR *oid_string
    ));
CS_RETCODE sil_init_list PROTOTYPE((
    SERVER_INFO_LIST **slp
    ));
CS_RETCODE sil_drop_list PROTOTYPE((
    CS_CONNECTION *conn,
    SERVER_INFO_LIST *slp
    ));
CS_RETCODE sil_add_object PROTOTYPE((
    SERVER_INFO_LIST *slp,
    CS_DS_OBJECT *ds_object
    ));
CS_RETCODE sil_extract_object PROTOTYPE((
    SERVER_INFO_LIST *slp,
    CS_INT number,
    CS_DS_OBJECT **p_dsobject
    ));
CS_INT sil_list_len PROTOTYPE((
    SERVER_INFO_LIST *slp
    ));

/*
** main() -- Entry point for our program.
*/
int
main()
{
	CS_RETCODE          ret;
	CS_CONTEXT         *ctx;
	CS_CONNECTION      *conn1;
	CS_CONNECTION      *conn2;
	SERVER_INFO_LIST   *servers;
	CS_CHAR             server_name[512];

        EX_SCREEN_INIT();

	/*
	** Initialize CS-Library and Client-Library.
	*/
	ret = ex_init(&ctx);
	if (ret != CS_SUCCEED)
	{
		ex_panic("Initialization failed.");
	}

	/*
	** Allocate a connection structure. We need it to query the
	** directory.
	*/
	ret = ct_con_alloc(ctx, &conn1);
	if (ret != CS_SUCCEED)
	{
		ex_panic("ct_con_alloc() failed.");
	}

	/*
	** Get a list of available servers.
	*/
	ret = get_servers(conn1, &servers);
	if (ret != CS_SUCCEED)
	{
		ex_panic("get_servers() failed.");
	}

	/*
	** Let the user choose a server and attempt a connection to it.
	*/
	ret = choose_server(conn1, servers, server_name, 512, NULL);
	if (ret != 0)
	{

		/*
		** User chose to quit, or an error occurred. In either
		** case, clean up and exit.
		*/
		fprintf(stdout, "Exiting.\n");
		(CS_VOID)sil_drop_list(conn1, servers);
		ret = ct_con_drop(conn1);
		ret = ex_ctx_cleanup(ctx, ret);
		exit(ret == 1 ? EX_EXIT_SUCCEED : EX_EXIT_FAIL);
	}

	/*
	** Connect to the chosen server. We could do this with the same
	** connection, that we used to query the directory. We don't do
	** that here because ex_connect() won't use a pre-allocated
	** connection.
	*/
	fprintf(stdout, "Connecting to %s ...\n", server_name);
	ret = ex_connect(ctx, &conn2, Ex_appname, Ex_user, Ex_password, 
			 server_name);
	if (ret != CS_SUCCEED)
	{
		ex_panic("Connect attempt failed.");
	}

	/*
	** Drop the list of servers.
	*/
	ret = sil_drop_list(conn1, servers);
	if (ret != CS_SUCCEED)
	{
		ex_panic("sil_drop_list() failed.");
	}

	/*
	** Clean up Client-Library and drop the CS_CONTEXT. We can't use
	** ex_con_cleanup() on conn1 because it's not open.
	*/
	ret = ct_con_drop(conn1);
	if (ret != CS_SUCCEED)
	{
		ex_error("Cleanup of connection 1 failed.");
	}
	ret = ex_con_cleanup(conn2, ret);
	if (ret != CS_SUCCEED)
	{
		ex_error("Cleanup of connection 2 failed.");
	}
	ret = ex_ctx_cleanup(ctx, ret);
	if (ret != CS_SUCCEED)
	{
		ex_error("Context-level cleanup failed.");
	}

	exit(EX_EXIT_SUCCEED);

} /* main() */

/*
** get_servers() -- Query the directory for servers and
**    get a list of directory objects that contain details
**    for each.
**
** Parameters
**   conn -- Pointer to allocated connection structure.
**   pserver_list -- Address of a pointer to a SERVER_INFO_LIST.
**       Upon successful return, the list will be initialized
**       and contain an object for each server found in the
**       search.
**
**       NOTE: The caller must clean up the list with sil_drop_list()
**       when done with it.
**
** Returns
**   CS_SUCCEED or CS_FAIL.
*/
CS_RETCODE
get_servers(conn, pserver_list)
CS_CONNECTION      *conn;
SERVER_INFO_LIST  **pserver_list;
{
	CS_RETCODE          ret;
	CS_INT              reqid;
	CS_VOID            *oldcallback;
	CS_OID              oid;
	CS_DS_LOOKUP_INFO   lookup_info;

	/*
	** Steps for synchronous-mode directory searches:
	** 
	** 1. If necessary, initialize application specific data structures
	**    (Our application collects directory objects in *pserver_list).
	** 2. Save the old directory callback and install our own (the
	**    directory_cb function, found below).
        ** 3. (Optional -- Network based directories only) 
        **    Set the base node in the directory to search beneath 
	**    (CS_DS_DITBASE property). 
        ** 4. Call ct_ds_lookup to begin the search, passing
	**    any application specific data structures as the userdata
	**    argument. 
        ** 5. Client-Library invokes our callback once for each
	**    found object. directory_cb() inserts each directory 
        **    object to the list of servers. 
        ** 6. Check the return status of ct_ds_lookup. 
        ** 7. Restore callbacks and properties
	**    that we changed.
	*/

	/*
	** Step 1. Initialize the data structure (*pserver_list).
	*/
	ret = sil_init_list(pserver_list);
	if (ret != CS_SUCCEED || (*pserver_list) == NULL)
	{
		ex_error("get_servers: Could not initialize list.");
		return CS_FAIL;
	}

	/*
	** Step 2. Save the old directory callback and install our own
	** callback, directory_cb(), to receive the found objects.
	*/
	ret = ct_callback(NULL, conn, CS_GET,
			  CS_DS_LOOKUP_CB, &oldcallback);
	if (ret == CS_SUCCEED)
	{
		ret = ct_callback(NULL, conn, CS_SET,
			       CS_DS_LOOKUP_CB, (CS_VOID *)directory_cb);
	}
	if (ret != CS_SUCCEED)
	{
		ex_error("get_servers: Could not install directory callback.");
		return CS_FAIL;
	}

	/*
	** Step 3. Set the base node in the directory to search beneath
	** (the CS_DS_DITBASE connection property).
	*/

	ret = provider_setup(conn);
	if (ret != CS_SUCCEED)
	{
		ex_error("get_servers: Provider-specific setup failed.");
		return CS_FAIL;
	}

	/*
	** Step 4. Call ct_ds_lookup to begin the search, passing the
	** server list pointer as userdata. Step 5. Client-Library invokes
	** our callback once for each found object (or once to report that
	** no objects were found). Our callback, directory_cb, will
	** receives a pointer to each found server object and appends it
	** to the list. Step 6. Check the return status of ct_ds_lookup.
	*/

	/*
	** Set the CS_DS_LOOKUP_INFO structure fields.
	*/
	lookup_info.path = NULL;
	lookup_info.pathlen = 0;
	lookup_info.attrfilter = NULL;
	lookup_info.attrselect = NULL;

	strcpy(oid.oid_buffer, CS_OID_OBJSERVER);
	oid.oid_length = STRLEN(oid.oid_buffer);
	lookup_info.objclass = &oid;

	/*
	** Begin the search.
	*/
	ret = ct_ds_lookup(conn, CS_SET, &reqid,
			   &lookup_info, (CS_VOID *)pserver_list);
	if (ret != CS_SUCCEED)
	{
		ex_error("get_servers: Could not run search.");
		return CS_FAIL;
	}

	/*
	** Step 7.  Restore callbacks and properties that we changed.
	*/
	ret = ct_callback(NULL, conn, CS_SET,
			  CS_DS_LOOKUP_CB, oldcallback);
	if (ret != CS_SUCCEED)
	{
		ex_error("get_servers: Could not restore directory callback.");
		return CS_FAIL;
	}

	return CS_SUCCEED;

} /* get_servers() */

/*
** directory_cb() -- Directory callback to install in Client-Library.
**   When we call ct_ds_lookup(), Client-Library calls this function
**   once for each object that is found in the search.
**
**   This particular callback collects the objects in
**   the SERVER_INFO_LIST that is received as userdata.
**
** Parameters
**   conn -- The connection handle passed to ct_ds_lookup() to
**      begin the search.
**   reqid -- The request id for the operation (assigned by Client-Library).
**   status -- CS_SUCCEED when search succeeded (ds_object is valid).
**      CS_FAIL if the search failed (ds_object is not valid).
**   numentries -- The count of objects to be returned for the
**      search. Includes the current object. Can be 0 if search
**      failed.
**   ds_object -- Pointer to a CS_DS_OBJECT structure. Will
**      be NULL if the search failed.
**   userdata -- The address of user-allocated data that was
**      passed to ct_ds_lookup().
**
**      This particular callback requires userdata to be the
**      address of a valid, initialized SERVER_INFO_LIST pointer.
**      (SERVER_INFO_LIST is an application data structure defined
**      by this sample).
**
** Returns
**   CS_CONTINUE unless the SERVER_INFO_LIST pointed at by userdata fills
**     up, then CS_SUCCEED to truncate the search results.
*/
CS_RETCODE          CS_PUBLIC
directory_cb(conn, reqid, status, numentries, ds_object, userdata)
CS_CONNECTION      *conn;
CS_INT              reqid;
CS_RETCODE          status;
CS_INT              numentries;
CS_DS_OBJECT       *ds_object;
CS_VOID            *userdata;
{
	CS_RETCODE          ret;
	SERVER_INFO_LIST   *server_list;

	if (status != CS_SUCCEED 
	    || numentries <= 0
	    || ds_object == (CS_DS_OBJECT *)NULL)
	{
		return CS_SUCCEED;
	}

	/*
	** Append the object to the list of servers.
	*/
	server_list = *((SERVER_INFO_LIST **)userdata);
	ret = sil_add_object(server_list, ds_object);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -