/* ams_stub.c — meow_amsd 宿主测试桩(不入固件)。 * * 用途:在宿主集成测试里,把 stdin 的每一行原样发到 amsd socket(command 与 EV 事件均可), * 然后读取响应直到 EOF 并打印。既当「launcher 上报桩」(注入 EV LAUNCH/EV OUT/EV EXIT), * 也当通用命令客户端(status/list/history/start/kill)。 * * 用法: * printf 'EV LAUNCH os.meow.hello home - 123 12345 100\n' | ./ams_stub_host --sock /tmp/sim_ams.sock * echo status | ./ams_stub_host --sock /tmp/sim_ams.sock * * 编译(宿主):gcc -Os -Wall -Wextra ams_stub.c -o ams_stub_host */ #include #include #include #include #include #include #include #define AMS_SOCK_DEFAULT "/usr/data/meow_ams.sock" #define AMS_SOCK_PATH_MAX 108 #define AMS_RESP_MAX 65536 static const char *g_sock = AMS_SOCK_DEFAULT; int main(int argc, char **argv) { const char *env = getenv("MEOW_AMS_SOCK"); if (env && env[0]) g_sock = env; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "--sock") && i + 1 < argc) g_sock = argv[++i]; else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { fprintf(stderr, "usage: %s [--sock ] (reads lines from stdin -> amsd)\n", argv[0]); return 0; } else { fprintf(stderr, "bad arg %s\n", argv[i]); return 2; } } int fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) { perror("socket"); return 1; } struct sockaddr_un a; memset(&a, 0, sizeof a); a.sun_family = AF_UNIX; snprintf(a.sun_path, sizeof a.sun_path, "%s", g_sock); if (connect(fd, (struct sockaddr *)&a, sizeof a) < 0) { fprintf(stderr, "connect %s: %s\n", g_sock, strerror(errno)); return 1; } char line[2048]; while (fgets(line, sizeof line, stdin)) { ssize_t w = write(fd, line, strlen(line)); (void)w; } /* half-close 写端:告知 amsd「无更多数据」(= launcher fire-and-forget 的 close 语义), * 事件连接 amsd 即收尾关闭;命令连接 amsd 写回响应后才关闭。 */ shutdown(fd, SHUT_WR); /* read response until EOF */ static char resp[AMS_RESP_MAX]; size_t n = 0; char tmp[2048]; ssize_t r; while ((r = read(fd, tmp, sizeof tmp)) > 0) { if (n + (size_t)r < sizeof resp - 1) { memcpy(resp + n, tmp, (size_t)r); n += (size_t)r; } } close(fd); resp[n] = '\0'; if (n > 0) fputs(resp, stdout); return 0; }