123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- /*
- * SpanDSP - a series of DSP components for telephony
- *
- * pseudo_terminals.c - pseudo terminal handling.
- *
- * Written by Steve Underwood <steveu@coppice.org>
- *
- * Copyright (C) 2012 Steve Underwood
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2, as
- * published by the Free Software Foundation.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #include <inttypes.h>
- #include <stdlib.h>
- #if defined(WIN32)
- #include <windows.h>
- #else
- #if defined(__APPLE__)
- #include <util.h>
- #include <sys/ioctl.h>
- #elif defined(__FreeBSD__)
- #include <libutil.h>
- #include <termios.h>
- #else
- #include <pty.h>
- #endif
- #include <sys/socket.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <poll.h>
- #endif
- #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
- #include "spandsp.h"
- #include "pseudo_terminals.h"
- int next_id = 0;
- const char *device_root_name = "/dev/spandsp";
- int pseudo_terminal_close(modem_t *modem)
- {
- #if defined(WIN32)
- if (modem->master)
- {
- CloseHandle(modem->master);
- modem->master = 0;
- }
- #else
- if (modem->master > -1)
- {
- shutdown(modem->master, 2);
- close(modem->master);
- modem->master = -1;
- }
- #endif
- if (modem->slave > -1)
- {
- shutdown(modem->slave, 2);
- close(modem->slave);
- modem->slave = -1;
- }
- if (unlink(modem->devlink))
- return -1;
- return 0;
- }
- /*- End of function --------------------------------------------------------*/
- int pseudo_terminal_create(modem_t *modem)
- {
- #if defined(WIN32)
- COMMTIMEOUTS timeouts = {0};
- #endif
- memset(modem, 0, sizeof(*modem));
- span_log_init(&modem->logging, SPAN_LOG_NONE, NULL);
- span_log_set_protocol(&modem->logging, "PTY");
- span_log_set_level(&modem->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
- span_log_set_tag(&modem->logging, "PTY");
- modem->master = -1;
- modem->slave = -1;
- #if USE_OPENPTY
- if (openpty(&modem->master, &modem->slave, NULL, NULL, NULL))
- {
- span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: failed to initialize pty\n");
- return -1;
- }
- modem->stty = ttyname(modem->slave);
- #else
- #if defined(WIN32)
- modem->slot = 4 + next_id++; /* need work here we start at COM4 for now*/
- snprintf(modem->devlink, sizeof(modem->devlink), "COM%d", modem->slot);
- modem->master = CreateFile(modem->devlink,
- GENERIC_READ | GENERIC_WRITE,
- 0,
- 0,
- OPEN_EXISTING,
- FILE_FLAG_OVERLAPPED,
- 0);
- if (modem->master == INVALID_HANDLE_VALUE)
- {
- if (GetLastError() == ERROR_FILE_NOT_FOUND)
- span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: Serial port does not exist\n");
- else
- span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: Serial port open error\n");
- return -1;
- }
- #elif !defined(HAVE_POSIX_OPENPT)
- modem->master = open("/dev/ptmx", O_RDWR);
- #else
- modem->master = posix_openpt(O_RDWR | O_NOCTTY);
- #endif
- #if !defined(WIN32)
- if (modem->master < 0)
- span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: failed to initialize UNIX98 master pty\n");
- if (grantpt(modem->master) < 0)
- span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: failed to grant access to slave pty\n");
- if (unlockpt(modem->master) < 0)
- span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: failed to unlock slave pty\n");
- if ((modem->stty = ptsname(modem->master)) == NULL)
- span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: failed to obtain slave pty filename\n");
- if ((modem->slave = open(modem->stty, O_RDWR)) < 0)
- span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: failed to open slave pty %s\n", modem->stty);
- #endif
- #if defined(SOLARIS)
- ioctl(modem->slave, I_PUSH, "ptem");
- ioctl(modem->slave, I_PUSH, "ldterm");
- #endif
- #endif
- #if defined(WIN32)
- timeouts.ReadIntervalTimeout = 50;
- timeouts.ReadTotalTimeoutConstant = 50;
- timeouts.ReadTotalTimeoutMultiplier = 10;
- timeouts.WriteTotalTimeoutConstant = 50;
- timeouts.WriteTotalTimeoutMultiplier = 10;
- SetCommMask(modem->master, EV_RXCHAR);
- if (!SetCommTimeouts(modem->master, &timeouts))
- {
- span_log(&modem->logging, SPAN_LOG_ERROR, "Cannot set up non-blocking read on %s\n", modem->devlink);
- pseudo_terminal_close(modem);
- return -1;
- }
- modem->threadAbort = CreateEvent(NULL, true, false, NULL);
- #else
- modem->slot = next_id++;
- snprintf(modem->devlink, sizeof(modem->devlink), "%s/%d", device_root_name, modem->slot);
- /* Remove any stale link which might be present */
- unlink(modem->devlink);
- if (symlink(modem->stty, modem->devlink))
- {
- span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: failed to create %s symbolic link\n", modem->devlink);
- pseudo_terminal_close(modem);
- return -1;
- }
- if (fcntl(modem->master, F_SETFL, fcntl(modem->master, F_GETFL, 0) | O_NONBLOCK))
- {
- span_log(&modem->logging, SPAN_LOG_ERROR, "Cannot set up non-blocking read on %s\n", ttyname(modem->master));
- pseudo_terminal_close(modem);
- return -1;
- }
- #endif
- return 0;
- }
- /*- End of function --------------------------------------------------------*/
- /*- End of file ------------------------------------------------------------*/
|