示例: TI-RPC 顶级服务 API

此代码示例说明了用于开发 TI-RPC 服务的顶级服务 API。

服务的开发在顶层更为复杂,因为它需要开发者编写调度例程。 在此级别,当服务请求进入时,将调用分派例程。 分派例程必须收集参数并调用正确的本地过程,捕获所有错误和结果,然后将该信息返回给客户机。 编写分派函数后,只需稍作修改即可轻松复制该函数并将其用于其他服务。

顶部,中间和专家层可以使用相同的分派功能而无需修改。 在以下示例中,分派函数与此文件中的其他本地函数捆绑在一起。 在服务运行之前,需要将这两个文件编译并链接在一起。 与其他层相比,顶级的优势在于能够将 NETTYPE 指定为字符串,而不是使用网络选择 API。 调用顶级 API 后,将创建服务,将其绑定到分派函数,并向 rpcbind 服务注册。

注: 通过使用代码示例,您同意 代码许可证和免责声明信息的条款。
#include <stdio.h>
#include <netconfig.h>
#include <rpc/rpc.h>
#include <errno.h>
#include "myapp.h"
int main(int argc, char *argv[]) {

	int num_svc; /* return value for the svc_create() API */

	/* unregister any existing copy of this service */
	/* (void)svc_unreg(program, version) */
	svc_unreg(PROGNUM, VERSNUM);

	/* (int)svc_create(dispatch, prognum, versnum, nettype); */
	num_svc = svc_create(myapp_dispatch, PROGNUM, VERSNUM, NETTYPE);

	/* check for errors calling svc_create() */
	if (num_svc == 0) {
		/* print error messages and exit */
		fprintf(stderr, "Error calling %s.\n", "svc_create");
		fprintf(stderr, "PROG: %lu\nVERS: %lu\tNET: %s\n", 
				PROGNUM, VERSNUM, NETTYPE);
		fprintf(stderr, "errno: %d\n", errno);
		return 1;
		}

	/* this should loop indefinitely waiting for client connections */
	svc_run();

	/* if we get here, svc_run() returned */
	fprintf(stderr, "svc_run() returned.  ERROR has occurred.\n");
	fprintf(stderr, "errno: %d\n", errno);

	/* clean up by unregistering.  then, exit */
	svc_unreg(PROGNUM, VERSNUM);

	return 1;

} /* end of main() */
/* This is an example of the dispatch function */
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <pwd.h>
#include <rpc/rpc.h>
#include <time.h>
#include "myapp.h"

char * myapp_get_uid(char *in) {

	u_int retval;              /* return value for this procedure() */
	struct stat sbuf;          /* data storage area for stat() */
	int stat_ret;              /* return value for stat() */
	char *file = *(char **)in; /* input value for stat() */

	/* (int)stat(filename, struct stat *) */
	stat_ret = stat(file, &sbuf);

	if (stat_ret == -1) {
		retval = (u_int)-1;
		}
	else {
		retval = (u_int)(sbuf.st_uid);
		}

	return (char *)&retval;
}

char *myapp_get_uid_string(char *in) {

	char *retval;              /* return value for this procedure() */
	struct passwd *pbuf;       /* return value for getpwuid() */
	struct stat sbuf;          /* data storage area for stat() */
	int stat_ret;              /* return value for stat() */
	char *file = *(char **)in; /* input value for stat() */

	/* (int)stat(filename, struct stat *) */
	stat_ret = stat(file, &sbuf);

	if (stat_ret == -1) {
		retval = (char *)NULL;
		}
	else {

		pbuf = (struct passwd *)getpwuid((uid_t)(sbuf.st_uid));

		if (pbuf == NULL) {
			retval = (char *)NULL;
			}
		else {
			retval = (char *)(pbuf->pw_name);
			}
		}

	return (char *)&retval;
}

char * myapp_get_size(char *in) {

	int retval;                /* return value for this procedure() */
	struct stat sbuf;          /* data storage area for stat() */
	int stat_ret;              /* return value for stat() */
	char *file = *(char **)in; /* input value for stat() */

	/* (int)stat(filename, struct stat *) */
	stat_ret = stat(file, &sbuf);

	if (stat_ret == -1) {
		retval = (int)-1;
		}
	else {
		retval = (int)(sbuf.st_size);
		}

	return (char *)&retval;
}

char * myapp_get_mtime(char *in) {

	long retval;               /* return value for this procedure() */
	struct stat sbuf;          /* data storage area for stat() */
	int stat_ret;              /* return value for stat() */
	char *file = *(char **)in; /* input value for stat() */

	/* (int)stat(filename, struct stat *) */
	stat_ret = stat(file, &sbuf);

	if (stat_ret == -1) {
		retval = (long)-1;
		}
	else {
		retval = (long)(sbuf.st_mtime);
		}

	return (char *)&retval;

}
		
char *myapp_get_mtime_string(char *in) {

	char *retval;              /* return value for this procedure() */
	struct stat sbuf;          /* data storage area for stat() */
	int stat_ret;              /* return value for stat() */
	char *file = *(char **)in; /* input value for stat() */

	/* (int)stat(filename, struct stat *) */
	stat_ret = stat(file, &sbuf);

	if (stat_ret == -1) {
		retval = (char *)NULL;
		}

	else {
		retval = (char *)ctime((time_t *)&(sbuf.st_mtime));
		}

	return (char *)&retval;
}

char * myapp_get_codepage(char *in) {

	u_short retval;            /* return value for this procedure() */
	struct stat sbuf;          /* data storage area for stat() */
	int stat_ret;              /* return value for stat() */
	char *file = *(char **)in; /* input value for stat() */

	stat_ret = stat(file, &sbuf);

	if (stat_ret == -1) {
		retval = (u_short)-1;
	}
	
	else {
		retval = (u_short)(sbuf.st_codepage);
	}

	return (char *)&retval;
}


char *myapp_get_objtype(char *in) {

	char *retval;              /* return value for this procedure() */
	struct stat sbuf;          /* data storage area for stat() */
	int stat_ret;              /* return value for stat() */
	char *file = *(char **)in; /* input value for stat() */

	/* (int)stat(filename, struct stat *) */
	stat_ret = stat(file, &sbuf);

	if (stat_ret == -1) {
		retval = (char *)NULL;
	}
	
	else {
		retval = (char *)(sbuf.st_objtype);
	}

	return (char *)&retval;

}

char *myapp_get_filetype(char *in) {

	char *result = NULL;       /* return value for this procedure() */
	struct stat sbuf;          /* data storage area for stat() */
	int stat_ret;              /* return value for stat() */
	char *file = *(char **)in; /* input value for stat() */

	/* (int)stat(filename, struct stat *) */
	stat_ret = stat(file, &sbuf);

	if (stat_ret == -1) {
		return (char *)NULL;
		}
	
	if (S_ISDIR(sbuf.st_mode)) {
		result = "Directory";
		}

	if (S_ISREG(sbuf.st_mode)) {
		result = "Regulare File";
		}

	if (S_ISLNK(sbuf.st_mode)) {
		result = "Symbolic Link";
		}

	if (S_ISSOCK(sbuf.st_mode)) {
		result = "Socket";
		}

	if (S_ISNATIVE(sbuf.st_mode)) {
		result = "System i Native Object";
		}

	if (S_ISFIFO(sbuf.st_mode)) {
		result = "FIFO";
		}

	if (S_ISCHR(sbuf.st_mode)) {
		result = "Character Special";
		}

	if (S_ISBLK(sbuf.st_mode)) {
		result = "Block Special";
		}

	return (char *)&result;

}

char * myapp_end_server(char *empty) {

	/* char *empty is not used      */
	/* function always returns NULL */

	svc_unreg(PROGNUM, VERSNUM);
	
	return (char *)NULL;

}
	
void myapp_dispatch(struct svc_req *request, SVCXPRT *svc) {

	union {
		/* all of the procedures take a string */
		/* if there were other procedures, it */
		/* might look like this:              */
		/* int set_codepage_arg               */
		char *  filename_arg;
	} argument;

	char *result;            /* pointer to returned data from proc */
	xdrproc_t xdr_argument;  /* decodes data from client call */
	xdrproc_t xdr_result;    /* encodes data to return to client */
	char *(*proc)(char *);   /* pointer to local procedure to call */

	switch (request->rq_proc) {
	
		case NULLPROC:
			/* a special case.  always return void */
                        (void)svc_sendreply((SVCXPRT *)svc, 
                                            (xdrproc_t)xdr_void, 
                                            (char *)NULL);
			return;

		case GET_UID:
			/* takes a string argument (filename) */
			/* returns an u_int (uid of file ownder) */
			xdr_argument = xdr_wrapstring;
			xdr_result   = xdr_u_int;
			proc         = (char *(*)(char *))myapp_get_uid;
			break;

		case GET_UID_STRING:
			/* takes a string argument (filename) */
			/* returns a string (owner's name in string format) */
			xdr_argument = xdr_wrapstring;
			xdr_result   = xdr_wrapstring;
			proc         = (char *(*)(char *))myapp_get_uid_string;
			break;

		case GET_SIZE:
			/* takes a string argument (filename) */
			/* returns an int (size of file in bytes) */
			xdr_argument = xdr_wrapstring;
			xdr_result   = xdr_int;
			proc         = (char *(*)(char *))myapp_get_size;
			break;

		case GET_MTIME:
			/* takes a string argument (filename) */
			/* returns a long (time last modified) */
			xdr_argument = xdr_wrapstring;
			xdr_result   = xdr_long;
			proc         = (char *(*)(char *))myapp_get_mtime;
			break;

		case GET_MTIME_STRING:
			/* takes a string argument (filename) */
			/* returns a string (time last modified, string format) */
			xdr_argument = xdr_wrapstring;
			xdr_result   = xdr_wrapstring;
			proc         = (char *(*)(char *))myapp_get_mtime_string;
			break;

		case GET_CODEPAGE:
			/* takes a string argument (filename) */
			/* returns an u_short (codepage of file) */
			xdr_argument = xdr_wrapstring;
			xdr_result   = xdr_u_short;
			proc         = (char *(*)(char *))myapp_get_codepage;
			break;

		case GET_OBJTYPE:
			/* takes a string argument (filename) */
			/* returns a string (object type) */
			xdr_argument = xdr_wrapstring;
			xdr_result   = xdr_wrapstring;
			proc         = (char *(*)(char *))myapp_get_objtype;
			break;

		case GET_FILETYPE:
			/* takes a string argument (filename) */
			/* returns a string (file type) */
			xdr_argument = xdr_wrapstring;
			xdr_result   = xdr_wrapstring;
			proc         = (char *(*)(char *))myapp_get_filetype;
			break;

		case END_SERVER:
			/* takes no arguments */
			/* returns no data */
			/* unregisters service with local rpcbind daemon */
			xdr_argument = (xdrproc_t)xdr_void;
			xdr_result   = (xdrproc_t)xdr_void;
			proc         = (char *(*)(char *))myapp_end_server;
			break;
		
		default:
			/* fall through case.  return error to client */
			svcerr_noproc(svc);
			return;

	} /* end switch(request->rq_proc) */


	/* clear the argument */
	memset((char *)&argument, (int)0, sizeof(argument));

	/* decode argument from client using xdr_argument() */
	if (svc_getargs(svc, xdr_argument, (char *)&argument) == FALSE) {
		/* if svc_getargs() fails, return RPC_CANTDECODEARGS to client */
		svcerr_decode(svc);
		return;
	}

	/* call local procedure, passing in pointer to argument */
	result = (char *)(*proc)((char *)&argument);

	/* check first that result isn't NULL */
	/* try to send results back to client.  check for failure */
	if ((result != NULL) && (svc_sendreply(svc, xdr_result, result) == FALSE))
{
		/* send error message back to client */
		svcerr_systemerr(svc);
	}

	/* free the decoded argument's space */
	if (svc_freeargs(svc, xdr_argument, (char *)&argument) == FALSE) {
		/* if unable to free, print error and exit */
		(void)fprintf(stderr, "unable to free arguments\n");
		exit(1);
	}

} /* end of myapp_dispatch() */