#include "prefork.h"
-const char *interp, *ident;
-
+const char *interp, *ident, *script, *socket_path, *lock_path;
+bool logging;
struct sha256_ctx identsc;
-uid_t us;
-const char *run_base, *script, *socket_path, *lock_path;
-const char *run_base_mkdir_p;
-bool logging;
+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); }
void common_die (const char *m) { die ("%s", m); }
if (logging) {
const char *fmt_use = fmt;
char *fmt_free = 0;
- if (errnoval) {
+ if (errnoval!=-1) {
r = asprintf(&fmt_free, "%s: %%m", fmt);
if (r) {
fmt_free = 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;
int i;
ident_addstring(0,interp);
- ident_addstring(0,script);
+ if (script)
+ ident_addstring(0,script);
sha256_digest(&identsc,sizeof(bbuf),bbuf);
for (i=0; i<identlen; i += 2)
int acquire_lock(void) {
int r;
int lockfd = -1;
+ struct stat stab_fd;
+ struct stat stab_path;
lock_path = m_asprintf("%s/l%s",run_base,ident);
- lockfd = open(lock_path, O_CREAT|O_RDWR, 0600);
- if (lockfd<0) diee("create lock (%s)", lock_path);
+ 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);
- r = flock(lockfd, LOCK_EX);
- if (r) diee("lock lock (%s)", lock_path);
+ r = flock(lockfd, LOCK_EX);
+ if (r && errno == EINTR) continue;
+ 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;
}
const char *smashedopt;
sha256_init(&identsc);
+ ident_addinit();
if ((*argv_io)[0] &&
(smashedopt = (*argv_io)[1]) &&
shbang_opts(&split_argv, cmdinfos);
/* sets interp */
+
+ if (!**argv_io)
+ badusage("no script argument (expected after combined #! options)");
} else {
shbang_opts(argv_io, cmdinfos);
}