📄 serie.c
字号:
/***********************************************************************//* serie.c *//* ------- *//* GTKTerm Software *//* (c) Julien Schmitt *//* julien@jls-info.com */ /* *//* ------------------------------------------------------------------- *//* *//* Purpose *//* Serial port access functions *//* *//* ChangeLog *//* - 0.99.5 : changed all calls to strerror() by strerror_utf8() *//* - 0.99.2 : Internationalization *//* - 0.98.6 : new sendbreak() function *//* - 0.98.1 : lockfile implementation (based on minicom) *//* - 0.98 : removed IOChannel *//* *//***********************************************************************/#include <gtk/gtk.h>#include <glib.h>#include <termios.h>#include <fcntl.h>#include <stdio.h>#include <unistd.h>#include <sys/ioctl.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <signal.h>#include <string.h>#include <errno.h>#include <pwd.h>#include "gettext.h"#include "config.h"#include "serie.h"#include "widgets.h"#include "fichier.h"#include "buffer.h"#include "i18n.h"struct termios termios_save;int serial_port_fd = -1;guint callback_handler;gboolean callback_activated = FALSE;char lockfile[128] = {0};gchar *str_err = NULL;extern struct configuration_port config;/* Local functions prototype */gint create_lockfile(char *);void remove_lockfile(void);void Ferme_Port(void);void Ouvre_Port(char *);void Lis_port(gpointer data, gint source, GdkInputCondition condition){ gint bytes_read; static gchar c[BUFFER_RECEPTION]; guint i; bytes_read = BUFFER_RECEPTION; while(bytes_read == BUFFER_RECEPTION) { bytes_read = read(serial_port_fd, c, BUFFER_RECEPTION); if(bytes_read > 0) { put_chars(c, bytes_read, config.crlfauto); if(config.car != -1 && waiting_for_char == TRUE) { i = 0; while(i < bytes_read) { if(c[i] == config.car) { waiting_for_char = FALSE; add_input(); i = bytes_read; } i++; } } } else if(bytes_read == -1) { if(errno != EAGAIN) perror(config.port); } } return;}static inline int Send_crlf(void){ const char crlf_seq[2] = {'\r', '\n'}; if(write(serial_port_fd, crlf_seq, 2) != 2) return (-1); else return 1;}int Send_chars(char *string, int length){ char *buffer, *start_buffer; int i, size_written, buf_length; int bytes_written = 0; /* Normally it never happens, but it is better not to segfault ;) */ if(length == 0) return 0; buffer=string; if(config.crlfauto) { if(length == 1) { if(*string == '\n' || *string == '\r') { bytes_written = Send_crlf(); } else { bytes_written = write(serial_port_fd, string, length); } } else { start_buffer = buffer; buf_length = 1; for(i = 0; i < length; i++) { if(*buffer == '\n' && *(buffer - 1) != '\r') { size_written = write(serial_port_fd, start_buffer, buf_length - 1); if(size_written == -1) return bytes_written; bytes_written += size_written; size_written = Send_crlf(); if(size_written == -1) return bytes_written; bytes_written += size_written; start_buffer = buffer + 1; buf_length = 0; } else if(*(buffer - 1) == '\r' && *buffer != '\n') { if(buf_length > 2) size_written = write(serial_port_fd, start_buffer, buf_length - 2); else size_written =0; if(size_written == -1) return bytes_written; bytes_written += size_written; size_written = Send_crlf(); if(size_written == -1) return bytes_written; bytes_written += size_written; start_buffer = buffer; buf_length = 1; } buffer++; buf_length++; } if(buf_length>1) bytes_written += write(serial_port_fd, start_buffer, buf_length-1); if(start_buffer[buf_length-2] == '\r') bytes_written += write(serial_port_fd, "\n", 1); } } else { bytes_written = write(serial_port_fd, buffer, length); } return bytes_written;}void Ouvre_Port(char *port){ serial_port_fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);}gchar *Config_port(void){ struct termios termios_p; gchar *msg; Ferme_Port(); remove_lockfile(); Ouvre_Port(config.port); if(serial_port_fd == -1) { g_free(str_err); str_err = g_strdup_printf(_("Cannot open %s : %s\n"), config.port, strerror_utf8(errno)); show_message(str_err, MSG_ERR); return NULL; } if(create_lockfile(config.port) == -1) { Ferme_Port(); return NULL; } msg = g_strdup_printf("%s : %d,%d", config.port, config.vitesse, config.bits); tcgetattr(serial_port_fd, &termios_p); memcpy(&termios_save, &termios_p, sizeof(struct termios)); switch(config.vitesse) { case 300: termios_p.c_cflag = B300; break; case 600: termios_p.c_cflag = B600; break; case 1200: termios_p.c_cflag = B1200; break; case 2400: termios_p.c_cflag = B2400; break; case 4800: termios_p.c_cflag = B4800; break; case 9600: termios_p.c_cflag = B9600; break; case 19200: termios_p.c_cflag = B19200; break; case 38400: termios_p.c_cflag = B38400; break; case 57600: termios_p.c_cflag = B57600; break; case 115200: termios_p.c_cflag = B115200; break; } switch(config.bits) { case 5: termios_p.c_cflag |= CS5; break; case 6: termios_p.c_cflag |= CS6; break; case 7: termios_p.c_cflag |= CS7; break; case 8: termios_p.c_cflag |= CS8; break; } switch(config.parite) { case 1: termios_p.c_cflag |= PARODD | PARENB; msg = g_strdup_printf("%s,O", msg); break; case 2: termios_p.c_cflag |= PARENB; msg = g_strdup_printf("%s,E", msg); break; default: msg = g_strdup_printf("%s,N", msg); break; } if(config.stops == 2) termios_p.c_cflag |= CSTOPB; termios_p.c_cflag |= CREAD; msg = g_strdup_printf("%s,%d", msg, config.stops); termios_p.c_iflag = IGNPAR | IGNBRK; switch(config.flux) { case 1: termios_p.c_iflag |= IXON | IXOFF; msg = g_strdup_printf("%s - Xon/Xoff", msg); break; case 2: termios_p.c_cflag |= CRTSCTS; msg = g_strdup_printf("%s - RTS/CTS", msg); break; default: termios_p.c_cflag |= CLOCAL; break; } termios_p.c_oflag = 0; termios_p.c_lflag = 0; termios_p.c_cc[VTIME] = 0; termios_p.c_cc[VMIN] = 1; tcsetattr(serial_port_fd, TCSANOW, &termios_p); tcflush(serial_port_fd, TCOFLUSH); tcflush(serial_port_fd, TCIFLUSH); callback_handler = gtk_input_add_full(serial_port_fd, GDK_INPUT_READ, (GdkInputFunction)Lis_port, NULL, NULL, NULL); callback_activated = TRUE; Set_local_echo(config.echo); return msg;}void configure_echo(gboolean echo){ config.echo = echo;}void configure_crlfauto(gboolean crlfauto){ config.crlfauto = crlfauto;}void Ferme_Port(void){ if(serial_port_fd != -1) { if(callback_activated == TRUE) { gtk_input_remove(callback_handler); callback_activated = FALSE; } tcsetattr(serial_port_fd, TCSANOW, &termios_save); tcflush(serial_port_fd, TCOFLUSH); tcflush(serial_port_fd, TCIFLUSH); close(serial_port_fd); serial_port_fd = -1; }}void Set_signals(guint param){ int stat_; if(serial_port_fd == -1) return; if(ioctl(serial_port_fd, TIOCMGET, &stat_) == -1) { i18n_perror(_("Control signals read")); return; } /* DTR */ if(param == 0) { if(stat_ & TIOCM_DTR) stat_ &= ~TIOCM_DTR; else stat_ |= TIOCM_DTR; if(ioctl(serial_port_fd, TIOCMSET, &stat_) == -1) i18n_perror(_("DTR write")); } /* RTS */ else if(param == 1) { if(stat_ & TIOCM_RTS) stat_ &= ~TIOCM_RTS; else stat_ |= TIOCM_RTS; if(ioctl(serial_port_fd, TIOCMSET, &stat_) == -1) i18n_perror(_("RTS write")); }}int lis_sig(void){ static int stat = 0; int stat_read; if(serial_port_fd != -1) { if(ioctl(serial_port_fd, TIOCMGET, &stat_read) == -1) { i18n_perror(_("Control signals read")); return -2; } if(stat_read == stat) return -1; stat = stat_read; return stat; } return -1;}/* * Find out name to use for lockfile when locking tty. */char *mbasename(char *s, char *res, int reslen){ char *p; if (strncmp(s, "/dev/", 5) == 0) { /* In /dev */ strncpy(res, s + 5, reslen - 1); res[reslen-1] = 0; for (p = res; *p; p++) if (*p == '/') *p = '_'; } else { /* Outside of /dev. Do something sensible. */ if ((p = strrchr(s, '/')) == NULL) p = s; else p++; strncpy(res, p, reslen - 1); res[reslen-1] = 0; } return res;}gint create_lockfile(char *port){ char buf[128]; char *username; struct stat stt; int fd, n = 0; int pid; int mask; uid_t real_uid; gid_t real_gid; real_uid = getuid(); real_gid = getgid(); username = (getpwuid(real_uid))->pw_name; /* First see if the lock file directory is present. */ if(P_LOCK[0] && stat(P_LOCK, &stt) == 0) snprintf(lockfile, sizeof(lockfile), "%s/LCK..%s", P_LOCK, mbasename(port, buf, sizeof(buf))); else lockfile[0] = 0; if(lockfile[0] && (fd = open(lockfile, O_RDONLY)) >= 0) { n = read(fd, buf, 127); close(fd); if(n > 0) { pid = -1; if(n == 4) /* Kermit-style lockfile. */ pid = *(int *)buf; else { /* Ascii lockfile. */ buf[n] = 0; sscanf(buf, "%d", &pid); } if(pid > 0 && kill((pid_t)pid, 0) < 0 && errno == ESRCH) { i18n_fprintf(stderr, _("Lockfile is stale. Overriding it..\n")); sleep(1); unlink(lockfile); } else n = 0; } if(n == 0) { i18n_fprintf(stderr, _("Device %s is locked.\n"), port); lockfile[0] = 0; return -1; } } if(lockfile[0]) { /* Create lockfile compatible with UUCP-1.2 */ mask = umask(022); if((fd = open(lockfile, O_WRONLY | O_CREAT | O_EXCL, 0666)) < 0) { i18n_fprintf(stderr, _("Cannot create lockfile. Sorry.\n")); lockfile[0] = 0; return -1; } (void)umask(mask); (void)chown(lockfile, real_uid, real_gid); snprintf(buf, sizeof(buf), "%10ld gtkterm %.20s\n", (long)getpid(), username); write(fd, buf, strlen(buf)); close(fd); } return 0;}void remove_lockfile(void){ if(lockfile[0]) unlink(lockfile);}void Close_port_and_remove_lockfile(void){ Ferme_Port(); remove_lockfile();}void sendbreak(void){ if(serial_port_fd == -1) return; else tcsendbreak(serial_port_fd, 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -