asterisk-chan-dongle/tools/tty.c

184 lines
3.2 KiB
C
Raw Normal View History

2023-05-25 08:30:27 +00:00
#include <stdio.h>
#include <termios.h> /* struct termios tcgetattr() tcsetattr() */
#include <fcntl.h> /* O_RDWR O_NOCTTY */
#include <sys/stat.h> /* S_IRUSR | S_IRGRP | S_IROTH */
#include <string.h> /* strrchr() */
#include <limits.h> /* PATH_MAX */
#include <stdlib.h> /* realpath() */
#include <unistd.h> /* getpid() */
#include <errno.h> /* errno */
#include <signal.h> /* kill() */
#/* return length of lockname */
static int lock_build(const char * devname, char * buf, unsigned length)
{
const char * basename;
char resolved_path[PATH_MAX];
/* follow symlinks */
if(realpath(devname, resolved_path) != NULL)
devname = resolved_path;
/*
while(1)
{
len = readlink(devname, symlink, sizeof(symlink) - 1);
if(len <= 0)
break;
symlink[len] = 0;
if(symlink[0] == '/')
devname = symlink;
else
{
// TODO
memmove()
memcpy(symlink, devname);
}
}
*/
basename = strrchr(devname, '/');
if(basename)
basename++;
else
basename = devname;
/* TODO: use asterisk build settings for /var/lock */
#if defined(__FreeBSD__)
return snprintf(buf, length, "/var/spool/lock/LCK..%s", basename);
#else
return snprintf(buf, length, "/var/lock/LCK..%s", basename);
#endif
}
#/* return 0 on error */
static int lock_create(const char * lockfile)
{
int fd;
int len = 0;
char pidb[21];
fd = open(lockfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IRGRP | S_IROTH);
if(fd >= 0)
{
len = snprintf(pidb, sizeof(pidb), "%d", getpid());
len = write(fd, pidb, len);
close(fd);
}
return len;
}
#/* return pid of owner, 0 if free */
static int lock_try(const char * devname)
{
int fd;
int len;
int pid = 0;
char name[256];
char pidb[21];
lock_build(devname, name, sizeof(name));
/* FIXME: rise condition: some time between lock check and got lock */
fd = open(name, O_RDONLY);
if(fd >= 0)
{
len = read(fd, pidb, sizeof(pidb) - 1);
if(len > 0)
{
pidb[len] = 0;
len = strtol(pidb, NULL, 10);
if(kill(len, 0) == 0)
pid = len;
}
close(fd);
}
if(pid == 0)
{
unlink(name);
lock_create(name);
}
return pid;
}
int opentty (const char* dev)
{
int pid;
int fd;
struct termios term_attr;
fd = open (dev, O_RDWR | O_NOCTTY);
if (fd < 0)
{
return -1;
}
if (tcgetattr (fd, &term_attr) != 0)
{
close(fd);
return -1;
}
term_attr.c_cflag = B115200 | CS8 | CREAD | CRTSCTS;
term_attr.c_iflag = 0;
term_attr.c_oflag = 0;
term_attr.c_lflag = 0;
term_attr.c_cc[VMIN] = 1;
term_attr.c_cc[VTIME] = 0;
if (tcsetattr (fd, TCSAFLUSH, &term_attr) != 0)
{
}
pid = lock_try(dev);
if(pid != 0)
{
close(fd);
return -1;
}
return fd;
}
#/* */
void closetty(const char * dev, int fd)
{
char name[256];
close(fd);
/* remove lock */
lock_build(dev, name, sizeof(name));
unlink(name);
}
#/* */
size_t write_all (int fd, const char* buf, size_t count)
{
ssize_t out_count;
size_t total = 0;
unsigned errs = 10;
while (count > 0)
{
out_count = write (fd, buf, count);
if (out_count <= 0)
{
if(errno == EINTR || errno == EAGAIN)
{
errs--;
if(errs != 0)
continue;
}
break;
}
// fprintf(stdout, "%*s", out_count, buf);
errs = 10;
count -= out_count;
buf += out_count;
total += out_count;
}
return total;
}