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

📄 controller.c

📁 This project provides a proxy that allows telnet/tcp connections to be made to serial ports on a mac
💻 C
📖 第 1 页 / 共 2 页
字号:
	setportenable(cntlr, tok, str);    } else if (strcmp(tok, "setportconfig") == 0) {	tok = strtok_r(NULL, " \t", &strtok_data);	if (tok == NULL) {	    char *err = "No port given\n\r";	    controller_output(cntlr, err, strlen(err));	    goto out;	}	str = strtok_r(NULL, "", &strtok_data);	if (str == NULL) {	    char *err = "No device config\n\r";	    controller_output(cntlr, err, strlen(err));	    goto out;	}	setportdevcfg(cntlr, tok, str);    } else if (strcmp(tok, "setportcontrol") == 0) {	tok = strtok_r(NULL, " \t", &strtok_data);	if (tok == NULL) {	    char *err = "No port given\n\r";	    controller_output(cntlr, err, strlen(err));	    goto out;	}	str = strtok_r(NULL, "", &strtok_data);	if (str == NULL) {	    char *err = "No device controls\n\r";	    controller_output(cntlr, err, strlen(err));	    goto out;	}	setportcontrol(cntlr, tok, str);    } else {	char *err = "Unknown command: ";	controller_output(cntlr, err, strlen(err));	controller_output(cntlr, tok, strlen(tok));	controller_output(cntlr, "\n\r", 2);    }out:    controller_output(cntlr, prompt, strlen(prompt));}/* Removes one or more characters starting at pos and going backwards.   So, for instance, if inbuf holds "abcde", pos points to d, and   count is 2, the new inbuf will be "abe".  This is used for   backspacing and for removing telnet command characters. */static intremove_chars(controller_info_t *cntlr, int pos, int count) {    int j;    for (j=pos-count+1; j<(cntlr->inbuf_count-count); j++) {	cntlr->inbuf[j] = cntlr->inbuf[j+count];    }    cntlr->inbuf_count -= count;    pos -= count;    return pos;}/* Data is ready to read on the TCP port. */static voidhandle_tcp_fd_read(int fd, void *data){    controller_info_t *cntlr = (controller_info_t *) data;    int read_count;    int read_start;    int i;    if (cntlr->inbuf_count == INBUF_SIZE) {        char *err = "Input line too long\n\r";	controller_output(cntlr, err, strlen(err));	cntlr->inbuf_count = 0;	return;    }    read_count = read(fd,		      &(cntlr->inbuf[cntlr->inbuf_count]),		      INBUF_SIZE - cntlr->inbuf_count);    if (read_count < 0) {	if (errno == EINTR) {	    /* EINTR means we were interrupted, just retry by returning. */	    return;	}	if (errno == EAGAIN) {	    /* EAGAIN, is due to O_NONBLOCK, just ignore it. */	    return;	}	/* Got an error on the read, shut down the port. */	syslog(LOG_ERR, "read error for controller port: %m");	shutdown_controller(cntlr);	return;    } else if (read_count == 0) {	/* The other end closed the port, shut it down. */	shutdown_controller(cntlr);	return;    }    read_start = cntlr->inbuf_count;    read_count = process_telnet_data	(cntlr->inbuf+read_start, read_count, &cntlr->tn_data);    if (cntlr->tn_data.error) {	shutdown_controller(cntlr);	return;    }    cntlr->inbuf_count += read_count;        for (i=read_start; i<cntlr->inbuf_count; i++) {	if (cntlr->inbuf[i] == 0x0) {	    /* Ignore nulls. */	    i = remove_chars(cntlr, i, 1);	} else if (cntlr->inbuf[i] == '\n') {	    /* Ignore newlines. */	    i = remove_chars(cntlr, i, 1);	} else if ((cntlr->inbuf[i] == '\b') || (cntlr->inbuf[i] == 0x7f)) {	    /* Got a backspace. */	    if (i == 0) {		/* We ignore backspaces at the beginning of the line. */		i = remove_chars(cntlr, i, 1);	    } else {		i = remove_chars(cntlr, i, 2);		controller_output(cntlr, "\b \b", 3);	    }	} else if (cntlr->inbuf[i] == '\r') {	    /* We got a newline, process the command. */	    int j;	    controller_output(cntlr, "\n\r", 2);	    cntlr->inbuf[i] ='\0';	    process_input_line(cntlr);	    /* Now copy any leftover data to the beginning of the buffer. */	    /* Don't use memcpy or strcpy because the memory might               overlap */	    i++;	    cntlr->inbuf_count -= i;	    for (j=0; j<cntlr->inbuf_count; i++,j++) {		cntlr->inbuf[j] = cntlr->inbuf[i];	    }	    i = -1;	} else {	    /* It's a normal character, just echo it. */	    controller_output(cntlr, &(cntlr->inbuf[i]), 1);	}    }}/* The TCP port has room to write some data.  This is only activated   if a write fails to complete, it is deactivated as soon as writing   is available again. */static voidhandle_tcp_fd_write(int fd, void *data){    controller_info_t *cntlr = (controller_info_t *) data;    telnet_data_t *td = &cntlr->tn_data;    int write_count;    if (td->out_telnet_cmd_size > 0) {	write_count = write(cntlr->tcpfd,			    &(td->out_telnet_cmd[0]),			    td->out_telnet_cmd_size);	if (write_count == -1) {	    if (errno == EINTR) {		/* EINTR means we were interrupted, just retry by returning. */		return;	    }	    if (errno == EAGAIN) {		/* This again was due to O_NONBLOCK, just ignore it. */	    } else if (errno == EPIPE) {		shutdown_controller(cntlr);	    } else {		/* Some other bad error. */		syslog(LOG_ERR, "The tcp write for controller had error: %m");		shutdown_controller(cntlr);	    }	} else {	    int i, j;	    /* Copy the remaining data. */	    for (j=0, i=write_count; i<td->out_telnet_cmd_size; i++, j++)		td->out_telnet_cmd[j] = td->out_telnet_cmd[i];	    td->out_telnet_cmd_size -= write_count;	    if (td->out_telnet_cmd_size != 0)		/* If we have more telnet command data to send, don't		   send any real data. */		return;	}    }    write_count = write(cntlr->tcpfd,			&(cntlr->outbuf[cntlr->outbuf_pos]),			cntlr->outbuf_count);    if (write_count == -1) {	if (errno == EAGAIN) {	    /* This again was due to O_NONBLOCK, just ignore it. */	} else if (errno == EPIPE) {	    shutdown_controller(cntlr);	} else {	    /* Some other bad error. */	    syslog(LOG_ERR, "The tcp write for controller had error: %m");	    shutdown_controller(cntlr);	}    } else {	cntlr->outbuf_count -= write_count;	if (cntlr->outbuf_count != 0) {	    /* We didn't write all the data, continue writing. */	    cntlr->outbuf_pos += write_count;	} else {	    /* We are done writing, turn the reader back on. */	    free(cntlr->outbuf);	    cntlr->outbuf = NULL;	    sel_set_fd_read_handler(ser2net_sel, cntlr->tcpfd,				    SEL_FD_HANDLER_ENABLED);	    sel_set_fd_write_handler(ser2net_sel, cntlr->tcpfd,				     SEL_FD_HANDLER_DISABLED);	}    }}/* Handle an exception from the TCP port. */static voidhandle_tcp_fd_except(int fd, void *data){    controller_info_t *cntlr = (controller_info_t *) data;    syslog(LOG_ERR, "Select exception for controller port");    shutdown_controller(cntlr);}/* A connection request has come in for the control port. */static voidhandle_accept_port_read(int fd, void *data){    controller_info_t *cntlr;    socklen_t         len;    char              *err = NULL;    if (num_controller_ports >= max_controller_ports) {	err = "Too many controller ports\n\r";	goto errout2;    } else {	cntlr = malloc(sizeof(*cntlr));	if (cntlr == NULL) {	    err = "Could not allocate controller port\n\r";	    goto errout2;	}    }    /* From here on, errors must go to errout. */    len = sizeof(cntlr->remote);    cntlr->tcpfd = accept(fd, (struct sockaddr *) &(cntlr->remote), &len);    if (cntlr->tcpfd == -1) {	syslog(LOG_ERR, "Could not accept on controller port: %m");	goto errout;    }#ifdef HAVE_TCPD_H    {	struct request_info req;		request_init(&req, RQ_DAEMON, progname, RQ_FILE, cntlr->tcpfd, NULL);	fromhost(&req);	if (!hosts_access(&req)) {	    char *err = "Access denied\n\r";	    write(cntlr->tcpfd, err, strlen(err));	    close(cntlr->tcpfd);	    goto errout;	}    }#endif /* HAVE_TCPD_H */    if (fcntl(cntlr->tcpfd, F_SETFL, O_NONBLOCK) == -1) {	close(cntlr->tcpfd);	syslog(LOG_ERR, "Could not fcntl the tcp port: %m");	goto errout;    }    cntlr->inbuf_count = 0;    cntlr->outbuf = NULL;    cntlr->monitor_port_id = NULL;    sel_set_fd_handlers(ser2net_sel,			cntlr->tcpfd,			cntlr,			handle_tcp_fd_read,			handle_tcp_fd_write,			handle_tcp_fd_except);    cntlr->next = controllers;    controllers = cntlr;    /* Send the telnet negotiation string.  We do this by       putting the data in the dev to tcp buffer and turning       the tcp write selector on. */    telnet_init(&cntlr->tn_data, cntlr, telnet_output_ready,		telnet_cmd_handler,		telnet_cmds,		telnet_init_seq, sizeof(telnet_init_seq));    controller_output(cntlr, prompt, strlen(prompt));    num_controller_ports++;    return;errout:    free(cntlr);    return;errout2:    {	/* We have a problem so refuse this one. */	struct sockaddr_in dummy_sockaddr;	socklen_t len = sizeof(dummy_sockaddr);	int new_fd = accept(fd, (struct sockaddr *) &dummy_sockaddr, &len);	if (new_fd != -1) {	    write(new_fd, err, strlen(err));	    close(new_fd);	}    }}/* Set up the controller port to accept connections. */intcontroller_init(char *controller_port){    struct sockaddr_in sock;    int    optval = 1;    if (scan_tcp_port(controller_port, &sock) == -1) {	return -1;    }    acceptfd = socket(PF_INET, SOCK_STREAM, 0);    if (acceptfd == -1) {	syslog(LOG_ERR, "Unable to create TCP socket: %m");	exit(1);    }    if (fcntl(acceptfd, F_SETFL, O_NONBLOCK) == -1) {	close(acceptfd);	syslog(LOG_ERR, "Could not fcntl the accept port: %m");	exit(1);    }    if (setsockopt(acceptfd,		   SOL_SOCKET,		   SO_REUSEADDR,		   (void *)&optval,		   sizeof(optval)) == -1) {	close(acceptfd);	syslog(LOG_ERR, "Unable to set reuseaddress on socket: %m");	exit(1);    }    if (bind(acceptfd, (struct sockaddr *) &sock, sizeof(sock)) == -1) {	close(acceptfd);	syslog(LOG_ERR, "Unable to bind TCP port: %m");	exit(1);    }    if (listen(acceptfd, 1) != 0) {	close(acceptfd);	syslog(LOG_ERR, "Unable to listen to TCP port: %m");	exit(1);    }    sel_set_fd_handlers(ser2net_sel,			acceptfd,			NULL,			handle_accept_port_read,			NULL,			NULL);    sel_set_fd_read_handler(ser2net_sel, acceptfd, SEL_FD_HANDLER_ENABLED);    return 0;}

⌨️ 快捷键说明

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