/* common stuff for cgi-fcgi-interp and prefork-interp */
+/*
+ * Copyright 2016-2022 Ian Jackson and contributors to chiark-utils
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ * There is NO WARRANTY.
+ */
#include "prefork.h"
const char *interp, *ident, *script, *socket_path, *lock_path;
bool logging;
struct sha256_ctx identsc;
+const char *run_base;
static uid_t us;
-static const char *run_base;
static const char *run_base_mkdir_p;
void common_diee(const char *m) { diee("%s", m); }
*ci->iassignto = v;
}
-void ident_addstring(const struct cmdinfo *ci, const char *string) {
- /* ci may be 0 and is provided so this can be .call */
+void ident_add_key_byte(char key) {
+ sha256_update(&identsc,1,&key);
+}
+
+void ident_addstring(char key, const char *string) {
+ ident_add_key_byte(key);
sha256_update(&identsc,strlen(string)+1,string);
}
+void off_ident_addstring(const struct cmdinfo *ci, const char *string) {
+ ident_addstring('G', string);
+}
+
void off_ident_addenv(const struct cmdinfo *ci, const char *name) {
+ ident_addstring('E', name);
const char *val = getenv(name);
if (val) {
- sha256_update(&identsc,strlen(name),name); /* no nul */
- sha256_update(&identsc,1,"=");
- ident_addstring(0,val);
+ ident_addstring('v', val);
} else {
- ident_addstring(0,name);
+ ident_add_key_byte(0);
}
}
+bool stabs_same_inode(struct stat *a, struct stat *b) {
+ return (a->st_dev == b->st_dev &&
+ a->st_ino == b->st_ino);
+}
+
bool find_run_base_var_run(void) {
struct stat stab;
char *try;
unsigned char bbuf[32];
int i;
- ident_addstring(0,interp);
+ ident_addstring('i', interp);
if (script)
- ident_addstring(0,script);
+ ident_addstring('s', script);
sha256_digest(&identsc,sizeof(bbuf),bbuf);
for (i=0; i<identlen; i += 2)
}
// Returns fd
-int acquire_lock(void) {
+int flock_file(const char *lock_path) {
int r;
int lockfd = -1;
+ struct stat stab_fd;
+ struct stat stab_path;
- lock_path = m_asprintf("%s/l%s",run_base,ident);
+ for (;;) {
+ if (lockfd >= 0) { close(lockfd); lockfd = -1; }
+
+ lockfd = open(lock_path, O_CREAT|O_RDWR, 0600);
+ if (lockfd<0) diee("create lock (%s)", lock_path);
- lockfd = open(lock_path, O_CREAT|O_RDWR, 0600);
- if (lockfd<0) diee("create lock (%s)", lock_path);
+ r = flock(lockfd, LOCK_EX);
+ if (r && errno == EINTR) continue;
+ if (r) diee("lock lock (%s)", lock_path);
- r = flock(lockfd, LOCK_EX);
- if (r) diee("lock lock (%s)", lock_path);
+ r = fstat(lockfd, &stab_fd);
+ if (r) diee("fstat locked lock");
+
+ r = stat(lock_path, &stab_path);
+ if (!r) {
+ if (stabs_same_inode(&stab_path, &stab_fd)) break;
+ } else {
+ if (!(errno == ENOENT)) diee("re-stat locked lock (%s)", lock_path);
+ }
+ }
return lockfd;
}
+// Returns fd
+int acquire_lock(void) {
+ lock_path = m_asprintf("%s/l%s",run_base,ident);
+ return flock_file(lock_path);
+}
+
static void shbang_opts(const char *const **argv_io,
const struct cmdinfo *cmdinfos) {
myopt(argv_io, cmdinfos);