Pythonic, but not prophetic


Posted on 09 September 2006 by jose

I was asked to present sample Python code recently. I figured since it was close to hand, digitally speaking, I might as well put it here as part of my code samples. The code below stems from my attempts to keep my dynamic IP address updated with my DNS provider (Zoneedit, if you're keeping score). That can be tricky sometimes; I've had instances when the Zoneedit DNS servers seem completely unresponsive, so no matter how clever the script, it can't really update anything. This is fairly rare, but extremely frustrating when it occurs.

Other tricky issues involve my router and the length of the connection timeout. It seems that on occasion, my router does not terminate a telneted session. This frequently happens when I'm telneting into it frequently when testing, say, a script to update my IP address on Zoneedit's servers.

When I first started using Zoneedit for dynamic DNS, they recommended various scripts to keep the DNS records updated. I've tried Ddclient (written in Perl), Inadyn (written in C), and Zoneclient (written in Python), and they all have their nifty features and quirks. When I tried Zoneclient out, I found that it could not communicate with my router. I didn't want to flood IP check websites with IP check requests, so decided to modify the script to get it to support my router. The main chunk of the resulting Python code is below:

  elif opt_RP114_password != "":
    #
    # RP114 router ip detection
    #

    #
    # determine the router host address
    #
    iphost = ""
    if RP114_host != "":
      logger.logit("RP114_host set explicitly.")
      iphost = RP114_host
    else:
      iphost = DefaultRoute(logger, Tempfile)

    if iphost == "":
      logger.logit("No router ip detected.  Assuming 192.168.0.1")
      iphost = "192.168.0.1"
    else:
      logline = "Trying router at " + iphost
      logger.logit(logline)

    # connect to the router's admin webpage
    try:
      logger.logit("Trying Netgear RP114")
      tn = telnetlib.Telnet(iphost)
      logger.logit("Creating telnetlib obj done")
      tn.read_until("assword:")
      logger.logit("Password prompt found")
      tn.write(opt_RP114_password + "\r\n")
      logger.logit("opt_RP114_password sent")
      #tn.read_until("Menu Selection Number:")
      tn.write("24\r\n")
      logger.logit("menu number 24 sent")
      #tn.read_until("Menu Selection Number:")
      tn.write("8\r\n")
      logger.logit("menu number 8 sent")
      tn.write("ip ifconfig\r\n")
      logger.logit("ip ifconfig sent")
      ip1 = tn.read_until("netmask", 3000)
      ip2 = tn.read_until("netmask 0xf", 3000)
      logger.logit("ip1 and ip2 read")
      tn.write("exit\r\n")
      logger.logit("exit sent")
      #tn.read_until("Menu Selection Number:")
      tn.write("99\r\n")
      logger.logit("menu number 99 sent")
      ipdata = ip1 + ip2
    except:
      logline = "No address found on router at " + iphost
      logger.logexit(logline)
      sys.exit(-1)

    # create an output file of the response
    filename = "RP114.out"
    if opt_directory != "":
      filename = opt_directory + filename
    fp = open(filename, "w")
    fp.write(ipdata)
    fp.close()
    logger.logit("RP114.out file created")

    # look for the last device in the log
    p1 = string.rfind(ipdata, "wanif")
    if p1 != -1:
      ipmatch = Addressgrep.search(ipdata, p1)
      if ipmatch != None:
        localip = ipmatch.group()
        logger.logit("IP matched: " + localip)
    else:
      p1 = string.rfind(ipdata, "enif")
      if p1 != -1:
        ipmatch = Addressgrep.search(ipdata, p1)
        if ipmatch != None:
          localip = ipmatch.group()
          logger.logit("IP matched: " + localip)

Tangent: I always have to play tricks on Wordpress's text to XHTML conversion scripts when I want to embed code in a post. This is because the scripts add extra </p> tags and other elements where they don't quite belong. That's the downside to hand-coding (X)HTML; when programs think they know better than you and try to correct the text (as they see it), they create more problems, particularly if you care about your page validating to a certain standard. That said, it is unfair to burden these programs with the expectation of mind-reading; there's just no way for the scripts to know when I'm writing plain-text that needs to be wrapped in valid XHTML and when I'm mixing plain-text with (X)HTML.

Latest poll

Which do you favor?

Choices

Twitter