int main(int argc, char *argv[]) { int ch; char *stuff; char tmp_filename[] = "/tmp/lockalot.XXXXXXXXXX"; struct pollfd pfd[1]; while ((ch = getopt(argc, argv, "h?Lm:")) != -1) { switch (ch) { case 'L': Flag_Skip_Mlock = true; case 'm': Flag_Mem_Amount = flagtoul(ch, optarg, 1UL, MOSTMEMPOSSIBLE); break; case 'h': case '?': default: emit_help(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (Flag_Mem_Amount == 0) emit_help(); if ((stuff = malloc((size_t) Flag_Mem_Amount)) == NULL) err(EX_OSERR, "could not malloc() %lu bytes of memory", Flag_Mem_Amount); if (!Flag_Skip_Mlock) if (mlock(stuff, (size_t) Flag_Mem_Amount) == -1) err(EX_OSERR, "could not mlock() %lu bytes of memory", Flag_Mem_Amount); // Avoid busy loop if cannot block on input (e.g. started in background) if (isatty(STDIN_FILENO)) { pfd[0].fd = STDIN_FILENO; } else { fprintf(stderr, "notice: doing mkstemp to create file to poll...\n"); if ((pfd[0].fd = mkstemp(tmp_filename)) == -1) err(EX_IOERR, "mkstemp failed to create tmp file"); } pfd[0].events = POLLPRI; for (;;) { poll(pfd, 1, 60 * 10000); } /* NOTREACHED */ exit(1); }
int main(int argc, char *argv[]) { int ch; while ((ch = getopt(argc, argv, "h?q")) != -1) { switch (ch) { case 'q': Flag_Quiet = true; break; case 'h': case '?': default: emit_help(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc < 1) emit_help(); /* Edge case. If YYYY-MM or YYYY only thing supplied, a mday of 0 (the * default due to where declared) will drag the epoch surprisingly back * to the previous month. */ when.tm_mday = 1; if (!strptime(*argv, "%Y-%m-%d", &when)) if (!strptime(*argv, "%Y-%m", &when)) if (!strptime(*argv, "%Y", &when)) errx(EX_DATAERR, "could not parse YYYY-MM-DD"); if (argc > 1) { ++argv; if (!strptime(*argv, "%H:%M:%S", &when)) if (!strptime(*argv, "%H:%M", &when)) if (!strptime(*argv, "%H", &when)) errx(EX_DATAERR, "could not parse HH:MM[:SS]"); } if (argc > 2 && !Flag_Quiet) { ++argv; if (!((strncmp(*argv, "UTC", (size_t) 4) == 0) || (strncmp(*argv, "GMT", (size_t) 4) == 0))) warnx("use of unknown timezone %s may lead to incorrect epoch", *argv); } printf("%ld\n", (long) timegm(&when)); exit(EXIT_SUCCESS); }
void process_command_line_args(int argc,char **argv, enum timemodes *tmode, struct timeval *start_time){ int numarg=0; *tmode=NORMAL; while( ++numarg < argc){ if( (lcl_strcasecmp(argv[numarg], "-h")==0) || (lcl_strcasecmp(argv[numarg], "--h")==0) || (lcl_strcasecmp(argv[numarg], "-?")==0) || (lcl_strcasecmp(argv[numarg], "--?")==0) || (lcl_strcasecmp(argv[numarg], "-help")==0) || (lcl_strcasecmp(argv[numarg], "--help")==0) ){ emit_help(); } else if(lcl_strcasecmp(argv[numarg], "-i")==0){ (void)fprintf(stderr,"Version: %s\n",VERSTRING); (void)fprintf(stderr,"bugs to: [email protected]\n"); (void)fprintf(stderr,"Copyright: 2002 David Mathog and California Institute of Technology\n"); (void)fprintf(stderr,"License terms:\n"); (void)fprintf(stderr," You may run this program on any platform. You may\n"); (void)fprintf(stderr," redistribute the source code of this program subject to\n"); (void)fprintf(stderr," the condition that you do not first modify it in any way.\n"); (void)fprintf(stderr," You may distribute binary versions of this program so long\n"); (void)fprintf(stderr," as they were compiled from unmodified source code. There\n"); (void)fprintf(stderr," is no charge for using this software. You may not charge\n"); (void)fprintf(stderr," others for the use of this software.\n"); exit(EXIT_SUCCESS); } else if(lcl_strcasecmp(argv[numarg], "-ds")==0){ setzerotime(start_time,&numarg,argc,argv,"-ds"); *tmode=DELTASECONDS; continue; } else if(lcl_strcasecmp(argv[numarg], "-df")==0){ setzerotime(start_time,&numarg,argc,argv,"-df"); *tmode=DELTA; continue; } else if(lcl_strcasecmp(argv[numarg], "-t0")==0){ *tmode=TZERO; continue; } else (void) fprintf(stderr,"Unknown command line argument: %s\n",argv[numarg]); exit(EXIT_FAILURE); continue; } }
int main(int argc, char *argv[]) { int ch, exit_status, status; pid_t bill; exit_status = EXIT_SUCCESS; while ((ch = getopt(argc, argv, "h?q")) != -1) { switch (ch) { case 'q': Flag_Quiet = true; break; case 'h': case '?': default: emit_help(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc < 2) emit_help(); iTimer.it_value.tv_sec = parse_duration(*argv++); bill = vfork(); if (bill == 0) { /* child */ if (execvp(*argv, argv) == -1) err(EX_OSERR, "could not exec %s", *argv); /* NOTREACHED */ } else if (bill > 0) { /* parent */ /* do not restart the wait() after SIGALRM, skip to the end... */ if (siginterrupt(SIGALRM, 1) == -1) err(EX_SOFTWARE, "could not siginterrupt()"); if (signal(SIGALRM, handle_alarm) == SIG_ERR) err(EX_SOFTWARE, "could not setup signal()"); if (setitimer(ITIMER_REAL, &iTimer, NULL) == -1) err(EX_SOFTWARE, "could not setitimer()"); wait(&status); /* the end */ if (Kill_Bill) { if (!Flag_Quiet) warnx("duration %ld exceeded: killing pid %d", (long)iTimer.it_value.tv_sec, bill); /* * Assume child is well behaved, and does not deadlock or * otherwise require multiple signals (race condition risk) to * take down. */ if (kill(bill, SIGTERM) == -1) err(EX_OSERR, "could not kill child pid %d", bill); exit_status = EXIT_TIMEOUT; } else { /* * Pass on the child exit status. These can be illustrated * via something like: * * timeout 99 perl -e 'exit 42' ; echo $? * timeout 99 perl -e 'kill 15, $$' ; echo $? */ if (WIFEXITED(status)) exit_status = WEXITSTATUS(status); else if (WIFSIGNALED(status)) exit_status = 128 + WTERMSIG(status); } } else { err(EX_OSERR, "could not fork()"); } exit(exit_status); }
int main(int argc, char *argv[]) { int ch; const char *errstr; struct passwd *pw; sigset_t blockmask; int nfds; struct pollfd pfd[POLL_FDS]; int fd4; socklen_t sin4_len; struct ip *ip4_hdr; struct sockaddr_in sin4; uint32_t hlen; int fd6; socklen_t sin6_len; struct ip6_hdr *ip6_hdr; struct sockaddr_in6 sin6; ssize_t nbytes; uint8_t packet[IP_MAXPACKET]; ssize_t range; while ((ch = getopt(argc, argv, "h?C:D:R:W:c:df:su:")) != -1) { switch (ch) { case 'C': Flag_Corrupt = flagtod(ch, optarg, 0.0, 1.0); break; case 'D': Flag_Drop = flagtod(ch, optarg, 0.0, 1.0); break; case 'R': Flag_Duplicate = flagtod(ch, optarg, 0.0, 1.0); break; case 'W': Flag_Delay = flagtod(ch, optarg, 0.0, 1.0); break; case 'a': Flag_Corrupt_All = true; break; case 'c': if ((Flag_Corrupt_Count = (uint8_t) strtonum(optarg, 1LL, (long long) UINT8_MAX, &errstr)) == 0) { if (errstr) err(EX_DATAERR, "could not parse -c flag"); } break; case 'd': Flag_Debug = true; break; case 'f': if ((Flag_Direction = strtonum(optarg, 0LL, 2LL, &errstr)) == 0) { if (errstr) err(EX_DATAERR, "could not parse -f flag"); } else { Flag_Direction = (Flag_Direction == 1) ? IPPROTO_DIVERT_INIT : IPPROTO_DIVERT_RESP; } break; case 's': Flag_Scrub_Mem = true; break; case 'u': Flag_User = optarg; break; case 'h': case '?': default: emit_help(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc != 1) emit_help(); if ((Divert_Port = (uint16_t) strtonum(*argv, DIVERT_MINPORT, (long long) DIVERT_MAXPORT, &errstr)) == 0) { if (errstr) err(EX_DATAERR, "could not parse divert port number"); } if (geteuid()) errx(EX_USAGE, "must be run as root"); if (Flag_Corrupt) { if (Flag_Corrupt_Count == 0) Flag_Corrupt_Count = 1; } /* IPv4 setup */ if ((fd4 = socket(AF_INET, SOCK_RAW, IPPROTO_DIVERT)) == -1) err(EX_OSERR, "socket() failed for IPv4"); if (Flag_Direction) { if (setsockopt (fd4, IPPROTO_IP, IP_DIVERTFL, &Flag_Direction, (socklen_t) sizeof(Flag_Direction)) == -1) err(EX_OSERR, "setsockopt() -f failed for IPv4"); } explicit_bzero(&sin4, sizeof(sin4)); sin4.sin_family = AF_INET; sin4.sin_port = htons(Divert_Port); sin4.sin_addr.s_addr = 0; sin4_len = sizeof(struct sockaddr_in); if (bind(fd4, (struct sockaddr *) &sin4, sin4_len) == -1) err(EX_OSERR, "bind() failed for IPv4"); v4stash.packet = NULL; /* IPv6 setup */ if ((fd6 = socket(AF_INET6, SOCK_RAW, IPPROTO_DIVERT)) == -1) err(EX_OSERR, "socket() failed for IPv6"); if (Flag_Direction) { if (setsockopt (fd6, IPPROTO_IPV6, IP_DIVERTFL, &Flag_Direction, (socklen_t) sizeof(Flag_Direction)) == -1) err(EX_OSERR, "setsockopt() -f failed for IPv6"); } explicit_bzero(&sin6, sizeof(sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_len = sizeof(struct sockaddr_in6); sin6.sin6_port = htons(Divert_Port); sin6_len = sizeof(struct sockaddr_in6); if (bind(fd6, (struct sockaddr *) &sin6, sin6.sin6_len) == -1) err(EX_OSERR, "bind() failed for IPv6"); v6stash.packet = NULL; if (Flag_User) { if ((pw = getpwnam(Flag_User)) == NULL) err(EX_OSERR, "getpwnam() for -u user failed"); if (chroot(pw->pw_dir) == -1) err(EX_OSERR, "chroot() failed"); if (chdir("/") == -1) err(EX_OSERR, "chdir(\"/\") failed"); if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) errx(EX_OSERR, "could not drop privileges"); } if (!Flag_Debug) { if (daemon(1, 1) == -1) err(EX_OSERR, "daemon() call failed"); } signal(SIGALRM, sig_handle); signal(SIGINT, sig_handle); signal(SIGTERM, sig_handle); ualarm(TICK_MS, TICK_MS); sigemptyset(&blockmask); sigaddset(&blockmask, SIGALRM); sigaddset(&blockmask, SIGINT); sigaddset(&blockmask, SIGTERM); explicit_bzero(&pfd, sizeof(pfd)); pfd[PFD_IPV4].fd = fd4; pfd[PFD_IPV4].events = POLLIN; pfd[PFD_IPV6].fd = fd6; pfd[PFD_IPV6].events = POLLIN; for (;;) { if ((nfds = poll(pfd, POLL_FDS, -1)) == -1) { if (errno != EINTR) err(EX_OSERR, "poll() failed"); } /* flush any delayed and bail out */ if (Sig_Terminate) { sigprocmask(SIG_BLOCK, &blockmask, NULL); if (v4stash.packet) { if (sendto (fd4, v4stash.packet, (size_t) v4stash.nbytes, 0, (struct sockaddr *) &sin4, sin4_len) == -1) if (Flag_Debug) warn("IPv4 sendto() failed"); if (Flag_Scrub_Mem) explicit_bzero(v4stash.packet, (size_t) v4stash.nbytes); free(v4stash.packet); v4stash.packet = NULL; } if (v6stash.packet) { if (sendto (fd6, v6stash.packet, (size_t) v6stash.nbytes, 0, (struct sockaddr *) &sin6, sin6_len) == -1) if (Flag_Debug) warn("IPv6 sendto() failed"); if (Flag_Scrub_Mem) explicit_bzero(v6stash.packet, (size_t) v6stash.nbytes); free(v6stash.packet); v6stash.packet = NULL; } if (Flag_Scrub_Mem) explicit_bzero(packet, (size_t) IP_MAXPACKET); exit(1); } if (nfds > 0 && pfd[PFD_IPV4].revents & POLLIN) { range = -1; explicit_bzero(packet, sizeof(packet)); if ((nbytes = recvfrom(fd4, packet, sizeof(packet), 0, (struct sockaddr *) &sin4, &sin4_len)) == -1) { if (Flag_Debug) warn("IPv4 recvfrom() error"); continue; } if (nbytes < (ssize_t) sizeof(struct ip)) { if (Flag_Debug) warnx("IPv4 packet is too short"); continue; } ip4_hdr = (struct ip *) packet; hlen = ip4_hdr->ip_hl << 2; if (hlen < sizeof(struct ip) || ntohs(ip4_hdr->ip_len) < hlen || nbytes < ntohs(ip4_hdr->ip_len)) { if (Flag_Debug) warnx("invalid IPv4 packet"); continue; } /* IPv4 decision */ if (Flag_Delay && FATED_TO(Flag_Delay)) { if (!v4stash.packet) { v4stash.nbytes = nbytes; if ((v4stash.packet = malloc((size_t) nbytes)) == NULL) { if (Flag_Debug) warn("could not malloc() stash for IPv4 packet"); } else { bcopy(packet, v4stash.packet, (size_t) nbytes); } if (Flag_Corrupt) { if (!corrupt_v4 (v4stash.packet, nbytes, ip4_hdr, &hlen, &range)) continue; } } if (Flag_Duplicate && !FATED_TO(Flag_Duplicate)) { continue; } } else if (Flag_Drop && FATED_TO(Flag_Drop)) { continue; } if (Flag_Corrupt) { if (!corrupt_v4(packet, nbytes, ip4_hdr, &hlen, &range)) continue; } if (sendto (fd4, packet, (size_t) nbytes, 0, (struct sockaddr *) &sin4, sin4_len) == -1) if (Flag_Debug) warn("IPv4 sendto() failed"); } if (nfds > 0 && pfd[PFD_IPV6].revents & POLLIN) { range = -1; explicit_bzero(packet, sizeof(packet)); if ((nbytes = recvfrom(fd6, packet, sizeof(packet), 0, (struct sockaddr *) &sin6, &sin6_len)) == -1) { if (Flag_Debug) warn("IPv6 recvfrom() error"); continue; } if (nbytes < (ssize_t) sizeof(struct ip6_hdr)) { if (Flag_Debug) warnx("IPv6 packet is too short"); continue; } ip6_hdr = (struct ip6_hdr *) packet; hlen = ntohs(ip6_hdr->ip6_plen); if (hlen == 0) { if (Flag_Debug) warnx("discarding unsupported IPv6 jumbo packet"); continue; } if (hlen > nbytes) { if (Flag_Debug) warnx("invalid IPv6 packet"); continue; } /* IPv6 decision */ if (Flag_Delay && FATED_TO(Flag_Delay)) { if (!v6stash.packet) { v6stash.nbytes = nbytes; if ((v6stash.packet = malloc((size_t) nbytes)) == NULL) { if (Flag_Debug) warn("could not malloc() stash for IPv6 packet"); } else { bcopy(packet, v6stash.packet, (size_t) nbytes); } if (Flag_Corrupt) { if (!corrupt_v6 (v6stash.packet, nbytes, ip6_hdr, &hlen, &range)) continue; } } if (Flag_Duplicate && !FATED_TO(Flag_Duplicate)) { continue; } } else if (Flag_Drop && FATED_TO(Flag_Drop)) { continue; } if (Flag_Corrupt) { if (!corrupt_v6(packet, nbytes, ip6_hdr, &hlen, &range)) continue; } if (sendto (fd6, packet, (size_t) nbytes, 0, (struct sockaddr *) &sin6, sin6_len) == -1) if (Flag_Debug) warn("IPv6 sendto() failed"); } if (Sig_Flush) { if (v4stash.packet) { if (sendto (fd4, v4stash.packet, (size_t) v4stash.nbytes, 0, (struct sockaddr *) &sin4, sin4_len) == -1) if (Flag_Debug) warn("IPv4 sendto() failed"); if (Flag_Scrub_Mem) explicit_bzero(v4stash.packet, (size_t) v4stash.nbytes); free(v4stash.packet); v4stash.packet = NULL; } if (v6stash.packet) { if (sendto (fd6, v6stash.packet, (size_t) v6stash.nbytes, 0, (struct sockaddr *) &sin6, sin6_len) == -1) if (Flag_Debug) warn("IPv6 sendto() failed"); if (Flag_Scrub_Mem) explicit_bzero(v6stash.packet, (size_t) v6stash.nbytes); free(v6stash.packet); v6stash.packet = NULL; } Sig_Flush = 0; } } exit(1); /* NOTREACHED */ }
int main(int argc, char *argv[]) { char **fbufs; int ch, *fds; long long *deltas; off_t fsize; size_t deltacount; struct stat statbuf; deltacount = 0; deltas = NULL; while ((ch = getopt(argc, argv, "h?d:")) != -1) { switch (ch) { case 'd': flagtololls(ch, optarg, -255LL, 255LL, &deltas, &deltacount, 1UL, MAX_DELTAS); break; case 'h': case '?': default: emit_help(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc <= 0 || deltacount == 0) emit_help(); if ((fds = calloc((size_t) argc, sizeof(int))) == NULL) err(EX_OSERR, "could not calloc() list of file descriptors"); if ((fbufs = calloc((size_t) argc, sizeof(char *))) == NULL) err(EX_OSERR, "could not calloc() list of file buffer pointers"); /* all files assumed of equal size as first */ if (stat(*argv, &statbuf) == -1) err(EX_IOERR, "could not stat '%s'", *argv); fsize = statbuf.st_size; if (fsize <= 0) errx(EX_DATAERR, "file '%s' is empty", *argv); if (fsize > INT_MAX) errx(EX_DATAERR, "file '%s' is too large", *argv); if (argc > (int) deltacount + 1) { warnx("notice: more files than deltas"); argc = (int) deltacount + 1; } /* TODO could use less memory by only having two images in memory at * once, or to improve the logic so deltas are done between all of * the images or that the logic is applied across all the files, and * not just for the two files and location in question. */ for (int i = 0; i < argc; i++) { if ((fds[i] = open(argv[i], O_RDONLY)) == -1) err(EX_IOERR, "could not open '%s'", argv[i]); if ((fbufs[i] = malloc((size_t) fsize * sizeof(char))) == NULL) err(EX_OSERR, "could not malloc() file buffer %d", i); if (read(fds[i], fbufs[i], (size_t) fsize) != fsize) err(EX_IOERR, "could not read exactly %lld from '%s'", fsize, argv[i]); } for (int i = 0; i < argc - 1; i++) { for (off_t w = 0; w < fsize; w++) { if ((fbufs[i + 1][w] - fbufs[i][w]) == (int) deltas[i]) { printf("%04X\n", (unsigned int) w); } } } exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { char buf[] = "all writes and no planning make filesystem go something something... "; unsigned long buf_size = sizeof(buf); int ch; /* getopt */ unsigned int backoff = 1; /* write failure delay (seconds) */ struct sigaction act; /* SIGUSR1 */ while ((ch = getopt(argc, argv, "hq")) != -1) { switch (ch) { case 'h': emit_help(); /* NOTREACHED */ case 'q': Flag_Quiet = 1; break; default: ; } } argc -= optind; argv += optind; if (argc == 0 || argv[0] == NULL) emit_help(); /* could also check if filename is "" but open(2) barfs on that so meh */ if (strnlen(argv[0], PATH_MAX) >= PATH_MAX) errx(EX_DATAERR, "filename exceeds PATH_MAX"); /* XXX need to learn me the mask stuff better */ if ((fd = open(argv[0], O_APPEND | O_CREAT | O_EXCL | O_NOFOLLOW | O_WRONLY, S_IRUSR | S_IWUSR)) < 0) err(EX_IOERR, "open() error for '%s'", argv[0]); act.sa_handler = do_close; sigemptyset(&act.sa_mask); act.sa_flags = 0; if (sigaction(SIGUSR1, &act, NULL) != 0) err(EX_OSERR, "sigaction() error"); /* * Or just use a wrapper: * * #!/bin/sh * echo $$ * exec fillerup -q */ if (!Flag_Quiet) fprintf(stderr, "pid %ld\n", (long int) getpid()); while (done_writing != 1) { if (write(fd, buf, buf_size) < 0) { if (!Flag_Quiet) warn("write() error"); sleep(backoff); backoff <<= 1; if (backoff > MAX_BACKOFF) backoff = MAX_BACKOFF; } else { backoff = 1; } } exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { FILE *fh; char *line = NULL; int ch; size_t linesize = 0; ssize_t linelen; ssize_t linenum = 1; time_t now; if (!setlocale(LC_ALL, "")) errx(EX_USAGE, "setlocale(3) failed: check the locale settings"); /* As otherwise the default of 0 could cause time formats that do not * include the date to skip back to a date in the previous month. */ When.tm_mday = 1; while ((ch = getopt(argc, argv, "f:gh?o:syY:")) != -1) { switch (ch) { case 'f': Flag_Input_Format = optarg; break; case 'g': Flag_Global = true; break; case 'o': Flag_Output_Format = optarg; break; case 's': Flag_Suppress = true; break; case 'y': if (time(&now) == (time_t) - 1) errx(EX_OSERR, "time(3) could not obtain current time??"); if (localtime_r(&now, &When) == NULL) errx(EX_OSERR, "localtime_r(3) failed??"); Flag_Custom_Year = true; break; case 'Y': if (!strptime(optarg, "%Y", &When)) errx(EX_USAGE, "strptime(3) could not parse year from -Y flag"); Flag_Custom_Year = true; break; case 'h': case '?': default: emit_help(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (!Flag_Input_Format) emit_help(); /* Due to crazy behavior on Mac OS X (see also guard for it, below), and * otherwise there are less expensive syscalls that can better deal with * epoch values. */ if (strncmp(Flag_Input_Format, "%s", (size_t) 2) == 0) errx(EX_DATAERR, "%%s is not supported as input format"); if (argc == 0 || strncmp(*argv, "-", (size_t) 2) == 0) { fh = stdin; } else { if ((fh = fopen(*argv, "r")) == NULL) err(EX_IOERR, "could not open '%s'", *argv); File_Name = *argv; } while ((linelen = getline(&line, &linesize, fh)) != -1) { parseline(line, linenum); linenum++; } if (ferror(fh)) err(EX_IOERR, "error reading file"); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { int ch, ret, sockfd; char ipstr[INET_ADDRSTRLEN]; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; while ((ch = getopt(argc, argv, "46suh?")) != -1) { switch (ch) { case '4': hints.ai_family = AF_INET; break; case '6': hints.ai_family = AF_INET6; break; case 's': Flag_Stick_Around = true; break; case 'u': hints.ai_socktype = SOCK_DGRAM; break; case 'h': case '?': default: emit_help(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc != 2) emit_help(); setvbuf(stdout, (char *)NULL, _IOLBF, (size_t) 0); if ((ret = getaddrinfo(argv[0], argv[1], &hints, &res)) != 0) errx(EX_NOHOST, "getaddrinfo error: %s", gai_strerror(ret)); for (remote = res; remote != NULL; remote = remote->ai_next) { if ((sockfd = socket(remote->ai_family, remote->ai_socktype, remote->ai_protocol)) == -1) { warn("socket() error"); continue; } /* Do need to connect first, unless you like seeing [::] or * 0.0.0.0 as your local address. */ if (connect(sockfd, remote->ai_addr, remote->ai_addrlen) == -1) { warn("connect() error"); continue; } break; } if (remote == NULL) errx(EX_IOERR, "could not connect to socket()"); switch (remote->ai_family) { case AF_INET: if ((localsa = malloc(sizeof(struct sockaddr_in))) == NULL) err(EX_OSERR, "malloc() sockaddr_in failed"); break; case AF_INET6: if ((localsa = malloc(sizeof(struct sockaddr_in6))) == NULL) err(EX_OSERR, "malloc() sockaddr_in6 failed"); break; default: errx(EX_OSERR, "unknown address family???"); } localsa_len = remote->ai_addrlen; if (getsockname(sockfd, localsa, &localsa_len) == -1) err(EX_OSERR, "getsockname() failed"); switch (localsa->sa_family) { case AF_INET: inet_ntop(AF_INET, &(((struct sockaddr_in *) localsa)->sin_addr), ipstr, localsa_len); printf("local %s:%u\n", ipstr, ntohs(((struct sockaddr_in *) localsa)->sin_port)); break; case AF_INET6: inet_ntop(AF_INET6, &(((struct sockaddr_in6 *) localsa)->sin6_addr), ipstr, localsa_len); printf("local [%s]:%u\n", ipstr, ntohs(((struct sockaddr_in6 *) localsa)->sin6_port)); break; default: errx(EX_OSERR, "unknown address family???"); } /* Cheap blocking trick. Then, presumably, `lsof -i -nP` or * `netstat` or something would be used to investigate what this * program has opened. `fg` will then bring the program back so * it can exit. */ if (Flag_Stick_Around) raise(SIGTSTP); exit(EXIT_SUCCESS); }