X-Git-Url: https://git.jankratochvil.net/?p=gnokii.git;a=blobdiff_plain;f=common%2Fdevices%2Fdevice.c;h=b002239d429e6bb7b8de71fd40ecf2eeded5093f;hp=be2f079f46811131ea06eb439b509dfd7cb23be7;hb=82bcbc2300f764bcb3551b152a0a961f4fef5e66;hpb=975a83d253eea8aa37bf3dfd7e026df3027db4ff diff --git a/common/devices/device.c b/common/devices/device.c index be2f079..b002239 100644 --- a/common/devices/device.c +++ b/common/devices/device.c @@ -16,6 +16,7 @@ #include #include #include + #include #else #include #include "devices/winserial.h" @@ -23,6 +24,7 @@ #include "gsm-api.h" #include "devices/device.h" +#include "files/cfgreader.h" #include @@ -37,6 +39,10 @@ static bool duringwrite; #ifndef WIN32 +#ifndef UCLINUX +char *lockfile; +#endif /* UCLINUX */ + //pthread_t Thread; #if defined(__svr4__) || defined(__FreeBSD__) pthread_t selThread; @@ -44,6 +50,114 @@ static bool duringwrite; int device_portfd = -1; +#define max_buf_len 128 +#define lock_path "/var/lock/LCK.." + +#ifndef UCLINUX + +/* 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; + pid = atoi(buf); + } + 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); +} + +#endif /* UCLINUX */ + /* * Structure to store the filedescriptor we use. * @@ -56,7 +170,22 @@ static int device_getfd(void) #endif /* DEBUG */ static int device_open(__const char *__file, int __with_odd_parity) { - +#ifndef UCLINUX + 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; + } + } + } +#endif /* UCLINUX */ + switch (CurrentConnectionType) { default: device_portfd = serial_opendevice(__file, __with_odd_parity, true, false); @@ -73,6 +202,10 @@ void device_close(void) /* Now wait for thread to terminate. */ //pthread_join(Thread, NULL); +#ifndef UCLINUX + unlock_device(lockfile); +#endif /* UCLINUX */ + switch (CurrentConnectionType) { default : serial_close(device_portfd); break; }