#!/usr/bin/env ruby ENV["LANG"]="en_US.utf-8" ENV["LC_CTYPE"]="en_US.utf-8" ENV["KRAMDOWN_PERSISTENT"]="yes" require 'optparse' require 'ostruct' require 'socket' require 'tempfile' require_relative "../lib/kdwatch/version" KDWATCH_PORT = 7991 # currently unregistered... def socket_is_free(host, port, uri) host = "localhost" if host == "::" begin TCPSocket.new(host, port, connect_timeout: 1) rescue Errno::ECONNREFUSED => e return true rescue => e warn "*** #{uri} -- #{e.inspect}" return nil # break, but don't use end return false end options = OpenStruct.new op = OptionParser.new do |opts| opts.banner = < e warn "** #{e}" warn op exit 1 end if options.internet warn "** overriding host #{options.host} with ::" if options.host options.host = "::" else options.host ||= "127.0.0.1" end if short_port = options[""] port = short_port + KDWATCH_PORT/10*10 warn "** overriding port #{options.port} with #{port}" if options.port options.port = port else unless options.port port = KDWATCH_PORT host = options.host host = "[#{host}]" if host =~ /:/ uri = nil found = false 100.times do uri = "http://#{host}:#{port}" # warn "Trying URI #{uri}" found = socket_is_free(options.host, port, uri) break unless found == false port += 1 end unless found warn "*** Cannot find port number available to serve from!" exit 1 end warn "*** Using URI: #{uri}" options.port = port end end # p options ## -r: Kill any previous kdwatch and continue ("restart") ## -e: Kill any previous kdwatch and exit if options.replace || options.end require 'open3' status = 1 lsof_host = case options.host when "::", "0.0.0.0" "" # can't do more specific with lsof; hope for the best when /:/ "@'[#{options.host}]'" else "@'#{options.host}'" end stdout_str, stderr_str, s = Open3.capture3("lsof -ti #{lsof_host}:#{options.port} -s TCP:LISTEN") pids = if s.success? && stdout_str =~ /\A[0-9\s]*\z/ && stderr_str stdout_str.split else text = stdout_str + stderr_str warn "** lsof, status #{s}, says: #{text}" if text != "" || s.exitstatus != 1 [] end if pids == [] warn "** Nothing listening on kdwatch port" unless options.replace elsif pids.size != 1 warn "** More than one process listening on kdwatch port, nothing done" else begin status = Process.kill(2, Integer(pids[0])) - 1 # should be 1 for 1 kill, exit 0 then rescue Errno => e warn "** #{pids[0]}: #{e.inspect}" end end exit(status) if options.end end ## Find an .mkd or a draft-*.md (excluding README.md and such) if ARGV == [] ARGV.replace Dir.glob(["draft-*.md", "*.mkd"]) warn_replace = 1 end if ARGV.size != 1 warn op if warn_replace if ARGV.size > 1 warn "** More than one draft file found #{ARGV.inspect}" warn "** Please select one for watching." else warn "** No draft file draft-*.md or *.mkd found." end end exit 1 end ENV["KDWATCH_SRC"] = ARGV[0] ENV["KDWATCH_HOST"] = options.host ENV["KDWATCH_PORT"] = options.port.to_s live_reload_port = options.port + 51234 # move up into ephemeral space ENV["KDWATCH_LRPORT"] = live_reload_port.to_s tf = Tempfile.new('kdwatch-config-ru-') path = tf.path rupath = "#{path}.ru" tf.write(<