feat: /realm in TUI, daemon instance takeover (0.9.16)
Pidfile records instance+port; login restarts the service when the seat changes. TUI /realm status|login|stop; prompts discourage filler chatter. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+4
-3
@@ -28,9 +28,10 @@ cst-agent --login --realm-label "thinkpad"
|
|||||||
查看状态:
|
查看状态:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cst-agent # 进入 TUI 后 /status
|
cst-agent # TUI: /status 或 /realm
|
||||||
# 或 CLI
|
# /realm login # TUI 内登录并启服务
|
||||||
cst-agent --service-stop # 停服务
|
# /realm stop # 停服务
|
||||||
|
cst-agent --service-stop
|
||||||
```
|
```
|
||||||
|
|
||||||
密码 Realm 开启后,直接打开 agent 会要求登录(TTY 下可当场输入密码)。
|
密码 Realm 开启后,直接打开 agent 会要求登录(TTY 下可当场输入密码)。
|
||||||
|
|||||||
@@ -63,8 +63,11 @@ int cst_parliament_apply_sync(unsigned long revision, const char *parliament_id,
|
|||||||
/* Background parliament service: discover + peer listen + context sync. */
|
/* Background parliament service: discover + peer listen + context sync. */
|
||||||
int cst_parliament_daemon_pidfile(char *out, size_t n);
|
int cst_parliament_daemon_pidfile(char *out, size_t n);
|
||||||
int cst_parliament_daemon_running(void);
|
int cst_parliament_daemon_running(void);
|
||||||
|
/* Read pidfile metadata. Returns 0 when a live service is recorded. */
|
||||||
|
int cst_parliament_daemon_info(int *pid_out, char *instance_out, size_t in_sz,
|
||||||
|
int *port_out);
|
||||||
/* Start in background (Unix fork). password unlocks Realm in the child.
|
/* Start in background (Unix fork). password unlocks Realm in the child.
|
||||||
* Returns 0 and writes pid. If already running, returns 0. */
|
* Returns 0 and writes pid. Restarts if a different instance/port is running. */
|
||||||
int cst_parliament_daemon_start(const char *password, const char *instance_id,
|
int cst_parliament_daemon_start(const char *password, const char *instance_id,
|
||||||
int peer_port, char *err, size_t err_sz);
|
int peer_port, char *err, size_t err_sz);
|
||||||
int cst_parliament_daemon_stop(void);
|
int cst_parliament_daemon_stop(void);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#define CST_VERSION_MAJOR 0
|
#define CST_VERSION_MAJOR 0
|
||||||
#define CST_VERSION_MINOR 9
|
#define CST_VERSION_MINOR 9
|
||||||
#define CST_VERSION_PATCH 15
|
#define CST_VERSION_PATCH 16
|
||||||
|
|
||||||
#define CST_VERSION_STR_(x) #x
|
#define CST_VERSION_STR_(x) #x
|
||||||
#define CST_VERSION_STR(x) CST_VERSION_STR_(x)
|
#define CST_VERSION_STR(x) CST_VERSION_STR_(x)
|
||||||
|
|||||||
+4
-2
@@ -292,7 +292,8 @@ static const char DEF_INTRO[] =
|
|||||||
"- Verify (build, tests, or running it) before saying it works; if you "
|
"- Verify (build, tests, or running it) before saying it works; if you "
|
||||||
"could not verify, say so.\n"
|
"could not verify, say so.\n"
|
||||||
"- Keep going until the task is done or truly blocked. Prefer acting with "
|
"- Keep going until the task is done or truly blocked. Prefer acting with "
|
||||||
"tools over describing the next step; do not stop at a plan unless asked.\n\n";
|
"tools over describing the next step; do not stop at a plan unless asked. "
|
||||||
|
"Skip filler like \"I'll start by looking\" — call a tool immediately.\n\n";
|
||||||
|
|
||||||
/* Same role, framed for /mode general: the workspace may hold documents,
|
/* Same role, framed for /mode general: the workspace may hold documents,
|
||||||
* data or anything else, not just code. */
|
* data or anything else, not just code. */
|
||||||
@@ -312,7 +313,8 @@ static const char DEF_INTRO_GENERAL[] =
|
|||||||
"- Check your work when you can (re-read it, run it, cross-check the "
|
"- Check your work when you can (re-read it, run it, cross-check the "
|
||||||
"source); if you could not verify something, say so.\n"
|
"source); if you could not verify something, say so.\n"
|
||||||
"- Keep going until the task is done or truly blocked. Prefer acting with "
|
"- Keep going until the task is done or truly blocked. Prefer acting with "
|
||||||
"tools over describing the next step; do not stop at a plan unless asked.\n\n";
|
"tools over describing the next step; do not stop at a plan unless asked. "
|
||||||
|
"Skip filler like \"I'll start by looking\" — call a tool immediately.\n\n";
|
||||||
|
|
||||||
static void put_tool_use(cst_buf_t *b, const cst_agent_config_t *cfg) {
|
static void put_tool_use(cst_buf_t *b, const cst_agent_config_t *cfg) {
|
||||||
cst_buf_puts(b, "\nTool use:\n");
|
cst_buf_puts(b, "\nTool use:\n");
|
||||||
|
|||||||
+9
-2
@@ -449,7 +449,10 @@ char *cst_parliament_status_text(void) {
|
|||||||
cst_parliament_load(&m);
|
cst_parliament_load(&m);
|
||||||
char sid[64] = {0};
|
char sid[64] = {0};
|
||||||
int sess = cst_parliament_session_ok(sid, sizeof(sid));
|
int sess = cst_parliament_session_ok(sid, sizeof(sid));
|
||||||
int svc = cst_parliament_daemon_running();
|
int svc_pid = 0, svc_port = 0;
|
||||||
|
char svc_id[64] = {0};
|
||||||
|
int svc = cst_parliament_daemon_info(&svc_pid, svc_id, sizeof(svc_id),
|
||||||
|
&svc_port) == 0;
|
||||||
cst_buf_printf(&b, "realm %s\n", pw ? "password" : "file-keys/legacy");
|
cst_buf_printf(&b, "realm %s\n", pw ? "password" : "file-keys/legacy");
|
||||||
cst_buf_printf(&b, "parliament %s project=%s rev=%lu\n",
|
cst_buf_printf(&b, "parliament %s project=%s rev=%lu\n",
|
||||||
m.status[0] ? m.status : "idle",
|
m.status[0] ? m.status : "idle",
|
||||||
@@ -460,6 +463,10 @@ char *cst_parliament_status_text(void) {
|
|||||||
m.chair_device[0] ? " @ " : "", m.chair_device);
|
m.chair_device[0] ? " @ " : "", m.chair_device);
|
||||||
cst_buf_printf(&b, "login %s%s%s\n", sess ? "ok" : "required",
|
cst_buf_printf(&b, "login %s%s%s\n", sess ? "ok" : "required",
|
||||||
sess && sid[0] ? " as " : "", sess ? sid : "");
|
sess && sid[0] ? " as " : "", sess ? sid : "");
|
||||||
cst_buf_printf(&b, "service %s\n", svc ? "running" : "stopped");
|
if (svc)
|
||||||
|
cst_buf_printf(&b, "service running pid=%d id=%s port=%d\n", svc_pid,
|
||||||
|
svc_id[0] ? svc_id : "-", svc_port);
|
||||||
|
else
|
||||||
|
cst_buf_puts(&b, "service stopped\n");
|
||||||
return cst_buf_steal(&b);
|
return cst_buf_steal(&b);
|
||||||
}
|
}
|
||||||
|
|||||||
+98
-15
@@ -41,21 +41,53 @@ int cst_parliament_daemon_pidfile(char *out, size_t n) {
|
|||||||
return os_path_join(out, n, dir, "parliament.pid");
|
return os_path_join(out, n, dir, "parliament.pid");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_pid(void) {
|
typedef struct {
|
||||||
|
int pid;
|
||||||
|
char instance[64];
|
||||||
|
int port;
|
||||||
|
} daemon_meta_t;
|
||||||
|
|
||||||
|
static int read_meta(daemon_meta_t *m) {
|
||||||
|
memset(m, 0, sizeof(*m));
|
||||||
|
m->pid = -1;
|
||||||
char path[OS_PATH_MAX];
|
char path[OS_PATH_MAX];
|
||||||
if (cst_parliament_daemon_pidfile(path, sizeof(path)) != 0)
|
if (cst_parliament_daemon_pidfile(path, sizeof(path)) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
FILE *f = fopen(path, "rb");
|
FILE *f = fopen(path, "rb");
|
||||||
if (!f)
|
if (!f)
|
||||||
return -1;
|
return -1;
|
||||||
int pid = -1;
|
char line[256];
|
||||||
if (fscanf(f, "%d", &pid) != 1)
|
while (fgets(line, sizeof(line), f)) {
|
||||||
pid = -1;
|
if (!strncmp(line, "pid=", 4))
|
||||||
|
m->pid = atoi(line + 4);
|
||||||
|
else if (!strncmp(line, "instance=", 9)) {
|
||||||
|
const char *p = line + 9;
|
||||||
|
size_t i = 0;
|
||||||
|
while (p[i] && p[i] != '\n' && p[i] != '\r' &&
|
||||||
|
i + 1 < sizeof(m->instance)) {
|
||||||
|
m->instance[i] = p[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
m->instance[i] = 0;
|
||||||
|
} else if (!strncmp(line, "port=", 5))
|
||||||
|
m->port = atoi(line + 5);
|
||||||
|
else if (m->pid <= 0) {
|
||||||
|
/* Legacy single-line pidfile. */
|
||||||
|
int pid = atoi(line);
|
||||||
|
if (pid > 0)
|
||||||
|
m->pid = pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return pid;
|
return m->pid > 0 ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_pid(int pid) {
|
static int read_pid(void) {
|
||||||
|
daemon_meta_t m;
|
||||||
|
return read_meta(&m) == 0 ? m.pid : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_pid(int pid, const char *instance_id, int peer_port) {
|
||||||
char path[OS_PATH_MAX], tmp[OS_PATH_MAX + 8];
|
char path[OS_PATH_MAX], tmp[OS_PATH_MAX + 8];
|
||||||
if (cst_parliament_daemon_pidfile(path, sizeof(path)) != 0)
|
if (cst_parliament_daemon_pidfile(path, sizeof(path)) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -64,7 +96,9 @@ static int write_pid(int pid) {
|
|||||||
FILE *f = fopen(tmp, "wb");
|
FILE *f = fopen(tmp, "wb");
|
||||||
if (!f)
|
if (!f)
|
||||||
return -1;
|
return -1;
|
||||||
int ok = fprintf(f, "%d\n", pid) > 0;
|
int ok = fprintf(f, "pid=%d\ninstance=%s\nport=%d\n", pid,
|
||||||
|
instance_id ? instance_id : "",
|
||||||
|
peer_port > 0 ? peer_port : 0) > 0;
|
||||||
if (fclose(f) != 0)
|
if (fclose(f) != 0)
|
||||||
ok = 0;
|
ok = 0;
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
@@ -80,8 +114,7 @@ static void clear_pid(void) {
|
|||||||
remove(path);
|
remove(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cst_parliament_daemon_running(void) {
|
static int pid_alive(int pid) {
|
||||||
int pid = read_pid();
|
|
||||||
if (pid <= 0)
|
if (pid <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -95,6 +128,34 @@ int cst_parliament_daemon_running(void) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cst_parliament_daemon_running(void) {
|
||||||
|
daemon_meta_t m;
|
||||||
|
if (read_meta(&m) != 0)
|
||||||
|
return 0;
|
||||||
|
if (!pid_alive(m.pid)) {
|
||||||
|
clear_pid();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cst_parliament_daemon_info(int *pid_out, char *instance_out, size_t in_sz,
|
||||||
|
int *port_out) {
|
||||||
|
daemon_meta_t m;
|
||||||
|
if (read_meta(&m) != 0 || !pid_alive(m.pid)) {
|
||||||
|
if (read_meta(&m) == 0 && !pid_alive(m.pid))
|
||||||
|
clear_pid();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (pid_out)
|
||||||
|
*pid_out = m.pid;
|
||||||
|
if (instance_out && in_sz)
|
||||||
|
snprintf(instance_out, in_sz, "%s", m.instance);
|
||||||
|
if (port_out)
|
||||||
|
*port_out = m.port;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void sleep_ms(int ms) {
|
static void sleep_ms(int ms) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
Sleep((DWORD)ms);
|
Sleep((DWORD)ms);
|
||||||
@@ -194,7 +255,8 @@ int cst_parliament_daemon_run(const char *password, const char *instance_id,
|
|||||||
#else
|
#else
|
||||||
(int)getpid()
|
(int)getpid()
|
||||||
#endif
|
#endif
|
||||||
);
|
,
|
||||||
|
instance_id, bound);
|
||||||
fprintf(stderr, "parliament_service pid=%d port=%d id=%s realm=%s\n",
|
fprintf(stderr, "parliament_service pid=%d port=%d id=%s realm=%s\n",
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
(int)GetCurrentProcessId(),
|
(int)GetCurrentProcessId(),
|
||||||
@@ -273,8 +335,25 @@ int cst_parliament_daemon_start(const char *password, const char *instance_id,
|
|||||||
int peer_port, char *err, size_t err_sz) {
|
int peer_port, char *err, size_t err_sz) {
|
||||||
if (err && err_sz)
|
if (err && err_sz)
|
||||||
err[0] = 0;
|
err[0] = 0;
|
||||||
if (cst_parliament_daemon_running())
|
if (!instance_id || !instance_id[0]) {
|
||||||
return 0;
|
if (err && err_sz)
|
||||||
|
snprintf(err, err_sz, "instance id required");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int want_port = peer_port > 0 ? peer_port : 9100;
|
||||||
|
{
|
||||||
|
int cur_pid = 0, cur_port = 0;
|
||||||
|
char cur_id[64] = {0};
|
||||||
|
if (cst_parliament_daemon_info(&cur_pid, cur_id, sizeof(cur_id),
|
||||||
|
&cur_port) == 0) {
|
||||||
|
int same = (!cur_id[0] || strcmp(cur_id, instance_id) == 0) &&
|
||||||
|
(cur_port <= 0 || cur_port == want_port);
|
||||||
|
if (same)
|
||||||
|
return 0;
|
||||||
|
/* Different seat or port: take over. */
|
||||||
|
(void)cst_parliament_daemon_stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
/* Windows: run in-process foreground loop under a detached console is
|
/* Windows: run in-process foreground loop under a detached console is
|
||||||
* deferred; callers should use --service in a service manager. */
|
* deferred; callers should use --service in a service manager. */
|
||||||
@@ -294,9 +373,13 @@ int cst_parliament_daemon_start(const char *password, const char *instance_id,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (pid > 0) {
|
if (pid > 0) {
|
||||||
/* Parent: wait briefly for pidfile. */
|
/* Parent: wait briefly for matching pidfile. */
|
||||||
for (int i = 0; i < 50; i++) {
|
for (int i = 0; i < 50; i++) {
|
||||||
if (cst_parliament_daemon_running())
|
int cur_pid = 0, cur_port = 0;
|
||||||
|
char cur_id[64] = {0};
|
||||||
|
if (cst_parliament_daemon_info(&cur_pid, cur_id, sizeof(cur_id),
|
||||||
|
&cur_port) == 0 &&
|
||||||
|
(!cur_id[0] || strcmp(cur_id, instance_id) == 0))
|
||||||
return 0;
|
return 0;
|
||||||
sleep_ms(50);
|
sleep_ms(50);
|
||||||
}
|
}
|
||||||
@@ -314,7 +397,7 @@ int cst_parliament_daemon_start(const char *password, const char *instance_id,
|
|||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
char derr[256];
|
char derr[256];
|
||||||
(void)cst_parliament_daemon_run(password, instance_id, peer_port, derr,
|
(void)cst_parliament_daemon_run(password, instance_id, want_port, derr,
|
||||||
sizeof(derr));
|
sizeof(derr));
|
||||||
_exit(0);
|
_exit(0);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "cst_models.h"
|
#include "cst_models.h"
|
||||||
#include "cst_parliament.h"
|
#include "cst_parliament.h"
|
||||||
#include "cst_plugins.h"
|
#include "cst_plugins.h"
|
||||||
|
#include "cst_realm.h"
|
||||||
#include "cst_provider_switch.h"
|
#include "cst_provider_switch.h"
|
||||||
#include "cst_skills.h"
|
#include "cst_skills.h"
|
||||||
#include "cst_subagent.h"
|
#include "cst_subagent.h"
|
||||||
@@ -4624,6 +4625,83 @@ static void cmd_max_steps(tui_t *t, char *arg, int *quit) {
|
|||||||
push_system_line(t, "(max steps per turn: %d)", cfg->max_steps);
|
push_system_line(t, "(max steps per turn: %d)", cfg->max_steps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cmd_realm(tui_t *t, char *arg, int *quit) {
|
||||||
|
(void)quit;
|
||||||
|
const char *sub = arg && arg[0] ? arg : "status";
|
||||||
|
if (!strcmp(sub, "status") || !strcmp(sub, "show")) {
|
||||||
|
char *pst = cst_parliament_status_text();
|
||||||
|
if (pst && pst[0]) {
|
||||||
|
push_system_line(t, "Realm / Parliament:");
|
||||||
|
char *p = pst;
|
||||||
|
while (*p) {
|
||||||
|
char *nl = strchr(p, '\n');
|
||||||
|
if (nl)
|
||||||
|
*nl = 0;
|
||||||
|
if (p[0])
|
||||||
|
push_system_line(t, " %s", p);
|
||||||
|
if (!nl)
|
||||||
|
break;
|
||||||
|
p = nl + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
push_system_line(t, "(no realm status)");
|
||||||
|
}
|
||||||
|
free(pst);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!strcmp(sub, "stop")) {
|
||||||
|
if (cst_parliament_daemon_stop() != 0)
|
||||||
|
push_system_line(t, "Error: could not stop parliament service");
|
||||||
|
else
|
||||||
|
push_system_line(t, "(parliament service stopped)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!strncmp(sub, "login", 5)) {
|
||||||
|
char dir[OS_PATH_MAX];
|
||||||
|
if (cst_realm_dir(dir, sizeof(dir)) != 0 ||
|
||||||
|
!cst_realm_is_password_mode(dir)) {
|
||||||
|
push_system_line(t, "No password Realm yet. Outside TUI run:");
|
||||||
|
push_system_line(t, " cst-agent --realm-password-init");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char pw[256];
|
||||||
|
if (secret_input_run(t, "Realm password",
|
||||||
|
"Unlocks this device as chair; starts the service",
|
||||||
|
pw, sizeof(pw)) != 0) {
|
||||||
|
push_system_line(t, "(login cancelled)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char *iid = getenv("CST_INSTANCE_ID");
|
||||||
|
if (!iid || !iid[0])
|
||||||
|
iid = "chair-local";
|
||||||
|
char err[256];
|
||||||
|
char *hand = cst_parliament_login(pw, iid, NULL, err, sizeof(err));
|
||||||
|
if (!hand) {
|
||||||
|
memset(pw, 0, sizeof(pw));
|
||||||
|
push_system_line(t, "Login failed: %s", err[0] ? err : "unknown");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Show a short summary, not the full handover blob. */
|
||||||
|
push_system_line(t, "(logged in as chair %s)", iid);
|
||||||
|
if (strstr(hand, "handover_from=") &&
|
||||||
|
!strstr(hand, "handover_from=\n") &&
|
||||||
|
!strstr(hand, "handover_from=\r"))
|
||||||
|
push_system_line(t, "(took chair from previous device)");
|
||||||
|
free(hand);
|
||||||
|
{
|
||||||
|
char serr[256];
|
||||||
|
if (cst_parliament_daemon_start(pw, iid, 9100, serr, sizeof(serr)) != 0)
|
||||||
|
push_system_line(t, "warning: service: %s",
|
||||||
|
serr[0] ? serr : "start failed");
|
||||||
|
else if (cst_parliament_daemon_running())
|
||||||
|
push_system_line(t, "(parliament service running)");
|
||||||
|
}
|
||||||
|
memset(pw, 0, sizeof(pw));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
push_system_line(t, "Usage: /realm [status|login|stop]");
|
||||||
|
}
|
||||||
|
|
||||||
static void cmd_status(tui_t *t, char *arg, int *quit) {
|
static void cmd_status(tui_t *t, char *arg, int *quit) {
|
||||||
(void)arg;
|
(void)arg;
|
||||||
(void)quit;
|
(void)quit;
|
||||||
@@ -5605,6 +5683,8 @@ static const slash_cmd_t SLASH[] = {
|
|||||||
cmd_mouse},
|
cmd_mouse},
|
||||||
{"max-steps", "", "[N]", "tool steps allowed per turn", 1, cmd_max_steps},
|
{"max-steps", "", "[N]", "tool steps allowed per turn", 1, cmd_max_steps},
|
||||||
{"status", "", "", "session, model, context and settings", 1, cmd_status},
|
{"status", "", "", "session, model, context and settings", 1, cmd_status},
|
||||||
|
{"realm", "parliament login", "[status|login|stop]",
|
||||||
|
"Realm / parliament chair status, login, or stop service", 1, cmd_realm},
|
||||||
{"cost", "usage", "", "tokens, cache hit rate and estimated cost", 1,
|
{"cost", "usage", "", "tokens, cache hit rate and estimated cost", 1,
|
||||||
cmd_cost},
|
cmd_cost},
|
||||||
{"todo", "tasks", "", "show the agent's task list", 1, cmd_todo},
|
{"todo", "tasks", "", "show the agent's task list", 1, cmd_todo},
|
||||||
|
|||||||
@@ -72,8 +72,10 @@ int main(void) {
|
|||||||
|
|
||||||
char *st = cst_parliament_status_text();
|
char *st = cst_parliament_status_text();
|
||||||
assert(st && strstr(st, "parliament"));
|
assert(st && strstr(st, "parliament"));
|
||||||
|
assert(strstr(st, "service"));
|
||||||
free(st);
|
free(st);
|
||||||
assert(cst_parliament_is_active());
|
assert(cst_parliament_is_active());
|
||||||
|
assert(cst_parliament_daemon_info(NULL, NULL, 0, NULL) != 0);
|
||||||
|
|
||||||
test_rmrf(dir);
|
test_rmrf(dir);
|
||||||
puts("test_parliament: OK");
|
puts("test_parliament: OK");
|
||||||
|
|||||||
Reference in New Issue
Block a user