X-Git-Url: http://git.jankratochvil.net/?p=gnokii.git;a=blobdiff_plain;f=common%2Fdevices%2Fdevice.c;h=bf48de3995749a4abcb37285b253e3dd0289d935;hp=9795a79680ba04f554930075e37ab14e49bed142;hb=253a25e0c1db3361620a7a14ca8249f072472299;hpb=5d49fe8eea4e11457b4f9904eb0d5db435679841 diff --git a/common/devices/device.c b/common/devices/device.c index 9795a79..bf48de3 100644 --- a/common/devices/device.c +++ b/common/devices/device.c @@ -24,6 +24,7 @@ #include "gsm-api.h" #include "devices/device.h" +#include "files/cfgreader.h" #include @@ -38,6 +39,8 @@ bool duringwrite; #ifndef WIN32 +char *lockfile; + //pthread_t Thread; #if defined(__svr4__) || defined(__FreeBSD__) pthread_t selThread; @@ -45,6 +48,110 @@ bool duringwrite; int device_portfd = -1; +#define max_buf_len 128 +#define lock_path "/var/lock/LCK.." + +/* Lock the device. Return allocated string with a lock name */ +char *lock_device(const char* port) +{ + char *lock_file = NULL; + char buffer[max_buf_len]; + const char *aux = rindex(port, '/'); + int fd, len = strlen(aux) + strlen(lock_path); + + /* Remove leading '/' */ + if (aux) aux++; + else aux = port; + + memset(buffer, 0, sizeof(buffer)); + lock_file = calloc(len + 1, 1); + if (!lock_file) { + fprintf(stderr, _("Out of memory error while locking device\n")); + return NULL; + } + /* I think we don't need to use strncpy, as we should have enough + * buffer due to strlen results + */ + strcpy(lock_file, lock_path); + strcat(lock_file, aux); + + /* Check for the stale lockfile. + * The code taken from minicom by Miquel van Smoorenburg */ + if ((fd = open(lock_file, O_RDONLY)) >= 0) { + char buf[max_buf_len]; + int pid, n = 0; + + n = read(fd, buf, sizeof(buf) - 1); + close(fd); + if (n > 0) { + pid = -1; + if (n == 4) + /* Kermit-style lockfile. */ + pid = *(int *)buf; + else { + /* Ascii lockfile. */ + buf[n] = 0; + sscanf(buf, "%d", &pid); + } + if (pid > 0 && kill((pid_t)pid, 0) < 0 && errno == ESRCH) { + fprintf(stderr, _("Lockfile %s is stale. Overriding it..\n"), lock_file); + sleep(1); + if (unlink(lock_file) == -1) { + fprintf(stderr, _("Overriding failed, please check the permissions\n")); + fprintf(stderr, _("Cannot lock device\n")); + goto failed; + } + } else { + fprintf(stderr, _("Device already locked.\n")); + goto failed; + } + } + /* this must not happen. because we could open the file */ + /* no wrong permissions are set. only reason could be */ + /* flock/lockf or a empty lockfile due to a broken binary */ + /* which is more likely (like gnokii 0.4.0pre11 ;-) */ + if (n == 0) { + fprintf(stderr, _("Unable to read lockfile %s.\n"), lock_file); + fprintf(stderr, _("Please check for reason and remove the lockfile by hand.\n")); + fprintf(stderr, _("Cannot lock device\n")); + goto failed; + } + } + + /* Try to create a new file, with 0644 mode */ + fd = open(lock_file, O_CREAT | O_EXCL | O_WRONLY, 0644); + if (fd == -1) { + if (errno == EEXIST) + fprintf(stderr, _("Device seems to be locked by unknown process\n")); + else if (errno == EACCES) + fprintf(stderr, _("Please check permission on lock directory\n")); + else if (errno == ENOENT) + fprintf(stderr, _("Cannot create lockfile %s. Please check for existence of path"), lock_file); + goto failed; + } + sprintf(buffer, "%10ld gnokii\n", (long)getpid()); + write(fd, buffer, strlen(buffer)); + close(fd); + return lock_file; +failed: + free(lock_file); + return NULL; +} + +/* Removes lock and frees memory */ +bool unlock_device(char *lock_file) +{ + int err; + + if (!lock_file) { +// fprintf(stderr, _("Cannot unlock device\n")); + return false; + } + err = unlink(lock_file); + free(lock_file); + return (err + 1); +} + /* * Structure to store the filedescriptor we use. * @@ -55,7 +162,20 @@ int device_getfd(void) } int device_open(__const char *__file, int __with_odd_parity) { - + struct CFG_Header *cfg_info; + char *aux; + + cfg_info=CFG_FindGnokiirc(); + if (cfg_info!=NULL) { + aux = CFG_Get(cfg_info, "global", "use_locking"); + if (aux) { + if (!strcmp(aux, "yes")) { + lockfile = lock_device(__file); + if (!lockfile) return false; + } + } + } + switch (CurrentConnectionType) { case GCT_Tekram: device_portfd = tekram_open(__file); @@ -78,6 +198,8 @@ void device_close(void) /* Now wait for thread to terminate. */ //pthread_join(Thread, NULL); + unlock_device(lockfile); + switch (CurrentConnectionType) { case GCT_Tekram: tekram_close(device_portfd); break; case GCT_Irda : irda_close(device_portfd); break;