[Pkg-sysvinit-devel] Bug#484883: [sysvinit]: startpar 0.52 + Debian compat.
Kel Modderman
kel at otaku42.de
Sun Jan 4 14:51:50 UTC 2009
tags 484883 + patch
retitle 484883 update and patch startpar for Debian
thanks
Package: sysvinit
Version: 2.86.ds1-61
After discussion with Petter on IRC, we decided that startpar will remain
in sysvinit source package for time being. Therefore, I bring this bug report
back to a wishlist item to update startpar and make it work in Makefile mode
on Debian.
Attaching cumulative patch which contains the following logical changes:
* update to startpar 0.52 from 0.50
* apply patch from SuSE to make use of posix_fadvise(2)
* apply patch to make startpar work on Debian, including Makefile mode
* apply patch from #457896 to make sure scripts executed before /dev/pts is
available are treated as interactive
Thanks, Kel.
---
--- a/debian/startpar/Makefile
+++ b/debian/startpar/Makefile
@@ -1,4 +1,5 @@
-VERSION = 0.50
+VERSION = 0.52
+ISSUSE = -DNOTSUSE
INSTALL = install -m 755
INSTALL_DATA = install -m 644
@@ -7,11 +8,18 @@ sbindir = /sbin
mandir = /usr/share/man
man8dir = $(mandir)/man8
-OBJS = startpar.o makeboot.o proc.o
+SRCS = startpar.c makeboot.c proc.c
+HDRS = makeboot.h proc.h
+REST = COPYING Makefile startpar.8
+OBJS = $(SRCS:.c=.o)
CC = gcc
OPTFLAGS = -O2 -g -Wall -W
-CFLAGS = $(OPTFLAGS) -D_GNU_SOURCE
+CFLAGS = $(OPTFLAGS) -D_GNU_SOURCE $(ISSUSE)
+
+ifeq ($(MAKECMDGOALS),makeboot)
+CFLAGS += -DTEST
+endif
.c.o:
$(CC) $(CFLAGS) -DVERSION=\"$(VERSION)\" -c $<
@@ -19,10 +27,20 @@ CFLAGS = $(OPTFLAGS) -D_GNU_SOURCE
startpar: $(OBJS)
$(CC) $(CFLAGS) -DVERSION=\"$(VERSION)\" -o $@ $(OBJS)
+makeboot: makeboot.c
+
install: startpar
$(INSTALL) -d $(DESTDIR)$(sbindir) $(DESTDIR)$(man8dir)
$(INSTALL) startpar $(DESTDIR)$(sbindir)/.
$(INSTALL_DATA) startpar.8 $(DESTDIR)$(man8dir)/.
clean:
- rm -f startpar $(OBJS)
+ rm -f startpar makeboot $(OBJS)
+
+dest: clean
+ mkdir -p startpar-$(VERSION)
+ for file in $(SRCS) $(HDRS) $(REST) ; do \
+ cp -p $$file startpar-$(VERSION)/; \
+ done
+ tar -cps -jf startpar-$(VERSION).tar.bz2 startpar-$(VERSION)/*
+ rm -rf startpar-$(VERSION)/
--- a/debian/startpar/makeboot.c
+++ b/debian/startpar/makeboot.c
@@ -13,6 +13,12 @@
#include <errno.h>
#include <limits.h>
#include "makeboot.h"
+#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+static int o_flags = O_RDONLY;
+#endif
int tree_entries = 0;
@@ -158,11 +164,28 @@ void parse_makefile(const char *path)
char *s, *strp, *p;
struct makenode *node;
- if ((fp = fopen(path, "r")) == NULL) {
+#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
+ int fd;
+
+ if (getuid() == (uid_t)0)
+ o_flags |= O_NOATIME;
+ if ((fd = open(path, o_flags)) < 0) {
fprintf(stderr, "Can't open %s: %s\n", path, strerror(errno));
exit(1);
}
-
+ (void)posix_fadvise(fd, 0, 0, POSIX_FADV_WILLNEED);
+ (void)posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
+ (void)posix_fadvise(fd, 0, 0, POSIX_FADV_NOREUSE);
+
+ if ((fp = fdopen(fd, "r")) == NULL)
+#else
+ if ((fp = fopen(path, "r")) == NULL)
+#endif
+ {
+ fprintf(stderr, "Can't open %s: %s\n", path, strerror(errno));
+ exit(1);
+ }
+
while (fgets(buf, sizeof(buf), fp)) {
for (s = buf; *s && isspace(*s); s++)
;
@@ -198,6 +221,11 @@ void parse_makefile(const char *path)
}
}
}
+
+#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
+ (void)posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
+#endif
+
fclose(fp);
for (node = tree_list; node; node = node->next) {
@@ -233,16 +261,32 @@ static void filter_files(const char *dir
struct makenode *t, *next;
filter_prefix = prefix;
- snprintf(path, sizeof(path), RCDBASEDIR "/%s.d", dir);
+#ifdef SUSE /* SuSE */
+ snprintf(path, sizeof(path), "/etc/init.d/%s.d", dir);
+#else /* Debian */
+ snprintf(path, sizeof(path), "/etc/%s.d", dir);
+#endif
+#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
+ if ((i = open(path, o_flags|O_DIRECTORY|O_LARGEFILE)) >= 0) {
+ (void)posix_fadvise(i, 0, 0, POSIX_FADV_SEQUENTIAL);
+ (void)posix_fadvise(i, 0, 0, POSIX_FADV_NOREUSE);
+ }
+#endif
ndirs = scandir(path, &dirlist, dirfilter, alphasort);
+#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
+ if (i >= 0)
+ (void)posix_fadvise(i, 0, 0, POSIX_FADV_DONTNEED);
+#endif
/* mark all matching nodes */
- for (i = 0; i < ndirs; i++) {
- t = lookup_target(dirlist[i]->d_name + 3);
- if (t)
- t->status = 1;
- free(dirlist[i]);
+ if (ndirs >= 0) {
+ for (i = 0; i < ndirs; i++) {
+ t = lookup_target(dirlist[i]->d_name + 3);
+ if (t)
+ t->status = 1;
+ free(dirlist[i]);
+ }
+ free(dirlist);
}
- free(dirlist);
/* deselect non-matching nodes */
for (t = tree_list; t; t = next) {
next = t->next;
@@ -287,8 +331,10 @@ void check_run_files(const char *action,
{
char buf[4] = "rc0";
if (! strcmp(action, "boot")) {
- buf[2] = 'S';
- filter_files(buf, 'S', 0);
+#ifdef SUSE /* SuSE */
+ filter_files("boot", 'S', 0);
+ } else if (! strcmp(action, "halt")) {
+ filter_files("boot", 'K', 0);
} else if (! strcmp(action, "start")) {
buf[2] = *prev;
filter_files(buf, 'K', 1);
@@ -299,6 +345,19 @@ void check_run_files(const char *action,
filter_files(buf, 'K', 0);
buf[2] = *run;
filter_files(buf, 'S', 1);
+#else /* Debian */
+ filter_files("rcS", 'S', 0);
+ } else if (! strcmp(action, "start")) {
+ buf[2] = *prev;
+ filter_files(buf, 'S', 1);
+ buf[2] = *run;
+ filter_files(buf, 'S', 0);
+ } else {
+ buf[2] = *prev;
+ filter_files(buf, 'K', 1);
+ buf[2] = *run;
+ filter_files(buf, 'K', 0);
+#endif
}
}
@@ -340,6 +399,21 @@ struct makenode *pickup_task(void)
best = node;
}
}
+ if (best) {
+#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
+ char path[128];
+ int fd;
+ snprintf(path, sizeof(path), "/etc/init.d/%s", best->name);
+ if ((fd = open(path, o_flags|O_DIRECT)) >= 0) {
+ (void)posix_fadvise(fd, 0, 0, POSIX_FADV_WILLNEED);
+ (void)posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
+ (void)posix_fadvise(fd, 0, 0, POSIX_FADV_NOREUSE);
+ close(fd);
+ }
+#endif
+ blogger("service %s", best->name);
+ best->status = T_RUNNING;
+ }
return best;
}
@@ -354,6 +428,17 @@ void finish_task(struct makenode *node)
return;
for (n = node->select; n; n = n->next)
n->node->num_deps--;
+#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
+ {
+ char path[128];
+ int fd;
+ snprintf(path, sizeof(path), "/etc/init.d/%s", node->name);
+ if ((fd = open(path, o_flags|O_DIRECT)) >= 0) {
+ (void)posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
+ close(fd);
+ }
+ }
+#endif
node->status = T_FINISHED;
blogger("service %s done", node->name);
}
@@ -413,3 +498,42 @@ void dump_status(void)
node->name, node->status, node->num_deps, node->interactive, node->importance);
}
#endif
+
+#ifdef TEST
+void *xcalloc(size_t nmemb, size_t size)
+{
+ void *r;
+ if ((r = (void *)calloc(nmemb, size)) == 0) {
+ fprintf(stderr, "calloc: out of memory\n");
+ exit(1);
+ }
+ return r;
+}
+
+int main(int argc, char **argv)
+{
+ struct makenode *nodevec;
+ char makefile[64];
+
+ if (argc != 4) {
+ fprintf(stderr, "usage: makeboot <action> [<prev> <run>]\n");
+ goto out;
+ }
+
+ nodevec = xcalloc(1, sizeof(*nodevec));
+
+ snprintf(makefile, sizeof(makefile), "depend.%s", argv[1]);
+ parse_makefile(makefile);
+
+ fprintf(stderr, "check_run_files(%s, %s, %s)\n", argv[1], argv[2],
+ argv[3]);
+ check_run_files(argv[1], argv[2], argv[3]);
+out:
+ while ((nodevec = pickup_task())) {
+ fprintf(stdout, "%s\n", nodevec->name);
+ finish_task(nodevec);
+ }
+
+ return 0;
+}
+#endif
--- a/debian/startpar/makeboot.h
+++ b/debian/startpar/makeboot.h
@@ -33,12 +33,3 @@ extern struct makenode *pickup_task(void
extern void finish_task(struct makenode *n);
extern void *xcalloc(size_t nmemb, size_t size);
extern void print_run_result(int *resvec, struct makenode **nodevec, const char *action);
-
-/* SUSE and Debian */
-#define INITDDIR "/etc/init.d"
-
-#if 0 /* SUSE */
-# define RCDBASEDIR "/etc/init.d"
-#else /* Debian */
-# define RCDBASEDIR "/etc"
-#endif
--- a/debian/startpar/startpar.c
+++ b/debian/startpar/startpar.c
@@ -31,6 +31,7 @@
#include <sys/ioctl.h>
#include <sys/sysinfo.h>
#include <sys/stat.h>
+#include <sys/vfs.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
@@ -40,6 +41,8 @@
#include "makeboot.h"
#include "proc.h"
+#define timerdiff(n,l) (__extension__ ({ (((n).tv_sec-(l).tv_sec)*1000)+(((n).tv_usec-(l).tv_usec)/1000); }))
+
typedef enum _boolean {false, true} boolean;
extern char *optarg;
extern int optind;
@@ -48,8 +51,13 @@ static long int numcpu = -1;
static char *myname;
static struct termios tio;
static struct winsize wz;
-static int wzok;
+static struct {
+ char env_row[128];
+ char env_col[128];
+} sz;
+static sig_atomic_t wzok;
static char *arg;
+static boolean isstart;
static struct sigaction sa;
static struct timeval glastio;
static struct timeval now;
@@ -72,7 +80,7 @@ struct prg {
static struct prg *prgs;
static int inpar, par;
static int pidpipe[2];
-static int iorate = 800;
+static double iorate = 800.0;
void *xcalloc(size_t nmemb, size_t size)
{
@@ -124,7 +132,9 @@ void waitsplash()
int status;
if (!splashpid)
return;
- waitpid(splashpid, &status, 0);
+ do {
+ waitpid(splashpid, &status, 0);
+ } while (errno == EINTR);
splashpid = 0;
}
@@ -181,8 +191,8 @@ void callsplash(int n, char *path, char
splashpid = pid;
return;
}
- close(1);
- dup(2);
+ while (dup2(2, 1) < 0 && (errno == EINTR))
+ ;
closeall();
execl("/sbin/splash", "splash", "-p", sbuf, "-t", tbuf, splashcfg, (char *)0);
_exit(1);
@@ -204,11 +214,10 @@ void writebuf(struct prg *p)
p->len -= r;
b += r;
}
- glastio.tv_sec = now.tv_sec;
- glastio.tv_usec = now.tv_usec;
+ glastio = now;
}
-static int checksystem(const int par, const char *mode, const boolean limit)
+static int checksystem(const int par, const boolean start, const boolean limit)
{
const int pg_size = sysconf(_SC_PAGESIZE);
const long int minphys_bytes = (sysconf(_SC_LONG_BIT) > 32L) ? (2<<22) : (2<<21);
@@ -223,7 +232,7 @@ static int checksystem(const int par, co
if (pg_size < 0)
return par;
- if (mode && strcmp(mode, "stop") == 0)
+ if (!start)
minphys_pg = avphys_pg;
else
minphys_pg = minphys_bytes / pg_size;
@@ -240,8 +249,8 @@ static int checksystem(const int par, co
if (read_proc(&prcs_run, &prcs_blked))
return par;
- newpar = (par*numcpu) - prcs_run + 1; /* +1 for startpar its self */
- newpar -= (prcs_blked * iorate); /* I/O load reduction */
+ newpar = (par*numcpu) - prcs_run + 1; /* +1 for startpar its self */
+ newpar -= (int)(((double)prcs_blked)*iorate); /* I/O load reduction */
#if DEBUG
fprintf(stderr, "checksystem par=%d newpar=%d (prcs_run=%u) %ld\n", par, newpar, prcs_run, time(0));
@@ -253,14 +262,70 @@ static int checksystem(const int par, co
return newpar;
}
-static inline int checklimit(const int par, const char *mode)
+static inline int checklimit(const int par, const boolean start)
{
- return checksystem(par, mode, true);
+ return checksystem(par, start, true);
}
-static inline int checkpar(const int par, const char *mode)
+static inline int checkpar(const int par, const boolean start)
{
- return checksystem(par, mode, false);
+ return checksystem(par, start, false);
+}
+
+/*
+ * Based on __posix_openpt() from glibc. Reimplemented here to work
+ * around the problem with getpt() failing for the entire process life
+ * time if /dev/pts/ is missing the first time it is called but
+ * mounted while the process is running. BSD style pts is not
+ * supported, but might be copied from glibc too if there is need.
+ */
+#define DEVFS_SUPER_MAGIC 0x1373
+#define DEVPTS_SUPER_MAGIC 0x1cd1
+
+static int startpar_getpt(void) {
+ int fd = open("/dev/ptmx", O_RDWR|O_NOCTTY);
+
+ if (fd != -1)
+ {
+ struct statfs fsbuf;
+
+ /* Check that the /dev/pts filesystem is mounted
+ or if /dev is a devfs filesystem (this implies /dev/pts). */
+ if ((statfs ("/dev/pts", &fsbuf) == 0
+ && fsbuf.f_type == DEVPTS_SUPER_MAGIC)
+ || (statfs ("/dev", &fsbuf) == 0
+ && fsbuf.f_type == DEVFS_SUPER_MAGIC))
+ {
+ /* Everything is ok, switch to the getpt() in libc. */
+ return fd;
+ }
+
+ /* If /dev/pts is not mounted then the UNIX98 pseudo terminals
+ are not usable. */
+ close (fd);
+ }
+
+ return -1;
+}
+
+static int checkdevpts(void)
+{
+ int ptsfd = startpar_getpt();
+
+ if (ptsfd == -1)
+ {
+ return 0;
+ }
+ else if (ptsname(ptsfd) == 0 || grantpt(ptsfd) || unlockpt(ptsfd))
+ {
+ close(ptsfd);
+ return 0;
+ }
+ else
+ {
+ close(ptsfd);
+ return 1;
+ }
}
void run(struct prg *p)
@@ -301,39 +366,45 @@ void run(struct prg *p)
(void)signal(SIGQUIT, SIG_DFL);
(void)signal(SIGSEGV, SIG_DFL);
(void)signal(SIGTERM, SIG_DFL);
+ (void)signal(SIGCHLD, SIG_DFL);
if (setpgid(0, 0))
perror("setpgid");
if (m && p->fd)
{
- close(1);
+ while (close(1) < 0 && (errno == EINTR))
+ ;
if (open(m, O_RDWR) != 1)
{
perror(m);
_exit(1);
}
- close(2);
- dup(1);
+ while (dup2(1, 2) < 0 && (errno == EINTR))
+ ;
tio.c_oflag &= ~OPOST;
if (tcsetattr(1, TCSANOW, &tio))
perror("tcsetattr");
- if (wzok && ioctl(0, TIOCSWINSZ, &wz))
- perror("TIOCSWINSZ");
+ if (wzok)
+ ioctl(1, TIOCSWINSZ, &wz);
+ putenv(sz.env_row);
+ putenv(sz.env_col);
}
else
{
- close(1);
- dup(2);
+ while (dup2(2, 1) < 0 && (errno == EINTR))
+ ;
}
closeall();
- if (run_mode) {
- char path[128];
- snprintf(path, sizeof(path), INITDDIR "/%s", p->name);
- execlp(path, path, arg, (char *)0);
- } else if (arg)
+ if (run_mode)
+ {
+ char path[128];
+ snprintf(path, sizeof(path), "/etc/init.d/%s", p->name);
+ execlp(path, path, arg, (char *)0);
+ }
+ else if (arg)
execlp(p->name, p->name, arg, (char *)0);
else
execlp(p->name, p->name, (char *)0);
@@ -359,14 +430,15 @@ int run_single(char *prg, int spl)
(void)signal(SIGQUIT, SIG_DFL);
(void)signal(SIGSEGV, SIG_DFL);
(void)signal(SIGTERM, SIG_DFL);
+ (void)signal(SIGCHLD, SIG_DFL);
- close(1);
- dup(2);
+ while (dup2(2, 1) < 0 && (errno == EINTR))
+ ;
closeall();
if (run_mode)
{
char path[128];
- snprintf(path, sizeof(path), INITDDIR "/%s", prg);
+ snprintf(path, sizeof(path), "/etc/init.d/%s", prg);
execlp(path, path, arg, (char *)0);
}
else if (arg)
@@ -377,7 +449,7 @@ int run_single(char *prg, int spl)
_exit(1);
}
- while (waitpid(pid, &r, 0) == (pid_t)-1)
+ while ((waitpid(pid, &r, 0) == (pid_t)-1) && (errno == EINTR))
;
callsplash(spl, prg, arg);
return WIFEXITED(r) ? WEXITSTATUS(r) : (WIFSIGNALED(r) ? 1 : 255);
@@ -420,8 +492,7 @@ void storebuf(struct prg *p)
(void)memcpy(gtimo_buf + gtimo_buflen, p->buf, p->len);
gtimo_buflen += p->len;
p->len = 0;
- glastio.tv_sec = now.tv_sec;
- glastio.tv_usec = now.tv_usec;
+ glastio = now;
}
void flushbuf(void)
@@ -475,10 +546,10 @@ void detach(struct prg *p, const int sto
{
if ((r = fork()) == 0)
{
- close(0);
- dup(p->fd);
- close(1);
- dup(2);
+ while (dup2(p->fd, 0) < 0 && (errno == EINTR))
+ ;
+ while (dup2(2, 1) < 0 && (errno == EINTR))
+ ;
closeall();
execlp(myname, myname, "-f", "--", p->name, NULL);
do_forward();
@@ -490,12 +561,25 @@ void detach(struct prg *p, const int sto
p->fd = 0;
}
-void sigchld(int sig __attribute__ ((unused)))
+static void sigchld(int sig __attribute__ ((unused)))
{
char c = 0;
write(pidpipe[1], &c, 1);
}
+static void sigwinch(int sig __attribute__ ((unused)))
+{
+ if (ioctl(0, TIOCGWINSZ, &wz) < 0)
+ {
+ wzok = 0;
+ return;
+ }
+ if (wz.ws_row == 0) wz.ws_row = 24;
+ if (wz.ws_col == 0) wz.ws_col = 80;
+ snprintf(sz.env_row, sizeof(sz.env_row), "LINES=%d", wz.ws_row);
+ snprintf(sz.env_col, sizeof(sz.env_col), "COLUMNS=%d", wz.ws_col);
+}
+
void usage(int status)
{
fprintf(stderr, "usage: startpar [options] [-a arg] prgs\n");
@@ -513,25 +597,24 @@ void usage(int status)
int main(int argc, char **argv)
{
- volatile int broken;
- int timo = -1;
int gtimo = -1;
- int r, c, i, s, last, num;
+ int timo = -1;
+ int isgtimo;
+ int forw = 0;
+ int c, i, num;
+ int limit;
int *resvec;
- int maxfd;
fd_set rset;
struct timeval tv;
struct prg *p;
- pid_t pid;
- int forw = 0;
char pipebuf[16];
- int isgtimo;
struct prg *gtimo_running = 0;
struct prg *interactive_task = NULL;
- int active, limit;
- char *prev_level = NULL, *run_level = NULL;
+ char *prev_level = getenv("PREVLEVEL");
+ char *run_level = getenv("RUNLEVEL");
char *splashopt = 0;
+ (void)signal(SIGCHLD, SIG_DFL);
numcpu = sysconf(_SC_NPROCESSORS_ONLN);
myname = argv[0];
@@ -573,9 +656,9 @@ int main(int argc, char **argv)
usage(0);
break;
case 'i':
- iorate = atoi(optarg);
- if (iorate <= 0)
- iorate = 800;
+ iorate = atof(optarg);
+ if (iorate < 0.0)
+ iorate = 800.0;
break;
default:
usage(1);
@@ -609,6 +692,8 @@ int main(int argc, char **argv)
char makefile[64];
if (!strcmp(run_mode, "boot"))
arg = "start";
+ else if (!strcmp(run_mode, "halt"))
+ arg = "stop";
else if (!strcmp(run_mode, "start") || !strcmp(run_mode, "stop"))
{
arg = run_mode;
@@ -623,11 +708,12 @@ int main(int argc, char **argv)
fprintf(stderr, "invalid run mode %s\n", run_mode);
exit(1);
}
- snprintf(makefile, sizeof(makefile), INITDDIR "/.depend.%s", run_mode);
+ snprintf(makefile, sizeof(makefile), "/etc/init.d/.depend.%s", run_mode);
parse_makefile(makefile);
check_run_files(run_mode, prev_level, run_level);
argc = tree_entries; /* number of handled scripts */
+ isstart = !strcmp(arg, "start");
if (argc == 0)
exit(0);
@@ -639,7 +725,7 @@ int main(int argc, char **argv)
inpar = par; /* the original argument of parallel procs per cpu */
- par = checkpar(inpar, run_mode); /* the number of parallel procs on all cpu's */
+ par = checkpar(inpar, isstart); /* the number of parallel procs on all cpu's */
if (par > argc) /* not more than the number of all scripts */
par = argc;
@@ -651,6 +737,9 @@ int main(int argc, char **argv)
if (par < 0)
usage(1);
+ if (arg)
+ isstart = !strcmp(arg, "start");
+
if (argc == 0)
exit(0);
@@ -661,7 +750,7 @@ int main(int argc, char **argv)
inpar = par; /* the original argument of parallel procs per cpu */
- par = checkpar(inpar, "stop"); /* the number of parallel procs on all cpu's */
+ par = checkpar(inpar, isstart); /* the number of parallel procs on all cpu's */
if (par > argc) /* not more than the number of all scripts */
par = argc;
@@ -674,12 +763,13 @@ int main(int argc, char **argv)
if (argc == 1)
{
- if (run_mode) {
- *nodevec = pickup_task();
- if (*nodevec) {
- *resvec = run_single((*nodevec)->name, calcsplash(0, 1, splashopt));
- finish_task(*nodevec);
- }
+ if (run_mode)
+ {
+ if ((*nodevec = pickup_task()))
+ {
+ *resvec = run_single((*nodevec)->name, calcsplash(0, 1, splashopt));
+ finish_task(*nodevec);
+ }
} else
*resvec = run_single(*argv, calcsplash(0, 1, splashopt));
goto finished;
@@ -691,6 +781,15 @@ int main(int argc, char **argv)
if (!gtimo_buf)
gtimo_bufsize = 0; /* Accept error due memory shortage */
+ sa.sa_handler = sigwinch;
+ sa.sa_flags = SA_RESTART|SA_NODEFER;
+ (void)sigemptyset(&sa.sa_mask);
+ if (sigaction(SIGWINCH, &sa, 0))
+ {
+ perror("sigwinch sigaction");
+ exit(1);
+ }
+
if (tcgetattr(0, &tio))
{
perror("tcgetattr");
@@ -698,6 +797,13 @@ int main(int argc, char **argv)
}
if (ioctl(0, TIOCGWINSZ, &wz) == 0)
wzok = 1;
+ if (wz.ws_row == 0) wz.ws_row = 24;
+ if (wz.ws_col == 0) wz.ws_col = 80;
+
+ strcat(&sz.env_row[0], "LINES=");
+ strcat(&sz.env_col[0], "COLUMNS=");
+ snprintf(sz.env_row, sizeof(sz.env_row), "LINES=%d", wz.ws_row);
+ snprintf(sz.env_col, sizeof(sz.env_col), "COLUMNS=%d", wz.ws_col);
if (pipe(pidpipe))
{
@@ -715,60 +821,61 @@ int main(int argc, char **argv)
exit(1);
}
- broken = 0; /* Detect broken hardware */
gettimeofday(&glastio, 0);
- limit = checklimit(inpar, (run_mode) ? run_mode : "stop");
- lastlim.tv_sec = glastio.tv_sec;
- lastlim.tv_usec = glastio.tv_usec;
+ limit = checklimit(inpar, isstart);
+ lastlim = glastio;
for (;;)
{
+ int active = 0;
+ int maxfd = -1;
+ int last = -1;
+ pid_t pid = 0;
+ int r = 0, s;
long diff;
+ int devpts = 0;
gettimeofday(&now, 0);
FD_ZERO(&rset);
- tv.tv_sec = now.tv_sec;
- tv.tv_usec = now.tv_usec;
- last = -1;
- maxfd = -1;
- active = 0;
- pid = 0;
-
- diff = ((now.tv_sec - lastlim.tv_sec) * 1000) +
- ((now.tv_usec - lastlim.tv_usec)/ 1000);
- if (diff >= 300 || diff < 0)
+ tv = now;
+
+ if ((diff = timerdiff(now, lastlim)) >= 300 || diff < 0)
{
#if DEBUG
fprintf(stderr, "%d: doing checklimit after %ldms %ld\n", getpid(), diff, time(0));
#endif
- limit = checklimit(inpar, (run_mode) ? run_mode : "stop");
- if (limit > argc)
+ if ((limit = checklimit(inpar, isstart)) > argc)
limit = argc; /* not more than the number of all scripts */
- lastlim.tv_sec = now.tv_sec;
- lastlim.tv_usec = now.tv_usec;
+ lastlim = now;
diff = 0;
}
#if DEBUG
- fprintf(stderr, "par = %d, inpar = %d, limit = %d (diff=%ld)\n", par, inpar, limit, diff);
+ fprintf(stderr, "par=%d, inpar=%d, limit=%d (diff=%ld)\n", par, inpar, limit, diff);
#endif
- for (s = 0; s < par; s++)
+ for (s = 0; s < par; s++) /* never leave this with break!! */
{
+ account: /* for the new process below */
+ if (!devpts)
+ devpts = checkdevpts();
p = prgs + s;
if (p == interactive_task)
- continue; /* don't handle this here */
+ continue; /* don't count this here */
if (p->fd || p->pid)
active++; /* count all running procs */
if (p->fd == 0)
{
- if (p->pid == 0 && num < argc && !interactive_task)
+ if (interactive_task)
+ continue; /* dont't start new processes */
+ if (num >= argc)
+ continue; /* nothing to do */
+ if (p->pid == 0)
{
if (active >= limit)
- break; /* load balancing */
+ continue; /* load balancing */
if (run_mode)
{
- nodevec[num] = pickup_task();
- if (! nodevec[num])
+ if ((nodevec[num] = pickup_task()) == NULL)
continue;
- if (nodevec[num]->interactive)
+ if (nodevec[num]->interactive || !devpts)
interactive_task = p;
p->name = nodevec[num]->name;
}
@@ -777,17 +884,17 @@ int main(int argc, char **argv)
p->splashadd = calcsplash(num, argc, splashopt);
p->num = num++;
if (interactive_task)
- break;
+ continue; /* don't start this here */
run(p);
- active++; /* remember this _new_ proc!!! */
if (p->pid == 0)
{
resvec[p->num] = 1;
if (run_mode)
finish_task(nodevec[p->num]);
- active--; /* fork in run() failed, sigh! */
}
- break;
+ gettimeofday(&now, 0);
+ tv = now;
+ goto account; /* take the new process into account */
}
continue;
}
@@ -796,18 +903,13 @@ int main(int argc, char **argv)
maxfd = p->fd;
if (p->len == 0)
continue;
- if ((last < 0) || (tv.tv_sec > p->lastio.tv_sec) ||
- (tv.tv_sec == p->lastio.tv_sec && tv.tv_usec > p->lastio.tv_usec))
+ if ((last < 0) || timercmp(&tv,&p->lastio,>))
{
last = s;
- tv.tv_sec = p->lastio.tv_sec;
- tv.tv_usec = p->lastio.tv_usec;
+ tv = p->lastio;
}
-
} /* for (s = 0; s < par; s++) */
- broken++; /* no endless loops due broken systems */
-
if (interactive_task)
{
if (active == 0)
@@ -819,36 +921,31 @@ int main(int argc, char **argv)
p->pid = 0;
p->fd = 0;
interactive_task = NULL;
- broken = 0; /* run_single() uses waitpid() */
continue;
}
}
- if ((active < limit) && (num < argc) && (broken < argc))
- continue; /* try to start new processes */
-
if (active == 0)
{
if (num < argc)
fprintf(stderr, "ERROR: not all processed (%d of %d)\n", num, argc);
#if DEBUG
- if ((pid = waitpid(-1, &r, maxfd < 0 ? 0 : WNOHANG)) > 0)
+ if ((pid = waitpid(-1, &r, (maxfd < 0 ? 0 : WNOHANG)|WUNTRACED)) > 0)
fprintf(stderr, "ERROR: not all processes are checked\n");
#endif
break;
}
-#if 0
+#if DEBUG
fprintf(stderr, "active = %d\n", active);
#endif
if (active == 1 && last >= 0)
{
p = prgs + last;
- if ((pid = waitpid(p->pid, &r, maxfd < 0 ? 0 : WNOHANG)) == 0)
+ if ((pid = waitpid(p->pid, &r, (maxfd < 0 ? 0 : WNOHANG)|WUNTRACED)) == 0)
{
writebuf(p);
continue;
}
- broken = 0;
}
FD_SET(pidpipe[0], &rset);
@@ -857,10 +954,7 @@ int main(int argc, char **argv)
;
if (pid == 0)
- {
- pid = waitpid(-1, &r, maxfd < 0 ? 0 : WNOHANG);
- broken = 0;
- }
+ pid = waitpid(-1, &r, (maxfd < 0 ? 0 : WNOHANG)|WUNTRACED);
if (pid > 0)
{
@@ -871,6 +965,16 @@ int main(int argc, char **argv)
p = prgs + s;
if (p->pid == pid)
{
+ if (WIFSTOPPED(r))
+ {
+ if (WSTOPSIG(r) == SIGTTIN)
+ {
+ pid_t pg = getpgid(pid);
+ if (pg > 0)
+ killpg(pg, SIGCONT);
+ }
+ continue;
+ }
callsplash(p->splashadd, p->name, arg);
resvec[p->num] = WIFEXITED(r) ? WEXITSTATUS(r) : (WIFSIGNALED(r) ? 1 : 255);
if (run_mode)
@@ -911,12 +1015,11 @@ int main(int argc, char **argv)
isgtimo = 0;
if (gtimo >= 0 && !gtimo_running && last >= 0 && prgs[last].pid)
{
- const long glsec = glastio.tv_sec + gtimo;
- if ((timo < 0) || (tv.tv_sec > glsec) ||
- (tv.tv_sec == glsec && tv.tv_usec > glastio.tv_usec))
+ struct timeval gl = glastio;
+ gl.tv_sec += gtimo;
+ if ((timo < 0) || timercmp(&tv,&gl,>))
{
- tv.tv_sec = glastio.tv_sec;
- tv.tv_usec = glastio.tv_usec;
+ tv = glastio;
tv.tv_sec += gtimo;
isgtimo = 1;
}
@@ -1015,8 +1118,7 @@ int main(int argc, char **argv)
memmove(p->buf, p->buf + p->len, sizeof(p->buf) - p->len);
p->len = sizeof(p->buf) - p->len;
}
- p->lastio.tv_sec = now.tv_sec;
- p->lastio.tv_usec = now.tv_usec;
+ p->lastio = now;
} /* for (s = 0; s < par; s++) */
}
} /* for (;;) */
---
More information about the Pkg-sysvinit-devel
mailing list