int grecs_str_to_sockaddr(struct grecs_sockaddr **sap, const char *arg, struct grecs_sockaddr_hints *gh, grecs_locus_t const *locus) { char *p; struct grecs_sockaddr_hints ghints; if (!gh) { memset(&ghints, 0, sizeof(ghints)); if (grecs_default_port) { ghints.flags = GRECS_HINT_PORT; ghints.port = ntohs(grecs_default_port); } gh = &ghints; } p = strchr(arg, ':'); if (p && p > arg && p[1] == '/' && p[2] == '/') { size_t len = p - arg; struct schemetab *sp; for (sp = schemetab; sp->scheme; sp++) if (len == sp->len && memcmp(arg, sp->scheme, len) == 0) return sp->parser(sap, arg, p + 3, gh, locus); grecs_error(locus, 0, _("unknown or unsupported scheme: %s"), arg); return -1; } if (arg[0] == '/') return parse_unix(sap, arg, arg, gh, locus); else if (strlen(arg) > 5 && memcmp(arg, "unix:", 5) == 0) { if (arg[5] != '/') grecs_error(locus, 0, _("%s: UNIX socket must be an absolute file name"), arg); return parse_unix(sap, arg, arg + 5, gh, locus); } return parse_inet(sap, AF_UNSPEC, arg, arg, gh, locus); }
static int parse_inet6(struct grecs_sockaddr **ret, const char *arg, const char *addrstr, struct grecs_sockaddr_hints *gh, grecs_locus_t const *locus) { return parse_inet(ret, AF_INET6, arg, addrstr, gh, locus); }
int main(int argc, char *argv[]) { opt_type opts; int sig_number; #ifdef WITH_IPV6 int ipv4_only, ipv6_only; #endif unsigned char default_namespace = NAMESPACE_FILE; struct device_list *match_devices = NULL; struct unixsocket_list *unixsockets = NULL; struct mount_list *mounts = NULL; dev_t netdev; struct ip_connections *tcp_connection_list = NULL; struct ip_connections *udp_connection_list = NULL; #ifdef WITH_IPV6 struct ip6_connections *tcp6_connection_list = NULL; struct ip6_connections *udp6_connection_list = NULL; #endif struct inode_list *match_inodes = NULL; struct names *names_head, *this_name, *names_tail; int argc_cnt; char *current_argv, *option; char option_buf[3]; struct option *optr; char *nsptr; int skip_argv; struct option options[] = { {"all", 0, NULL, 'a'}, {"kill", 0, NULL, 'k'}, {"interactive", 0, NULL, 'i'}, {"list-signals", 0, NULL, 'l'}, {"mount", 0, NULL, 'm'}, {"ismountpoint", 0, NULL, 'M'}, {"namespace", 1, NULL, 'n'}, {"silent", 0, NULL, 's'}, {"user", 0, NULL, 'u'}, {"verbose", 0, NULL, 'v'}, {"version", 0, NULL, 'V'}, #ifdef WITH_IPV6 {"ipv4", 0, NULL, '4'}, {"ipv6", 0, NULL, '6'}, #endif { 0, 0, 0, 0 } }; #ifdef WITH_IPV6 ipv4_only = ipv6_only = 0; #endif names_head = this_name = names_tail = NULL; opts = 0; sig_number = SIGKILL; #ifdef ENABLE_NLS /* Set up the i18n */ setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif netdev = find_net_dev(); fill_unix_cache(&unixsockets); for (argc_cnt = 1; argc_cnt < argc; argc_cnt++) { current_argv = argv[argc_cnt]; if (current_argv[0] == '-') { /* its an option */ if (current_argv[1] == '-') { /* its a long option */ if (current_argv[2] == '\0') /* -- */ break; /* Parse the long options */ option = option_buf; for (optr = options; optr->name != NULL; optr++) { if (strcmp(current_argv+2,optr->name) == 0) { sprintf(option_buf, "-%c", (char)optr->val); break; } } if (optr->name == NULL) { fprintf(stderr, _("%s: Invalid option %s\n"), argv[0], current_argv); usage(NULL); } } else { option = current_argv; } skip_argv=0; while (*(++option) != '\0' && !skip_argv) { /* skips over the - */ switch (*option) { #ifdef WITH_IPV6 case '4': ipv4_only = 1; break; case '6': ipv6_only = 1; break; #endif /* WITH_IPV6 */ case 'a': opts |= OPT_ALLFILES; break; case 'c': opts |= OPT_MOUNTS; break; case 'f': /* ignored */ break; case 'h': usage(NULL); break; case 'i': opts |= OPT_INTERACTIVE; break; case 'k': opts |= OPT_KILL; break; case 'l': list_signals(); return 0; case 'm': opts |= OPT_MOUNTS; break; case 'M': opts |= OPT_ISMOUNTPOINT; read_proc_mounts(&mounts); break; case 'n': argc_cnt++; if (argc_cnt >= argc) { usage(_ ("Namespace option requires an argument.")); exit(1);; } skip_argv=1; //while(option != '\0') option++; if (strcmp(argv[argc_cnt], "tcp") == 0) default_namespace = NAMESPACE_TCP; else if (strcmp(argv[argc_cnt], "udp") == 0) default_namespace = NAMESPACE_UDP; else if (strcmp(argv[argc_cnt], "file") == 0) default_namespace = NAMESPACE_FILE; else usage(_("Invalid namespace name")); break; case 's': opts |= OPT_SILENT; break; case 'u': opts |= OPT_USER; break; case 'v': opts |= OPT_VERBOSE; break; case 'V': print_version(); return 0; default: if (isupper(*option) || isdigit(*option)) { sig_number = get_signal(current_argv+1, argv[0]); skip_argv=1; break; } fprintf(stderr, "%s: Invalid option %c\n", argv[0], *option); usage(NULL); exit(1); break; } /* switch */ } /* while option */ continue; } /* an option */ /* Not an option, must be a file specification */ if ((this_name = malloc(sizeof(struct names))) == NULL) continue; this_name->next = NULL; /* try to find namespace spec */ this_name->name_space = default_namespace; if (((nsptr = strchr(current_argv, '/')) != NULL) && (nsptr != current_argv)) { if (strcmp(nsptr + 1, "tcp") == 0) { this_name->name_space = NAMESPACE_TCP; *nsptr = '\0'; } else if (strcmp(nsptr + 1, "udp") == 0) { this_name->name_space = NAMESPACE_UDP; *nsptr = '\0'; } else if (strcmp(nsptr + 1, "file") == 0) { this_name->name_space = NAMESPACE_FILE; *nsptr = '\0'; } } this_name->matched_procs = NULL; if (opts & (OPT_MOUNTS|OPT_ISMOUNTPOINT) && this_name->name_space != NAMESPACE_FILE) usage(_ ("You can only use files with mountpoint options")); if (opts & OPT_ISMOUNTPOINT && !is_mountpoint(&mounts, current_argv)) { free(this_name); continue; } switch (this_name->name_space) { case NAMESPACE_TCP: if (asprintf(&(this_name->filename), "%s/tcp", current_argv) > 0) { #ifdef WITH_IPV6 parse_inet(this_name, ipv4_only, ipv6_only, &tcp_connection_list, &tcp6_connection_list); #else parse_inet(this_name, &tcp_connection_list); #endif } break; case NAMESPACE_UDP: if (asprintf(&(this_name->filename), "%s/udp", current_argv) > 0) { #ifdef WITH_IPV6 parse_inet(this_name, ipv4_only, ipv6_only, &udp_connection_list, &udp6_connection_list); #else parse_inet(this_name, &udp_connection_list); #endif } break; default: /* FILE */ this_name->filename = strdup(current_argv); if (parse_file(this_name, &match_inodes) == 0) { parse_unixsockets(this_name, &match_inodes, unixsockets); if (opts & OPT_MOUNTS) parse_mounts(this_name, &match_devices, opts); } break; } if (names_head == NULL) names_head = this_name; if (names_tail != NULL) names_tail->next = this_name; names_tail = this_name; } /* for across the argvs */ if (names_head == NULL) usage(_("No process specification given")); if (opts & OPT_SILENT) { opts &= ~OPT_VERBOSE; opts &= ~OPT_USER; if (opts & OPT_ALLFILES) usage(_ ("all option cannot be used with silent option.")); } #ifdef WITH_IPV6 if (ipv4_only && ipv6_only) usage(_ ("You cannot search for only IPv4 and only IPv6 sockets at the same time")); if (!ipv6_only) { #endif if (tcp_connection_list != NULL) find_net_sockets(&match_inodes, tcp_connection_list, "tcp", netdev); if (udp_connection_list != NULL) find_net_sockets(&match_inodes, udp_connection_list, "udp", netdev); #ifdef WITH_IPV6 } if (!ipv4_only) { if (tcp6_connection_list != NULL) find_net6_sockets(&match_inodes, tcp6_connection_list, "tcp", netdev); if (udp6_connection_list != NULL) find_net6_sockets(&match_inodes, udp6_connection_list, "udp", netdev); } #endif #ifdef DEBUG debug_match_lists(names_head, match_inodes, match_devices); #endif scan_procs(names_head, match_inodes, match_devices, unixsockets, netdev); scan_knfsd(names_head, match_inodes, match_devices); scan_mounts(names_head, match_inodes, match_devices); scan_swaps(names_head, match_inodes, match_devices); return print_matches(names_head, opts, sig_number); }