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

📄 picocom.c

📁 picocom 是一款linux下的串口调试工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* vi: set sw=4 ts=4: * * picocom.c * * simple dumb-terminal program. Helps you manually configure and test * stuff like modems, devices w. serial ports etc. * * by Nick Patavalis (npat@efault.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA  */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <errno.h>#include <assert.h>#include <stdarg.h>#include <signal.h>#include <unistd.h>#include <fcntl.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>#include <limits.h>#define _GNU_SOURCE#include <getopt.h>#include "term.h"/**********************************************************************/#define KEY_EXIT    '\x18' /* C-x: exit picocom */#define KEY_QUIT    '\x11' /* C-q: exit picocom without reseting port */#define KEY_PULSE   '\x10' /* C-p: pulse DTR */#define KEY_TOGGLE  '\x14' /* C-t: toggle DTR */#define KEY_BAUD_UP '\x15' /* C-u: increase baudrate (up) */#define KEY_BAUD_DN '\x04' /* C-d: decrase baudrate (down) */ #define KEY_FLOW    '\x06' /* C-f: change flowcntrl mode */ #define KEY_PARITY  '\x19' /* C-y: change parity mode */ #define KEY_BITS    '\x02' /* C-b: change number of databits */ #define KEY_STATUS  '\x16' /* C-v: show program option */#define KEY_SEND    '\x13' /* C-s: send file */#define KEY_RECEIVE '\x12' /* C-r: receive file */#define KEY_BREAK   '\x1c' /* C-\: break */#define STO STDOUT_FILENO#define STI STDIN_FILENO/**********************************************************************/struct {	char port[128];	int baud;	enum flowcntrl_e flow;	char *flow_str;	enum parity_e parity;	char *parity_str;	int databits;	int noinit;	int noreset;#ifdef UUCP_LOCK_DIR	int nolock;#endif	unsigned char escape;	char send_cmd[128];	char receive_cmd[128];} opts = {	.port = "",	.baud = 9600,	.flow = FC_NONE,	.flow_str = "none",	.parity = P_NONE,	.parity_str = "none",	.databits = 8,	.noinit = 0,	.noreset = 0,#ifdef UUCP_LOCK_DIR	.nolock = 0,#endif	.escape = '\x01',	.send_cmd = "ascii_xfr -s -v -l10",	.receive_cmd = "rz -vv"};int tty_fd;/**********************************************************************/#ifdef UUCP_LOCK_DIR/* use HDB UUCP locks  .. see * <http://www.faqs.org/faqs/uucp-internals> for details */char lockname[_POSIX_PATH_MAX] = "";intuucp_lockname(const char *dir, const char *file){	char *p, *cp;	struct stat sb;	if ( ! dir || *dir == '\0' || stat(dir, &sb) != 0 )		return -1;	/* cut-off initial "/dev/" from file-name */	p = strchr(file + 1, '/');	p = p ? p + 1 : (char *)file;	/* replace '/'s with '_'s in what remains (after making a copy) */	p = cp = strdup(p);	do { if ( *p == '/' ) *p = '_'; } while(*p++);	/* build lockname */	snprintf(lockname, sizeof(lockname), "%s/LCK..%s", dir, cp);	/* destroy the copy */	free(cp);	return 0;}intuucp_lock(void){	int r, fd, pid;	char buf[16];	mode_t m;	if ( lockname[0] == '\0' ) return 0;	fd = open(lockname, O_RDONLY);	if ( fd >= 0 ) {		r = read(fd, buf, sizeof(buf)); 		close(fd);		/* if r == 4, lock file is binary (old-style) */		pid = (r == 4) ? *(int *)buf : strtol(buf, NULL, 10);		if ( pid > 0 			 && kill((pid_t)pid, 0) < 0 			 && errno == ESRCH ) {			/* stale lock file */			printf("Removing stale lock: %s\n", lockname);			sleep(1);			unlink(lockname);		} else {			lockname[0] = '\0';			errno = EEXIST;			return -1;		}	}	/* lock it */	m = umask(022);	fd = open(lockname, O_WRONLY|O_CREAT|O_EXCL, 0666);	if ( fd < 0 ) { lockname[0] = '\0'; return -1; }	umask(m);	snprintf(buf, sizeof(buf), "%04d\n", getpid());	write(fd, buf, strlen(buf));	close(fd);	return 0;}intuucp_unlock(void){	if ( lockname[0] ) unlink(lockname);	return 0;}#endif /* of UUCP_LOCK_DIR *//**********************************************************************/ssize_twriten_ni(int fd, const void *buff, size_t n){	size_t nl; 	ssize_t nw;	const char *p;	p = buff;	nl = n;	while (nl > 0) {		do {			nw = write(fd, p, nl);		} while ( nw < 0 && errno == EINTR );		if ( nw <= 0 ) break;		nl -= nw;		p += nw;	}		return n - nl;}intfd_printf (int fd, const char *format, ...){	char buf[256];	va_list args;	int len;		va_start(args, format);	len = vsnprintf(buf, sizeof(buf), format, args);	buf[sizeof(buf) - 1] = '\0';	va_end(args);		return writen_ni(fd, buf, len);}voidfatal (const char *format, ...){	char *s, buf[256];	va_list args;	int len;	term_reset(STO);	term_reset(STI);		va_start(args, format);	len = vsnprintf(buf, sizeof(buf), format, args);	buf[sizeof(buf) - 1] = '\0';	va_end(args);		s = "\r\nFATAL: ";	writen_ni(STO, s, strlen(s));	writen_ni(STO, buf, len);	s = "\r\n";	writen_ni(STO, s, strlen(s));	/* wait a bit for output to drain */	sleep(1);#ifdef UUCP_LOCK_DIR	uucp_unlock();#endif		exit(EXIT_FAILURE);}#define cput(fd, c) do { int cl = c; write((fd), &(cl), 1); } while(0)intfd_readline (int fdi, int fdo, char *b, int bsz){	int r;	unsigned char c;	unsigned char *bp, *bpe;		bp = b;	bpe = b + bsz - 1;	while (1) {		r = read(fdi, &c, 1);		if ( r <= 0 ) { r--; goto out; }		switch (c) {		case '\b':			if ( bp > (unsigned char *)b ) { 				bp--;				cput(fdo, c); cput(fdo, ' '); cput(fdo, c);			} else {				cput(fdo, '\x07');			}			break;		case '\r':			*bp = '\0';			r = bp - (unsigned char *)b; 			goto out;		default:			if ( bp < bpe ) { *bp++ = c; cput(fdo, c); }			else { cput(fdo, '\x07'); }			break;		}	}out:	return r;}#undef cput/**********************************************************************/intbaud_up (int baud){	if ( baud < 300 )		baud = 300;	else if ( baud == 38400 )		baud = 57600;	else			baud = baud * 2;	if ( baud > 115200 )		baud = 115200;	return baud;}intbaud_down (int baud){	if ( baud > 115200 )		baud = 115200;	else if ( baud == 57600 )		baud = 38400;	else		baud = baud / 2;	if ( baud < 300)		baud = 300;	return baud;}intflow_next (int flow, char **flow_str){	switch(flow) {	case FC_NONE:		flow = FC_RTSCTS;		*flow_str = "RTS/CTS";		break;	case FC_RTSCTS:		flow = FC_XONXOFF;		*flow_str = "xon/xoff";		break;	case FC_XONXOFF:		flow = FC_NONE;		*flow_str = "none";		break;	default:		flow = FC_NONE;		*flow_str = "none";		break;	}	return flow;}intparity_next (int parity, char **parity_str){	switch(parity) {	case P_NONE:		parity = P_EVEN;		*parity_str = "even";		break;	case P_EVEN:		parity = P_ODD;		*parity_str = "odd";		break;	case P_ODD:		parity = P_NONE;		*parity_str = "none";		break;	default:		parity = P_NONE;		*parity_str = "none";		break;	}	return parity;}intbits_next (int bits){	bits++;	if (bits > 8) bits = 5;	return bits;}/**********************************************************************/voidchild_empty_handler (int signum){}voidestablish_child_signal_handlers (void){	struct sigaction empty_action;		/* Set up the structure to specify the "empty" action. */    empty_action.sa_handler = child_empty_handler;	sigemptyset (&empty_action.sa_mask);	empty_action.sa_flags = 0;		sigaction (SIGINT, &empty_action, NULL);	sigaction (SIGTERM, &empty_action, NULL);}intrun_cmd(int fd, ...){	pid_t pid;	sigset_t sigm, sigm_old;	/* block signals, let child establish its own handlers */	sigemptyset(&sigm);	sigaddset(&sigm, SIGTERM);	sigprocmask(SIG_BLOCK, &sigm, &sigm_old);	pid = fork();	if ( pid < 0 ) {		sigprocmask(SIG_SETMASK, &sigm_old, NULL);		fd_printf(STO, "*** cannot fork: %s\n", strerror(errno));		return -1;	} else if ( pid ) {		/* father: picocom */		int r;		/* reset the mask */		sigprocmask(SIG_SETMASK, &sigm_old, NULL);		/* wait for child to finish */		waitpid(pid, &r, 0);		/* reset terminal (back to raw mode) */		term_apply(STI);		/* check and report child return status */		if ( WIFEXITED(r) ) { 			fd_printf(STO, "\r\n*** exit status: %d\r\n", 					  WEXITSTATUS(r));			return WEXITSTATUS(r);		} else {			fd_printf(STO, "\r\n*** abnormal termination: 0x%x\r\n", r);			return -1;		}	} else {		/* child: external program */		int r;		long fl;		char cmd[512];		establish_child_signal_handlers();		sigprocmask(SIG_SETMASK, &sigm_old, NULL);		/* unmanage terminal, and reset it to canonical mode */		term_remove(STI);		/* unmanage serial port fd, without reset */		term_erase(fd);		/* set serial port fd to blocking mode */		fl = fcntl(fd, F_GETFL); 		fl &= ~O_NONBLOCK;		fcntl(fd, F_SETFL, fl);		/* connect stdin and stdout to serial port */		close(STI);		close(STO);		dup2(fd, STI);		dup2(fd, STO);		{			/* build command-line */			char *c, *ce;			const char *s;			int n;			va_list vls;						c = cmd;			ce = cmd + sizeof(cmd) - 1;			va_start(vls, fd);			while ( (s = va_arg(vls, const char *)) ) {				n = strlen(s);				if ( c + n + 1 >= ce ) break;				memcpy(c, s, n); c += n;				*c++ = ' ';			}			va_end(vls);			*c = '\0';		}		/* run extenral command */		fd_printf(STDERR_FILENO, "%s\n", cmd);		r = system(cmd);		if ( WIFEXITED(r) ) exit(WEXITSTATUS(r));		else exit(128);	}}/**********************************************************************/#define TTY_Q_SZ 256struct tty_q {	int len;	unsigned char buff[TTY_Q_SZ];} tty_q;/**********************************************************************/voidloop(void){	enum {		ST_COMMAND,		ST_TRANSPARENT	} state;	int dtr_up;	fd_set rdset, wrset;	int newbaud, newflow, newparity, newbits;

⌨️ 快捷键说明

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