summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2003-12-15 23:20:10 +0000
committerLennart Poettering <lennart@poettering.net>2003-12-15 23:20:10 +0000
commitc35f713ae46fef0bf5d5dbab434c2f581e1d1181 (patch)
tree38465e471c62fcff64b4dedfb88f5564a4afd34e
parent6883bbb1e8fcdf359716dcd5af44ca6ece55b16b (diff)
many more stuff
git-svn-id: file:///home/lennart/svn/public/ivam2/trunk@5 dbf6933d-3bce-0310-9bcc-ed052ba35b35
-rw-r--r--src/Makefile9
-rw-r--r--src/lock.c120
-rw-r--r--src/lock.h7
-rw-r--r--src/main.c43
-rw-r--r--src/main.h8
-rw-r--r--src/modem.c92
-rw-r--r--src/modem.h9
-rw-r--r--src/modemman.c60
-rw-r--r--src/modemman.h2
-rw-r--r--src/util.c44
-rw-r--r--src/util.h8
11 files changed, 381 insertions, 21 deletions
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 <unistd.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libdaemon/dlog.h>
+
+#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 <oop.h>
+
+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