diff --git a/src/conf.c b/src/conf.c index 56886794..37049c68 100644 --- a/src/conf.c +++ b/src/conf.c @@ -358,7 +358,7 @@ static void parse_dynamic(char *line, struct timeval *mtime) } if (MATCH_CMD(line, "tty ", x)) { - tty_register(strip_line(x)); + tty_register(strip_line(x), mtime); return; } } @@ -462,6 +462,7 @@ void conf_reload_dynamic(void) /* Mark and sweep */ svc_mark_dynamic(); + tty_mark(); num = scandir(dir, &e, NULL, alphasort); if (num < 0) { diff --git a/src/sm.c b/src/sm.c index 15c53f97..cbf34a9f 100644 --- a/src/sm.c +++ b/src/sm.c @@ -196,6 +196,7 @@ restart: sm->in_teardown = 1; cond_reload(); service_step_all(SVC_TYPE_SERVICE | SVC_TYPE_INETD); + tty_reload(); sm->state = SM_RELOAD_WAIT_STATE; break; diff --git a/src/tty.c b/src/tty.c index 0d0ef613..87da4d86 100644 --- a/src/tty.c +++ b/src/tty.c @@ -43,9 +43,48 @@ static pid_t fallback = 0; #endif static LIST_HEAD(, tty_node) tty_list = LIST_HEAD_INITIALIZER(); +void tty_mark(void) +{ + tty_node_t *tty; + + LIST_FOREACH(tty, &tty_list, link) { + if (tty->mtime.tv_sec) + tty->dirty = -1; + } +} + +void tty_check(tty_node_t *tty, struct timeval *mtime) +{ + if (mtime && timercmp(&tty->mtime, mtime, !=)) + tty->dirty = 1; /* Modified, restart */ + else + tty->dirty = 0; /* Not modified */ + + /* Update mtime, if given */ + tty->mtime.tv_sec = mtime ? mtime->tv_sec : 0; + tty->mtime.tv_usec = mtime ? mtime->tv_usec : 0; +} + +void tty_sweep(void) +{ + tty_node_t *tty, *tmp; + + LIST_FOREACH_SAFE(tty, &tty_list, link, tmp) { + if (tty->mtime.tv_sec && tty->dirty) { + _d("TTY %s dirty, stopping ...", tty->data.name); + tty_stop(&tty->data); + + if (tty->dirty == -1) { + _d("TTY %s removed, cleaning up.", tty->data.name); + LIST_REMOVE(tty, link); + tty_unregister(tty); + } + } + } +} /* tty [!1-9,S] [BAUD[,BAUD,...]] [TERM] [noclear] */ -int tty_register(char *line) +int tty_register(char *line, struct timeval *mtime) { tty_node_t *entry; int insert = 0, noclear = 0; @@ -53,7 +92,7 @@ int tty_register(char *line) char *runlevels = NULL, *term = NULL; if (!line) { - _e("Invalid input argument"); + _e("Missing argument"); return errno = EINVAL; } @@ -97,6 +136,27 @@ int tty_register(char *line) if (insert) LIST_INSERT_HEAD(&tty_list, entry, link); + tty_check(entry, mtime); + _d("TTY %s is %sdirty", dev, entry->dirty ? "" : "NOT "); + + return 0; +} + +int tty_unregister(tty_node_t *tty) +{ + if (!tty) { + _e("Missing argument"); + return errno = EINVAL; + } + + if (tty->data.name) + free(tty->data.name); + if (tty->data.baud) + free(tty->data.baud); + if (tty->data.term) + free(tty->data.term); + free(tty); + return 0; } @@ -169,7 +229,7 @@ static char *canonicalize(char *tty) return path; } -int tty_check(char *dev) +static int tty_exist(char *dev) { int fd; struct termios c; @@ -210,7 +270,7 @@ void tty_start(finit_tty_t *tty) if (console && !strcmp(dev, console)) is_console = 1; - if (tty_check(dev)) { + if (tty_exist(dev)) { _d("%s: Not a valid TTY: %s", dev, strerror(errno)); return; } @@ -309,6 +369,25 @@ int tty_respawn(pid_t pid) return 1; } +/* + * Called after reload of /etc/finit.d/, stop/start TTYs + */ +void tty_reload(void) +{ + tty_node_t *tty; + + tty_sweep(); + + LIST_FOREACH(tty, &tty_list, link) { + if (!tty_enabled(&tty->data)) + tty_stop(&tty->data); + else + tty_start(&tty->data); + + tty->dirty = 0; + } +} + /* Start all TTYs that exist in the system and are allowed at this runlevel */ void tty_runlevel(void) { diff --git a/src/tty.h b/src/tty.h index b50a6318..4a1fccb3 100644 --- a/src/tty.h +++ b/src/tty.h @@ -43,11 +43,22 @@ typedef struct { typedef struct tty_node { LIST_ENTRY(tty_node) link; finit_tty_t data; + + /* XXX: Yes, TTYs should be refactored into a separate SVC type. */ + struct timeval mtime; /* Modification time for .conf from /etc/finit.d/ */ + int dirty; /* Set if old mtime != new mtime => reloaded, + * or -1 when marked for removal */ } tty_node_t; //extern LIST_HEAD(, tty_node) tty_list; -int tty_register (char *line); +void tty_mark (void); +void tty_check (tty_node_t *tty, struct timeval *mtime); +void tty_sweep (void); + +int tty_register (char *line, struct timeval *mtime); +int tty_unregister (tty_node_t *tty); + tty_node_t *tty_find (char *dev); size_t tty_num (void); size_t tty_num_active (void); @@ -56,6 +67,7 @@ void tty_start (finit_tty_t *tty); void tty_stop (finit_tty_t *tty); int tty_enabled (finit_tty_t *tty); int tty_respawn (pid_t pid); +void tty_reload (void); void tty_runlevel (void); #endif /* FINIT_TTY_H_ */