def main():
    try:
        signal.signal(signal.SIGTSTP, signal.SIG_IGN)  # ignore CTRL+Z
        signal.signal(signal.SIGINT, signal_handler)  # custom CTRL+C handler
    except AttributeError: # not all signals are supported on all platforms
        pass

    if len(sys.argv) == 1:
        usage()

    dnsrecord = 'A'
    count = 30
    timeout = 1
    quiet = False
    dnsserver = dns.resolver.get_default_resolver().nameservers[0]
    dest_port = 53
    hops = 0
    as_lookup = False
    should_resolve = True

    try:
        opts, args = getopt.getopt(sys.argv[1:], "aqhc:s:t:w:p:n",
                                   ["help", "count=", "server=", "quiet", "type=", "wait=", "asn", "port"])
    except getopt.GetoptError as err:
        # print help information and exit:
        print(err)  # will print something like "option -a not recognized"
        usage()

    if args and len(args) == 1:
        hostname = args[0]
    else:
        usage()

    for o, a in opts:
        if o in ("-h", "--help"):
            usage()
        elif o in ("-c", "--count"):
            count = int(a)
        elif o in ("-s", "--server"):
            dnsserver = a
        elif o in ("-q", "--quiet"):
            quiet = True
        elif o in ("-w", "--wait"):
            timeout = int(a)
        elif o in ("-t", "--type"):
            dnsrecord = a
        elif o in ("-p", "--port"):
            dest_port = int(a)
        elif o in ("-n"):
            should_resolve = False
        elif o in ("-a", "--asn"):
            if has_whois:
                as_lookup = True
            else:
                print('Warning: cymruwhois module cannot be loaded. AS Lookup disabled.')
        else:
            usage()

    resolver = dns.resolver.Resolver()
    resolver.nameservers = [dnsserver]
    resolver.timeout = timeout
    resolver.lifetime = timeout
    resolver.retry_servfail = 0

    icmp = socket.getprotobyname('icmp')

    ttl = 1
    reached = False

    if not quiet:
        print("%s DNS: %s:%d, hostname: %s, rdatatype: %s" % (__PROGNAME__, dnsserver, dest_port, hostname, dnsrecord))

    while True:
        if should_stop:
            break

        # some platforms permit opening a DGRAM socket for ICMP without root permission
        # if not availble, we will fall back to RAW which explicitly requires root permission
        try:
            icmp_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
        except OSError:
            try:
                icmp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, icmp)
            except OSError:
                print("Error: Unable to create ICMP socket with unprivileged user. Please run as root.")
                exit(1)

        icmp_socket.bind(("", dest_port))
        icmp_socket.settimeout(timeout)

        try:  # send DNS request
            stime = time.time()
            resolver.query(hostname, dnsrecord, ipttl=ttl)
        except dns.resolver.NoNameservers as e:
            if not quiet:
                print("no or bad response:", e)
            exit(1)
        except dns.resolver.NXDOMAIN as e:
            if not quiet:
                print("Invalid hostname:", e)
            exit(1)
        except dns.resolver.Timeout:
            pass
        except dns.resolver.NoAnswer:
            if not quiet:
                print("invalid answer")
            pass
        except SystemExit:
            pass
        except:
            print("unxpected error: ", sys.exc_info()[0])
            exit(1)
        else:
            reached = True

        curr_addr = None
        curr_host = None

        try:  # expect ICMP response
            _, curr_addr = icmp_socket.recvfrom(512)
            curr_addr = curr_addr[0]

        except socket.error:
            pass

        finally:
            icmp_socket.close()

        etime = time.time()
        elapsed = (etime - stime) * 1000  # convert to milliseconds

        if reached:
            curr_addr = dnsserver

        elapsed -= timeout * 1000

        if should_resolve:
            try:
                if curr_addr:
                    curr_name = socket.gethostbyaddr(curr_addr)[0]
            except socket.error:
                curr_name = curr_addr
            except SystemExit:
                pass
            except:
                print("unxpected error: ", sys.exc_info()[0])
        else:
            curr_name = curr_addr

        if curr_addr:
            as_name = ""
            if has_whois and as_lookup:
                ASN = whoisrecord(curr_addr)
                as_name = ''
                try:
                    if ASN and ASN.asn != "NA":
                        as_name = "[%s %s] " % (ASN.asn, ASN.owner)
                except __HOLE__:
                    if should_stop:
                        exit(0)
                    pass

            print("%d\t%s (%s) %s%d ms" % (ttl, curr_name, curr_addr, as_name, elapsed))
        else:
            print("%d\t *" % ttl)

        ttl += 1
        hops += 1
        if (hops >= count) or (curr_addr == dnsserver) or reached:
            break
dataset/ETHPy150Open farrokhi/dnstools/dnstraceroute.py/main