int mdns_send(const struct mdns_ctx *ctx, const struct mdns_hdr *hdr, const struct rr_entry *entries) { uint8_t buf[MDNS_PKT_MAXSZ] = {0}; const struct rr_entry *entry = entries; ssize_t n = 0, l, r; if (!entries) return (MDNS_STDERR); if ((l = mdns_write_hdr(buf, hdr)) < 0) { return (MDNS_STDERR); } n += l; for (entry = entries; entry; entry = entry->next) { l = rr_write(buf+n, entry, (hdr->flags & FLAG_QR) > 0); if (l < 0) { return (MDNS_STDERR); } n += l; } r = sendto(ctx->sock, (const char *) buf, n, 0, (const struct sockaddr *) &ctx->addr, ss_len(&ctx->addr)); return (r < 0 ? MDNS_NETERR : 0); }
void dump_packages (ss_val file) { ss_val packages = ss_dict_get (file_packages_dict, file); int len = packages? ss_len (packages) : 0, i; dyn_print ("%r:", file); for (i = 0; i < len; i++) { ss_val pkg = ss_ref (packages, i); dyn_print (" %r", pkg); } dyn_print ("\n"); }
void dump_package_info (ss_val pkg, const char *field) { ss_val info = ss_dict_get (package_info_dict, pkg); if (info) { if (field) { ss_val key = intern_soft (field); int n = ss_len (info), i; for (i = 0; i < n; i += 2) { if (ss_ref (info, i) == key) dyn_print ("%r\n", ss_ref (info, i+1)); } } else { int n = ss_len (info), i; for (i = 0; i < n; i += 2) dyn_print ("%r: %r\n", ss_ref (info, i), ss_ref (info, i+1)); } } }
void rem_list (ss_val pkg) { ss_val files = ss_dict_get (package_files_dict, pkg); if (files) { int len = ss_len (files), i; for (i = 0; i < len; i++) { ss_val file = ss_ref (files, i); ss_dict_del (file_packages_dict, file, pkg); } dyn_print ("%r: removed %d files\n", pkg, len); } ss_dict_set (package_files_dict, pkg, NULL); }
void init (const char *file, int mode) { ss_val r; int len; store = ss_open (file, mode); r = ss_get_root (store); len = r? ss_len (r) : 0; table = ss_tab_init (store, (len > 0)? ss_ref (r, 0) : NULL); package_files_dict = ss_dict_init (store, (len > 1)? ss_ref (r, 1) : NULL, SS_DICT_STRONG); file_packages_dict = ss_dict_init (store, (len > 2)? ss_ref (r, 2) : NULL, SS_DICT_STRONG); package_info_dict = ss_dict_init (store, (len > 2)? ss_ref (r, 3) : NULL, SS_DICT_STRONG); }
static void info (const char *package) { if (package) { dpm_db_open (); dpm_package pkg = dpm_db_find_package (package); if (pkg) { ss_val versions = dpm_db_available (pkg); dpm_version installed = dpm_db_installed (pkg); int installed_shown = 0; dyn_print ("%r:", dpm_pkg_name (pkg)); if (versions) for (int i = 0; i < ss_len (versions); i++) { dpm_version ver = ss_ref (versions, i); if (ver == installed) { dyn_print (" [%r]", dpm_ver_version (ver)); installed_shown = 1; } else dyn_print (" %r", dpm_ver_version (ver)); dyn_foreach (dpm_package_index idx, dpm_db_version_foreach_pkgindex, ver) { dpm_release_index release = dpm_pkgidx_release (idx); if (release) dyn_print (" (%r)", dpm_relidx_dist (release)); } } if (!installed_shown && installed) dyn_print (" [%r]", dpm_ver_version (installed)); dyn_print ("\n"); } dpm_db_done (); }
void set_list (ss_val pkg, char *file) { FILE *f; char *line = NULL; size_t len = 0; ssize_t l; int n; ss_val lines[10240]; rem_list (pkg); if (file == NULL) file = dyn_format ("/var/lib/dpkg/info/%.*s.list", ss_len (pkg), ss_blob_start (pkg)); n = 0; f = fopen (file, "r"); if (f) { while ((l = getline (&line, &len, f)) != -1) { if (l > 0 && line[l-1] == '\n') l -= 1; line[l] = 0; if (n < 10240) { ss_val file = intern (line); lines[n++] = file; ss_dict_add (file_packages_dict, file, pkg); } } free (line); fclose (f); } dyn_print ("%r: added %d files\n", pkg, n); ss_dict_set (package_files_dict, pkg, ss_newv (store, 0, n, lines)); }
void show (const char *package, const char *version) { if (package) { dpm_db_open (); dpm_package pkg = dpm_db_find_package (package); dpm_version ver_to_show = NULL; if (pkg) { ss_val versions = dpm_db_available (pkg); dyn_print ("%r [%d]:", dpm_pkg_name (pkg), dpm_pkg_id (pkg)); if (versions) for (int i = 0; i < ss_len (versions); i++) { dpm_version ver = ss_ref (versions, i); dyn_print (" %r (%r) [%d]", dpm_ver_version (ver), dpm_ver_architecture (ver), dpm_ver_id (ver)); if (!ver_to_show) { if (version == NULL || ss_equal_blob (dpm_ver_version (ver), strlen (version), version)) ver_to_show = ver; } } dyn_print ("\n"); } if (ver_to_show) dpm_db_show_version (ver_to_show); dpm_db_done (); } }
int mdns_init(struct mdns_ctx **p_ctx, const char *addr, unsigned short port) { const uint32_t on_off = 1; const uint32_t ttl = 255; const uint8_t loop = 1; #ifdef _WIN32 union { struct sockaddr_storage ss; struct sockaddr_in sin; struct sockaddr_in6 sin6; } dumb; #endif /* _WIN32 */ struct mdns_ctx *ctx; if (p_ctx == NULL) return (MDNS_STDERR); *p_ctx = malloc(sizeof(struct mdns_ctx)); if (*p_ctx == NULL) return (MDNS_STDERR); ctx = *p_ctx; ctx->sock = INVALID_SOCKET; errno = os_init("2.2"); if (errno != 0) return (MDNS_NETERR); if (mdns_resolve(&ctx->addr, addr, port) < 0) return (MDNS_LKPERR); if ((ctx->sock = socket(ss_family(&ctx->addr), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) return (MDNS_NETERR); if (setsockopt(ctx->sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &on_off, sizeof(on_off)) < 0) return (MDNS_NETERR); #ifdef _WIN32 /* bind the receiver on any local address */ memset(&dumb, 0, sizeof(dumb)); dumb.ss.ss_family = ss_family(&ctx->addr); if (dumb.ss.ss_family == AF_INET) { dumb.sin.sin_port = htons(port); dumb.sin.sin_addr.s_addr = INADDR_ANY; } else { dumb.sin6.sin6_port = htons(port); dumb.sin6.sin6_addr = in6addr_any; } if (bind(ctx->sock, (const struct sockaddr *) &dumb, ss_len(&dumb.ss)) < 0) return (MDNS_NETERR); #else /* _WIN32 */ if (bind(ctx->sock, (const struct sockaddr *) &ctx->addr, ss_len(&ctx->addr)) < 0) return (MDNS_NETERR); #endif /* _WIN32 */ if (os_mcast_join(ctx->sock, &ctx->addr) < 0) return (MDNS_NETERR); if (setsockopt(ctx->sock, ss_level(&ctx->addr), ss_family(&ctx->addr)==AF_INET ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS, (const void *) &ttl, sizeof(ttl)) < 0) return (MDNS_NETERR); if (setsockopt(ctx->sock, ss_level(&ctx->addr), IP_MULTICAST_LOOP, (const void *) &loop, sizeof(loop)) < 0) return (MDNS_NETERR); ctx->services = NULL; return (0); }
void print_blob (ss_val v) { printf ("%.*s", ss_len (v), (char *)ss_blob_start (v)); }
int main (int argc, char **argv) { if (argc < 2) usage (); dyn_begin (); if (strcmp (argv[1], "add") == 0) { init (argv[2], SS_WRITE); while (argc > 3) { set_list (intern (argv[3]), NULL); argc--; argv++; } ss_tab_dump (table); finish (SS_WRITE); } else if (strcmp (argv[1], "rem") == 0) { init (argv[2], SS_WRITE); while (argc > 3) { rem_list (intern (argv[3])); argc--; argv++; } ss_tab_dump (table); finish (SS_WRITE); } else if (strcmp (argv[1], "set-list") == 0) { init (argv[2], SS_WRITE); if (argc > 4) set_list (intern (argv[3]), argv[4]); ss_tab_dump (table); finish (SS_WRITE); } else if (strcmp (argv[1], "list") == 0) { init (argv[2], SS_READ); if (argc > 3) { int i; ss_val files = ss_dict_get (package_files_dict, intern_soft (argv[3])); if (files) { for (i = 0; i < ss_len (files); i++) { ss_val b = ss_ref (files, i); dyn_print ("%r\n", b); } } else printf ("%s not found\n", argv[3]); } finish (SS_READ); } else if (strcmp (argv[1], "search") == 0) { init (argv[2], SS_READ); if (argc > 3) { ss_val file = intern_soft (argv[3]); if (file && ss_dict_get (file_packages_dict, file)) dump_packages (file); else { dyn_foreach (ss_val blob, ss_tab_foreach, table) { grep_blob (blob, argv[3]); } }
void dump_package (ss_val key, ss_val val) { dyn_print ("%r: %d files\n", key, ss_len (val)); }