From aede7e0121a037fd7226a8bfd558eb21a932fa5a Mon Sep 17 00:00:00 2001
From: Samo Penic <samo.penic@gmail.com>
Date: Wed, 14 Aug 2019 21:30:25 +0000
Subject: [PATCH] Added additional functions to ease Ulm2 poststating

---
 src/general.c |  121 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 119 insertions(+), 2 deletions(-)

diff --git a/src/general.c b/src/general.c
index ed06398..6b8a99c 100644
--- a/src/general.c
+++ b/src/general.c
@@ -1,12 +1,27 @@
+/* vim: set ts=4 sts=4 sw=4 noet : */
 #include<stdio.h>
 #include<stdlib.h>
 #include "general.h"
 #include<stdarg.h>
 
+#include <sys/time.h>
+#include <unistd.h>
+#include <time.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
 ts_uint ts_fprintf(FILE *fd, char *fmt, ...){
 if(quiet) return TS_SUCCESS;
-    va_list ap;
-    va_start(ap,fmt);
+	va_list ap;
+	va_start(ap,fmt);
+	char tmbuf[255];
+	struct timeval now;
+  	gettimeofday(&now, 0);
+	strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d %H:%M:%S", localtime(&now.tv_sec));
+fprintf(fd, "[%s] ",tmbuf); 
 vfprintf(fd, fmt, ap); /* Call vfprintf */
 va_end(ap); /* Cleanup the va_list */
 return TS_SUCCESS;
@@ -22,3 +37,105 @@
 }
 
 
+/* Open/create the file named in 'pidFile', lock it, optionally set the
+   close-on-exec flag for the file descriptor, write our PID into the file,
+   and (in case the caller is interested) return the file descriptor
+   referring to the locked file. The caller is responsible for deleting
+   'pidFile' file (just) before process termination. 'progName' should be the
+   name of the calling program (i.e., argv[0] or similar), and is used only for
+   diagnostic messages. If we can't open 'pidFile', or we encounter some other
+   error, then we print an appropriate diagnostic and terminate. */
+
+/* 
+ This is filelock/create_pid_file.c (Listing 55-4, page 1143), an example program file from the book, The Linux Programming Interface.
+
+The source code file is copyright 2010, Michael Kerrisk, and is licensed under the GNU Lesser General Public License, version 3. 
+*/
+
+#define BUF_SIZE 100
+int createPidFile(const char *progName, const char *pidFile, int flags)
+{
+    int fd;
+    char buf[BUF_SIZE];
+
+    fd = open(pidFile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+    if (fd == -1){
+        ts_fprintf(stderr,"Could not open PID file %s", pidFile);
+	fatal("Cannot continue (1)",1);
+}
+    if (flags & CPF_CLOEXEC) {
+
+        /* Set the close-on-exec file descriptor flag */
+
+        /* Instead of the following steps, we could (on Linux) have opened the
+           file with O_CLOEXEC flag. However, not all systems support open()
+           O_CLOEXEC (which was standardized only in SUSv4), so instead we use
+           fcntl() to set the close-on-exec flag after opening the file */
+
+        flags = fcntl(fd, F_GETFD);                     /* Fetch flags */
+        if (flags == -1){
+            ts_fprintf(stderr,"Could not get flags for PID file %s", pidFile);
+	fatal("Cannot continue (2)",1);
+}
+        flags |= FD_CLOEXEC;                            /* Turn on FD_CLOEXEC */
+
+        if (fcntl(fd, F_SETFD, flags) == -1)            /* Update flags */
+            ts_fprintf(stderr,"Could not set flags for PID file %s", pidFile);
+		fatal("Cannot continue (3)",1);
+	    
+    }
+
+    if (lockRegion(fd, F_WRLCK, SEEK_SET, 0, 0) == -1) {
+        if (errno  == EAGAIN || errno == EACCES){
+            ts_fprintf(stderr,"PID file '%s' is locked; probably "
+                     "'%s' is already running", pidFile, progName);
+		fatal("Cannot continue (4)",1);
+}
+        else{
+            ts_fprintf(stderr,"Unable to lock PID file '%s'", pidFile);
+	fatal("Cannot continue (5)",1);
+}
+    }
+
+    if (ftruncate(fd, 0) == -1){
+        ts_fprintf(stderr,"Could not truncate PID file '%s'", pidFile);
+	fatal("Cannot continue (6)",1);
+}
+
+    snprintf(buf, BUF_SIZE, "%ld\n", (long) getpid());
+    if (write(fd, buf, strlen(buf)) != strlen(buf)){
+
+        ts_fprintf(stderr,"Writing to PID file '%s'", pidFile);
+	fatal("Cannot continue (7)",1);
+}
+    return fd;
+}
+
+
+
+/* Lock a file region (private; public interfaces below) */
+
+static int
+lockReg(int fd, int cmd, int type, int whence, int start, off_t len)
+{
+    struct flock fl;
+
+    fl.l_type = type;
+    fl.l_whence = whence;
+    fl.l_start = start;
+    fl.l_len = len;
+
+    return fcntl(fd, cmd, &fl);
+}
+
+
+int                     /* Lock a file region using nonblocking F_SETLK */
+lockRegion(int fd, int type, int whence, int start, int len)
+{
+    return lockReg(fd, F_SETLK, type, whence, start, len);
+}
+
+
+char *libVersion(){
+	return TS_VERSION;
+}

--
Gitblit v1.9.3