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

📄 sel_svc.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *	Give_holder: clients ask for a holder for the service as they start up */static voidseln_svc_give_holder(transport)     SVCXPRT            *transport; {     Seln_holder	 hold;     hold.rank = SELN_UNKNOWN;     hold.state = SELN_NONE;     hold.access = clients.access;     (void) svc_sendreply(transport, xdr_seln_holder,      	(char *)(LINT_CAST(&hold))); }  /*	Procedures by which the service resonds to requests about *	files it's acting as the holder of *//*	seln_svc_do_function: respond to a function-key release when *		service holds a file as a selection or shelf. *//*ARGSUSED*/static voidseln_svc_do_function(private, buffer)    caddr_t               private;    Seln_function_buffer *buffer;{    Seln_holder          **hold = NULL;    if (seln_figure_response(buffer, hold) != SELN_IGNORE) {	complain("Service asked to to perform meaningless operation on a file-selection?"		 );    }}/*	seln_svc_do_reply: respond to a request concerning a selection *		for which selection service holds a file. */static Seln_resultseln_svc_do_reply(item, context, len)    Seln_attribute        item;    Seln_replier_data    *context;    int                   len;{    struct stat           stat_buf;    int                   fd, count, size;    char                 *destp;    extern long lseek();    if ((int) item >= ord(SELN_TRACE_ACQUIRE) &&	(int) item <= ord(SELN_TRACE_DUMP)) {	*context->response_pointer++ =	    (char *) seln_svc_debug(item, (u_int)(LINT_CAST(	    	*context->request_pointer)));	return SELN_SUCCESS;    }    if ((int) item == SELN_SET_NOTIFY_SUPPRESSION     ||	(int) item == SELN_GET_NOTIFY_SUPPRESSION) {	*context->response_pointer++ =	    seln_svc_notify_suppression(item,			    (u_int)(LINT_CAST(*context->request_pointer)));	return SELN_SUCCESS;    }    if (holder[ord(context->rank)].state != SELN_FILE) {	return SELN_DIDNT_HAVE;    }    fd = held_file[ord(context->rank)];    if (fstat(fd, &stat_buf) != 0) {	perror("Selection service couldn't reply about a file");	return SELN_FAILED;    }    if (context->context == 0) {	if (lseek(fd, 0L, 0) == (long)-1) {	    perror("Selection service couldn't reset to start of file");	    return SELN_FAILED;	}    }    switch (item) {      case SELN_REQ_BYTESIZE:	*context->response_pointer++ = (char *) stat_buf.st_size;	return SELN_SUCCESS;      case SELN_REQ_CONTENTS_ASCII:	size = stat_buf.st_size - (int) context->context;	if (size > len) {	    count = read(fd,(char *)(LINT_CAST(context->response_pointer)), len);	    if (count != len) {		goto terminate_buffer;	    }	    context->response_pointer =  (char **) (LINT_CAST(		((char *) (LINT_CAST(context->response_pointer)) + count)));	    context->context += count;	    return SELN_CONTINUED;	} else {	    count = read(fd,(char*)(LINT_CAST(context->response_pointer)), size);	terminate_buffer:	    destp = (char *) context->response_pointer;	    destp += count;	    while ((int) destp % 4 != 0) {		*destp++ = '\0';	    }	    context->response_pointer = (char **) (LINT_CAST(destp));	    *context->response_pointer++ = (char *) 0;	    return SELN_SUCCESS;	}      case SELN_REQ_YIELD:	*context->response_pointer++ =	    (char *) seln_svc_do_yield(context->rank);	return SELN_SUCCESS;      case SELN_REQ_END_REQUEST:	return SELN_SUCCESS;      default:	return SELN_UNRECOGNIZED;    }}/*	seln_svc_do_yield: respond to a yield request when *		service holds a file as a selection or shelf. */static Seln_resultseln_svc_do_yield(input)    Seln_rank             input;{    Seln_result		  result;    if (trace_yield) {	(void)fprintf(stderr, "Service told to yield ");	seln_dump_rank(stderr, &input);	(void)fprintf(stderr, " selection.\n");    }    if (ord(input) < ord(SELN_PRIMARY) || ord(input) > ord(SELN_SHELF) ||	    holder[ord(input)].state != SELN_FILE) {	    result = SELN_DIDNT_HAVE;    } else if (seln_function_pending && ord(input) == ord(SELN_PRIMARY)) {	    result = SELN_WRONG_RANK;    } else {    /* reset state, but not access, to preserve the fact that		 * this selection was made */	holder[ord(input)].state = SELN_NONE;	(void)close(held_file[ord(input)]);	held_file[ord(input)] = 0;	    result = SELN_SUCCESS;    }    if (trace_yield) {	(void)fprintf(stderr, "Service yield returns ");	seln_dump_result(stderr, &result);	(void)fprintf(stderr, "\n");    }    return result;}/* *	Init_access:  fill in the service_access struct so we can *	respond to requests for file-selections. */static voidseln_svc_init_access(access)    Seln_access		 *access;{    if ((seln_my_udp_transport = svcudp_bufcreate(RPC_ANYSOCK,					SELN_RPC_BUFSIZE, SELN_RPC_BUFSIZE))	== (SVCXPRT *) NULL) {	perror("selection_service");	(void)fprintf(stderr, "Couldn't start selection service.\n");	return;    }    seln_my_udp_socket = seln_my_udp_transport->xp_sock;    (void) seln_svc_unmap();    if (!svc_register(seln_my_udp_transport, seln_svc_program, SELN_VERSION,		      seln_svc_dispatch, IPPROTO_UDP)) {	perror("selection_service");	(void)fprintf(stderr, "Couldn't start selection service.\n");	(void)close(seln_my_udp_socket);	svc_destroy(seln_my_udp_transport);	return;    }    access->pid = getpid();    access->program = seln_svc_program;    get_myaddress(&access->udp_address);    access->udp_address.sin_port = htons(seln_my_udp_transport->xp_port);    access->client = (caddr_t) &clients;    old_func = notify_set_input_func((Notify_client) seln_my_udp_transport,				     seln_listener, seln_my_udp_socket);    if (seln_get_tcp(seln_svc_program, seln_svc_dispatch) != SELN_SUCCESS) {	(void)close(seln_my_udp_socket);	svc_destroy(seln_my_udp_transport);	return;    }    access->tcp_address = access->udp_address;    access->tcp_address.sin_port = htons(seln_my_tcp_transport->xp_port);}/* *	Tell holders of data selections that a function key has gone up, *	 & who they should contact about it.  This routine returns the *	 buffer (and doesn't send it to the informing client) to prevent *	 race where the informer might get a button click between informing *	 the service and getting its notification.  This way, it acts on the *	 return value from seln_inform, before going back to the notifier. */static Seln_function_bufferseln_execute_fn(args)    Seln_inform_args *args;{    static Seln_rank informer;    Seln_function_buffer buffer;    buffer.function = args->function;    buffer.caret = holder[ord(SELN_CARET)];    buffer.primary = holder[ord(SELN_PRIMARY)];    buffer.secondary = holder[ord(SELN_SECONDARY)];    buffer.shelf = holder[ord(SELN_SHELF)];    informer = SELN_UNKNOWN;    if (!full_notifications) {	/* New style: 1 notification  */	register Seln_rank recipient;	switch (args->function) {	  case SELN_FN_GET:	  case SELN_FN_FIND:	    recipient = SELN_CARET;	    break;	  case SELN_FN_PUT:	  case SELN_FN_DELETE:	    if (buffer.secondary.state == SELN_EXISTS) {		recipient = SELN_SECONDARY;	    } else {		recipient = SELN_PRIMARY;	    }	    break;	  default:	    return seln_null_function;	}	if (holder[ord(recipient)].state != SELN_EXISTS)	    return seln_null_function;	/*  if the informer is the intended recipient, tell him in the	 *  return value.  Otherwise, send a notification and give the	 *  informer a no-op return.	 */	if (seln_equal_access(&args->holder.access,			      &holder[ord(recipient)].access)) {	    buffer.addressee_rank = recipient;	    return buffer;	} else {	    (void) seln_send_msg(recipient, &buffer);	    return seln_null_function;	}    }     else {			/* Old style: 1 - 4 notifications  */	if (holder[ord(SELN_CARET)].state != SELN_NONE) {	    if (seln_equal_access(&args->holder.access, &buffer.caret.access)) {		informer = SELN_CARET;	    } else {		if (seln_send_msg(SELN_CARET, &buffer) != SELN_SUCCESS) {		    return seln_null_function;		}	    }	}	if (holder[ord(SELN_PRIMARY)].state != SELN_NONE	    && !seln_equal_access(&buffer.primary.access,				  &buffer.caret.access)) {	    if (seln_equal_access(&args->holder.access,				  &buffer.primary.access)) {		informer = SELN_PRIMARY;	    } else {		if (seln_send_msg(SELN_PRIMARY, &buffer) != SELN_SUCCESS) {		    return seln_null_function;		}	    }	}	if (holder[ord(SELN_SECONDARY)].state != SELN_NONE	    && !seln_equal_access(&buffer.secondary.access,				  &buffer.caret.access)	    && !seln_equal_access(&buffer.secondary.access,				  &buffer.primary.access)) {	    if (seln_equal_access(&args->holder.access,				  &buffer.secondary.access)) {		informer = SELN_SECONDARY;	    } else {		if (seln_send_msg(SELN_SECONDARY, &buffer) != SELN_SUCCESS) {		    return seln_null_function;		}	    }	}	if (holder[ord(SELN_SHELF)].state != SELN_NONE	    && !seln_equal_access(&buffer.shelf.access,				  &buffer.caret.access)	    && !seln_equal_access(&buffer.shelf.access,				  &buffer.primary.access)	    && !seln_equal_access(&buffer.shelf.access,				  &buffer.secondary.access)) {	    if (seln_equal_access(&args->holder.access, &buffer.shelf.access)) {		informer = SELN_SHELF;	    } else {		if (seln_send_msg(SELN_SHELF, &buffer) != SELN_SUCCESS) {		    return seln_null_function;		}	    }	}    }    if (informer == SELN_UNKNOWN) {	return seln_null_function;    } else {	buffer.addressee_rank = informer;	return buffer;    }}static Seln_resultseln_send_msg(rank, buffer)    Seln_rank             rank;    Seln_function_buffer *buffer;{    register Seln_holder *recipient;    register CLIENT      *client;    struct timeval        timeout;    enum clnt_stat        result;    int                   socket = RPC_ANYSOCK;    timeout.tv_sec = 0;    timeout.tv_usec = 0;    recipient = &holder[ord(rank)];    buffer->addressee_rank = rank;    if ((client = clntudp_bufcreate(&recipient->access.udp_address,				    recipient->access.program, SELN_VERSION,				    timeout, &socket,				    SELN_RPC_BUFSIZE, SELN_RPC_BUFSIZE))	== (CLIENT *) NULL) {	return SELN_FAILED;    }    if (trace_inform) {	(void)fprintf(stderr, "\tfunction-key notification sent to ");	seln_dump_rank(stderr, &rank);	(void)fprintf(stderr, " holder.\n");    }    result = clnt_call(client, SELN_CLNT_DO_FUNCTION,		       xdr_seln_function, buffer, xdr_void, 0, timeout);    clnt_destroy(client);    (void)close(socket);	/*  no, clnt_destroy didn't close it....  */    if (result == RPC_TIMEDOUT || result == RPC_SUCCESS)  {	if (trace_inform) {	    (void)fprintf(stderr, "    notification returns Success\n");	}	return SELN_SUCCESS;    } else {	if (trace_inform) {	    (void)fprintf(stderr, "    notification returns Failure\n");	}	return SELN_FAILED;    }}static char *seln_svc_debug(attr, value)    Seln_attribute        attr;    u_int                 value;{    if (attr == SELN_TRACE_DUMP) {	return (char *) seln_dump_service(stderr, holder, (Seln_rank)value);    }    (void)fprintf(stderr, "Selection service trace %s for ", (value ? "on" : "off"));    switch (attr) {      case SELN_TRACE_ACQUIRE:	(void)fprintf(stderr, "acquire.\n");	if (value == TRUE) {	    return (char *) (trace_acquire = TRUE);	} else {	    return (char *) (trace_acquire = FALSE);	}      case SELN_TRACE_DONE:	(void)fprintf(stderr, "done.\n");	if (value == TRUE) {	    return (char *) (trace_done = TRUE);	} else {	    return (char *) (trace_done = FALSE);	}      case SELN_TRACE_HOLD_FILE:	(void)fprintf(stderr, "hold file.\n");	if (value == TRUE) {	    return (char *) (trace_hold_file = TRUE);	} else {	    return (char *) (trace_hold_file = FALSE);	}      case SELN_TRACE_INFORM:	(void)fprintf(stderr, "inform.\n");	if (value == TRUE) {	    return (char *) (trace_inform = TRUE);	} else {	    return (char *) (trace_inform = FALSE);	}      case SELN_TRACE_INQUIRE:	(void)fprintf(stderr, "inquire.\n");	if (value == TRUE) {	    return (char *) (trace_inquire = TRUE);	} else {	    return (char *) (trace_inquire = FALSE);	}      case SELN_TRACE_YIELD:	(void)fprintf(stderr, "yield.\n");	if (value == TRUE) {	    return (char *) (trace_yield = TRUE);	} else {	    return (char *) (trace_yield = FALSE);	}      case SELN_TRACE_STOP:	(void)fprintf(stderr, "stop.\n");	if (value == TRUE) {	    return (char *) (trace_stop = TRUE);	} else {	    return (char *) (trace_stop = FALSE);	}	/*NOTREACHED*/    }    /*NOTREACHED*/}/*	return or modify the flag which controls how many notifications *	are sent on a function-button up (in response to a SELN_INFORM). */static char *seln_svc_notify_suppression(item, context, len)    Seln_attribute        item;    Seln_replier_data    *context;    int                   len;{    int                   old;    if (item == SELN_GET_NOTIFY_SUPPRESSION) {	return (char *)full_notifications;    } else {	old = full_notifications;	full_notifications = (int) *context->response_pointer;	return (char *)old;    }}/* how many interfaces could there be on a computer? */#define	MAX_LOCAL 64static struct in_addr addrs[MAX_LOCAL];bool_tchklocal(taddr)	struct in_addr	taddr;{	int		i;	struct in_addr	iaddr;	int 		num_local;	if (taddr.s_addr == INADDR_LOOPBACK)		return (TRUE);	num_local = getlocal();	for (i = 0; i < num_local; i++) {		iaddr.s_addr = ntohl(addrs[i].s_addr);		if (bcmp((char *) &taddr, (char *) &(iaddr),			sizeof (struct in_addr)) == 0)			return (TRUE);	}	return (FALSE);}intgetlocal(){	struct ifconf	ifc;	struct ifreq	ifreq, *ifr;	int		n, j, sock;	char		buf[UDPMSGSIZE];	ifc.ifc_len = UDPMSGSIZE;	ifc.ifc_buf = buf;	sock = socket(PF_INET, SOCK_DGRAM, 0);	if (sock < 0)		return (FALSE);	if (ioctl(sock, SIOCGIFCONF, (char *) &ifc) < 0) {		perror("sel_svc:ioctl SIOCGIFCONF");		(void) close(sock);		return (FALSE);	}	ifr = ifc.ifc_req;	j = 0;	for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) {		ifreq = *ifr;		if (ioctl(sock, SIOCGIFFLAGS, (char *) &ifreq) < 0) {			perror("sel_svc:ioctl SIOCGIFFLAGS");			continue;		}		if ((ifreq.ifr_flags & IFF_UP) &&			ifr->ifr_addr.sa_family == AF_INET) {			if (ioctl(sock, SIOCGIFADDR, (char *) &ifreq) < 0) {				perror("SIOCGIFADDR");			} else {				addrs[j] = ((struct sockaddr_in *)						& ifreq.ifr_addr)->sin_addr;				j++;			}		}		if (j >= (MAX_LOCAL - 1))			break;	}	(void) close(sock);	return (j);}

⌨️ 快捷键说明

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