From c35f713ae46fef0bf5d5dbab434c2f581e1d1181 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 Dec 2003 23:20:10 +0000 Subject: many more stuff git-svn-id: file:///home/lennart/svn/public/ivam2/trunk@5 dbf6933d-3bce-0310-9bcc-ed052ba35b35 --- src/Makefile | 9 +++++ src/lock.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lock.h | 7 ++++ src/main.c | 43 +++++++++++++-------- src/main.h | 8 ++++ src/modem.c | 92 +++++++++++++++++++++++++++++++++++++++++-- src/modem.h | 9 ++++- src/modemman.c | 60 +++++++++++++++++++++++++++++ src/modemman.h | 2 +- src/util.c | 44 +++++++++++++++++++++ src/util.h | 8 ++++ 11 files changed, 381 insertions(+), 21 deletions(-) create mode 100644 src/Makefile create mode 100644 src/lock.c create mode 100644 src/lock.h create mode 100644 src/main.h create mode 100644 src/modemman.c create mode 100644 src/util.c create mode 100644 src/util.h diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..7269fde --- /dev/null +++ b/src/Makefile @@ -0,0 +1,9 @@ +CC=gcc +CFLAGS=`pkg-config --cflags libdaemon shbuf` -Wall -O2 -pipe +LIBS=`pkg-config --libs libdaemon shbuf` + +ivamd: modem.o main.o + $(CC) $(LIBS) -o $@ $^ + +clean: + rm -f *.o ivamd diff --git a/src/lock.c b/src/lock.c new file mode 100644 index 0000000..48c409f --- /dev/null +++ b/src/lock.c @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "lock.h" + +/* Where do lockfiles reside? */ +#define LOCK_PATH "/var/lock" + +static const char *lockfile(const char *dev) { + static char lockfile[PATH_MAX]; + snprintf(lockfile, sizeof(lockfile), "%s/LCK..%s", LOCK_PATH, basename(dev)); + return lockfile; +} + +static const char *tempfile(const char *path) { + static char t[PATH_MAX]; + snprintf(t, sizeof(t), "%s.tmp.%lu", path, (unsigned long) getpid()); + return t; +} + +int device_lock(const char *dev) { + struct stat st; + int fd; + char *path, *temp; + char buf[100]; + + if (stat(LOCK_PATH, &st) != 0 || !S_ISDIR(st.st_mode)) { + daemon_log(LOG_ERR, "Failed to lock device, directory "LOCK_PATH" not existent."); + return -1; + } + + path = lockfile(dev); + temp = tempfile(path); + + for (;;) { + + if ((fd = open(path, O_RDONLY)) < 0) { + if (errno != ENOENT) { + daemon_log(LOG_ERR, "Failed to open lock file: %s", strerror(errno)); + return -1; + } + } + + if (fd >= 0) { + ssize_t n; + + n = loop_read(fd, buf, sizeof(buf) - 1); + close(fd); + + if (n < 0) { + close(fd) + daemon_log(LOG_ERR, "Failed to read from lock file: %s", strerror(errno)); + return -1; + } + + if (n > 0) { + pid_t pid; + + if (n == 4) + pid = (pid_t) *((uint32_t*) buf); + else { + buf[n] = 0; + sscanf(buf, "%lu", &pid); + } + + if (pid > 0) { + if (kill(pid, 0) < 0 && errno == ESRCH) { + daemon_log(LOG_WARN, "Lockfile is stale. Overriding it."); + /* Yes, here is a race condition */ + unlink(path); + } else + return 1; + } + } + } + + if ((fd = open(temp, O_WRONLY | O_CREAT | O_EXCL, 0666)) < 0) { + daemon_log(LOG_ERR, "Failed to create temporary lock file: %s", strerror(errno)); + return -1; + } + + snprintf(buf, sizeof(buf), "%10lu %s %.20s\n", (unsigned long) getpid(), appname, username); + if (loop_write(fd, buf, strlen(buf)) < 0) { + daemon_log(LOG_ERR, "Failed to write to temporary lock file: %s", sterror(errno)); + close(fd); + return -1; + } + + close(fd); + + if (link(temp, path) < 0) { + if (errno == EEXIST) + continue; + + daemon_log(LOG_ERR, "Failed to link temporary lock file: %s", strerror(errno)); + } + + + return 0; + } +} + +int device_unlock(const char *dev) { + + if (unlink(lockfile(dev)) < 0) { + daemon_log(LOG_ERR, "Failed to remove lock file: %s", strerror(errno)); + return -1; + } + + return 0; +} diff --git a/src/lock.h b/src/lock.h new file mode 100644 index 0000000..cd201a0 --- /dev/null +++ b/src/lock.h @@ -0,0 +1,7 @@ +#ifndef foolockhfoo +#define foolockhfoo + +int device_lock(const char *dev); +int device_unlock(const char *dev); + +#endif diff --git a/src/main.c b/src/main.c index db4c438..9fac796 100644 --- a/src/main.c +++ b/src/main.c @@ -2,30 +2,41 @@ #include "main.h" -int init(void) { - if (modem_manager_init(CHANNELS) < 0) - return -1; - -} +#define CHANNELS (2) -void done(void) { - - modem_manager_done(CHANNELS); - -} +oop_source* event_source = NULL; int main_loop(void) { + int r = -1; + oop_source_sys *sys = NULL; + + if (!(sys = oop_sys_new())) { + daemon_log(LOG_ERR, "Failed to create system source"); + goto finish; + } + event_source = oop_sys_source(sys); + assert(event_source); - if (init() < 0) - return -1; + if (modem_manager_init(CHANNELS) < 0) + goto finish; - for (;;) { - /* ... */ + if (oop_sys_run(sys) == OOP_ERROR) { + daemon_log(LOG_ERR, "oop_sys_new() returned OOP_ERROR"); + goto finish; } - - done(); + r = 0; + +finish: + modem_manager_done(); + + if (sys) { + event_source = NULL; + oop_sys_delete(sys); + } + + return r; } int main(int argc, char*argv[]) { diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..3aef24b --- /dev/null +++ b/src/main.h @@ -0,0 +1,8 @@ +#ifndef foomainhfoo +#define foomainhfoo + +#include + +extern oop_source* event_source; + +#endif diff --git a/src/modem.c b/src/modem.c index dd2cf75..44eec06 100644 --- a/src/modem.c +++ b/src/modem.c @@ -1,8 +1,94 @@ #include "modem.h" +#include "lock.h" -int modem_open(const char *dev) { -} +/* Baudrate for the TTY. Should be greater the 64000. */ +#define BAUD_RATE B115200 + +struct modem *modem_open(const char *dev) { + struct modem *m; + int fd = -1, n; + struct termios ts, ts2; + + assert(dev); + + if (device_lock(dev) != 0) + return -1; + + if ((fd = open(dev, O_RDWR|O_NDELAY)) < 0) { + daemon_log(LOG_ERR, "Failed to open device <%s>: %s", dev, strerror(errno)); + goto fail; + } + + if ((n = fcntl(fd, F_GETFL, 0)) < 0 || fcntl(fd, F_SETFL, n & ~O_NDELAY) < 0) { + daemon_log(LOG_ERR, "Failed to remove O_NDELAY flag from device: %s", strerror(errno)); + goto fail; + } + + memset(&ts, 0, sizeof ts); + ts.c_cflag = CRTSCTS | IGNPAR | HUPCL | CS8; + ts.c_iflag = IGNPAR; + ts.c_oflag = 0; + ts.c_lflag = 0; + + ts.c_cc[VMIN] = 1; + ts.c_cc[VTIME] = 0; + + cfsetospeed(&ts, BAUD_RATE); + cfsetispeed(&ts, BAUD_RATE); + + tcflush(fd, TCIFLUSH); + + if (tcsetattr(fd, TCSANOW, &ts) < 0) { + daemon_log(LOG_ERR, "Failed to set TTY attributes: %s", strerror(errno)); + goto fail; + } + + if (tcgetattr(fd, &ts2) < 0 || memcmp(&ts, &ts2) != 0) { + daemon_log(LOG_ERR, "Failed to set TTY attributes"); + goto fail; + } + + m = malloc(sizeof(struct modem)); + assert(m); + memset(m, 0, sizeof(struct modem)); + m->dev = strdup(dev); + assert(m->dev); + m->fd = fd; + m->state = MODEM_STATE_INIT; -int modem_close(int fd) { + return m; + +fail: + if (fd >= 0) + close(fd); + + device_unlock(dev); + + return NULL; } + +void modem_close(struct modem *m) { + assert(m); + device_unlock(m->dev); + + close(m->fd); + free(m->dev); + free(m); +} + +static void* modem_cb(oop_source *source, int fd, oop_event event, void *user) { + struct modem *m; + + assert(source && user); + m = (struct modem*) user; + + if (m->mode == MODEM_STATE_INIT) { + } else if (m->mode == MODEM_STATE_AUDIO) { + + if (event) + } + + return OOP_CONTINUE; +} + diff --git a/src/modem.h b/src/modem.h index e8a4ec1..edcfefd 100644 --- a/src/modem.h +++ b/src/modem.h @@ -1,11 +1,18 @@ #ifndef foomodemhfoo #define foomodemhfoo -enum modem_state { MODEM_STATE_DISABLED, MODEM_STATE_INIT, MODEM_STATE_AUDIO }; +enum modem_state { MODEM_STATE_INIT, MODEM_STATE_AUDIO }; struct modem { char *dev; int fd; + + char *ouput_buf; + size_t output_buf_len; + + char *input_buf; + size_t input_buf_len; + enum modem_state state; }; diff --git a/src/modemman.c b/src/modemman.c new file mode 100644 index 0000000..c156e61 --- /dev/null +++ b/src/modemman.c @@ -0,0 +1,60 @@ +#include "modemman.h" +#include "modem.h" + +#define MAX_CHANNELS 10 +#define TTY_START 11 + +struct llist { + struct modem *modem; + struct llist *next; +}; + +static struct llist *llist = NULL; +static int n_llist = 0; + +int modem_manager_init(int channels) { + int i; + + assert(channels <= MAX_CHANNELS && channels > 0); + assert(n_llist == 0); + + for (i = TTY_START; i < TTY_START+MAX_CHANNLES && n_llist < channels; i++) { + char d[PATH_MAX]; + struct modem *m; + + snprintf(d, sizeof(d), "/dev/ttyI%i", i); + + if (m = modem_open(d)) { + struct llist *l = malloc(sizeof(struct llist)); + assert(l); + + l->modem = m; + l->next = llist; + llist = l; + n_llist++; + } + } + + if (n_llist < channels) { + daemon_log(LOG_ERR, "Failed to allocate the requested channels. Got %i of %i.", n_llist, channels); + modem_manager_done(); + return -1; + } + + return 0; +} + +void modem_manager_done(void) { + + while (llist) { + struct llist *l; + + modem_close(l->modem); + l = llist; + llist = l->next; + free(l); + n_llist = 0; + } + + assert(!n_llist && !llist); +} diff --git a/src/modemman.h b/src/modemman.h index 31e5aa1..9e108b3 100644 --- a/src/modemman.h +++ b/src/modemman.h @@ -4,6 +4,6 @@ #include "modem.h" int modem_manager_init(int channels); -void modem_manager_done(); +void modem_manager_done(void); #endif diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000..415da09 --- /dev/null +++ b/src/util.c @@ -0,0 +1,44 @@ +#include "util.h" + +char *basename(const char *path) { + const char *p; + + if (p = strrchr(path, '/')) + return p+1; + + return path; +} + +ssize_t loop_read(int FILEDES, void *BUFFER, size_t SIZE) { + int c = 0; + + while (SIZE > 0) { + int r = read(FILEDES, BUFFER, SIZE); + + if (r <= 0) + break; + + SIZE -= r; + c += r; + BUFFER = ((void*) (((char*) BUFFER) + r)); + } + + return c; +} + +ssize_t loop_write(int FILEDES, const void *BUFFER, size_t SIZE) { + int c = 0; + + while (SIZE > 0) { + int r = write(FILEDES, BUFFER, SIZE); + + if (r <= 0) + break; + + SIZE -= r; + c += r; + BUFFER = ((void*) (((char*) BUFFER) + r)); + } + + return c; +} diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..2e0b2ae --- /dev/null +++ b/src/util.h @@ -0,0 +1,8 @@ +#ifndef fooutilhfoo +#define fooutilhfoo + +char *basename(const char *path); +ssize_t loop_read(int FILEDES, void *BUFFER, size_t SIZE); +ssize_t loop_write(int FILEDES, const void *BUFFER, size_t SIZE); + +#endif -- cgit