#include #include //#include #include #include #include #include #include #include #include #include #include "util.h" void set_nonblocking (int fd) { long arg = 0; arg = fcntl (fd, F_GETFL, arg); arg |= O_NONBLOCK; fcntl (fd, F_SETFL, arg); } void set_blocking (int fd) { long arg = 0; arg = fcntl (fd, F_GETFL, arg); arg &= ~O_NONBLOCK; fcntl (fd, F_SETFL, arg); } int fd_can_read (int fd) { struct timeval tv = {0}; fd_set rfds; FD_ZERO (&rfds); FD_SET (fd, &rfds); if (select (fd + 1, &rfds, NULL, NULL, &tv) == 1) return 1; return 0; } ssize_t read_with_timeout (int fd, void *_b, size_t len, unsigned timeout) { struct timeval tv = {0}; unsigned char *b = _b; fd_set rfds; ssize_t red, ret = 0; tv.tv_sec = timeout / 100; tv.tv_usec = (timeout % 100) * 10000; while (tv.tv_sec || tv.tv_usec) { FD_ZERO (&rfds); FD_SET (fd, &rfds); if (select (fd + 1, &rfds, NULL, NULL, &tv) == 1) { red = read (fd, &b[ret], 1); if (red == 1) ret++; if (red <= 0) { if (ret) return ret; return red; } if (ret == len) return ret; } } return ret; } int fd_drain (int fd) { char c; while (fd_can_read (fd)) if (read (fd, &c, 1) != 1) return -1; return 0; } static speed_t baud_to_speed_t (int baud) { switch (baud) { #ifdef B0 case 0: return B0; #endif #ifdef B50 case 50: return B50; #endif #ifdef B75 case 75: return B75; #endif #ifdef B110 case 110: return B110; #endif #ifdef B134 case 134: return B134; #endif #ifdef B150 case 150: return B150; #endif #ifdef B200 case 200: return B200; #endif #ifdef B300 case 300: return B300; #endif #ifdef B600 case 600: return B600; #endif #ifdef B1200 case 1200: return B1200; #endif #ifdef B1800 case 1800: return B1800; #endif #ifdef B2400 case 2400: return B2400; #endif #ifdef B4800 case 4800: return B4800; #endif #ifdef B9600 case 9600: return B9600; #endif #ifdef B19200 case 19200: return B19200; #endif #ifdef B38400 case 38400: return B38400; #endif #ifdef B57600 case 57600: return B57600; #endif #ifdef B115200 case 115200: return B115200; #endif #ifdef B230400 case 230400: return B230400; #endif } return -1; } static void default_termios (struct termios *termios) { termios->c_iflag = 0; termios->c_oflag = NL0 | CR0 | TAB0 | BS0 | VT0 | FF0; termios->c_lflag = 0; termios->c_cflag = CS8 | CREAD | CLOCAL; termios->c_cc[VINTR] = 003; termios->c_cc[VQUIT] = 034; termios->c_cc[VERASE] = 0177; termios->c_cc[VKILL] = 025; termios->c_cc[VEOF] = 004; termios->c_cc[VEOL] = 0; termios->c_cc[VEOL2] = 0; termios->c_cc[VSTART] = 021; termios->c_cc[VSTOP] = 023; termios->c_cc[VSUSP] = 032; termios->c_cc[VLNEXT] = 026; termios->c_cc[VWERASE] = 027; termios->c_cc[VREPRINT] = 022; termios->c_cc[VDISCARD] = 017; } //XXX: no locks int open_tty (const char *path, int baud) { int fd; struct termios termios; speed_t s = baud_to_speed_t (baud); if (s == (speed_t) - 1) return -1; fd = open (path, O_RDWR | O_NOCTTY | O_NONBLOCK); if (tcgetattr (fd, &termios)) { close (fd); return -1; } default_termios (&termios); if (tcsetattr (fd, TCSANOW, &termios)) { close (fd); return -1; } cfsetispeed (&termios, s); cfsetospeed (&termios, s); return fd; } static int host_to_sin (const char *host, struct sockaddr_in *sin) { struct hostent *he = gethostbyname2 (host, AF_INET); if (!he) { if (!inet_aton (host, &sin->sin_addr)) return -1; return 0; } if (he->h_addrtype != AF_INET) return -1; sin->sin_family = AF_INET; memcpy (&sin->sin_addr, he->h_addr_list[0], he->h_length); return 0; } int open_tcp_client (const char *host, unsigned port) { struct sockaddr_in sin = {0}; int fd; if (host_to_sin (host, &sin)) return -1; fd = socket (PF_INET, SOCK_STREAM, 0); if (fd < 0) return -1; sin.sin_port = htons (port); if (connect (fd, (struct sockaddr *)&sin, sizeof (sin))) { close (fd); return -1; } return fd; } int open_tcp_server (unsigned port) { int fd; int enable = 1; struct sockaddr_in sin = {0}; fd = socket (PF_INET, SOCK_STREAM, 0); if (fd < 0) return -1; if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof (enable))) return -1; sin.sin_family = AF_INET; sin.sin_port = htons (port); sin.sin_addr.s_addr = INADDR_ANY; if (bind (fd, (struct sockaddr *)&sin, sizeof (sin))) { close (fd); return -1; } if (listen (fd, 5)) { close (fd); return -1; } return fd; } int daemonish (int nochdir, int noclose) { pid_t pid; int status; if (!nochdir && chdir ("/")) return -1; if (!noclose) { int fd, failed = 0; if ((fd = open ("/dev/null", O_RDWR)) < 0) return -1; if (dup2 (fd, 0) < 0 || dup2 (fd, 1) < 0 || dup2 (fd, 2) < 0) failed++; if (fd > 2) close (fd); if (failed) return -1; } switch ((pid = fork())) { case 0: break; case -1: return -1; default: waitpid (pid, &status, 0); return 1;; } if (setsid() < 0) return -1; switch (fork()) { case 0: break; case -1: return -1; default: _exit (0); } return 0; } int local_isalnum (char c) { if ((c >= '0') && (c <= '9')) return 1; if ((c >= 'A') && (c <= 'Z')) return 1; if ((c >= 'a') && (c <= 'z')) return 1; return 0; }