diff options
Diffstat (limited to 'content/posts/WIP-how-bsd-authentication-works/gen_dot.rb')
-rw-r--r-- | content/posts/WIP-how-bsd-authentication-works/gen_dot.rb | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/content/posts/WIP-how-bsd-authentication-works/gen_dot.rb b/content/posts/WIP-how-bsd-authentication-works/gen_dot.rb new file mode 100644 index 0000000..9925d8c --- /dev/null +++ b/content/posts/WIP-how-bsd-authentication-works/gen_dot.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +SOURCE_DIR = File.join Dir.home, 'src', 'github.com', 'openbsd', 'src', 'lib', 'libc', 'gen' +FILENAMES = %w[authenticate.c auth_subr.c login_cap.c].freeze + +FUNCTION_REGEX = /^\w.*?$\n(\w*)\(.*?\)\n\{(.*?)^\}/m.freeze +ONELINE_FUNCTION_REFGEX = /^\w.*?(\w*)\(.*?\).*?\{(.*?)\}/.freeze +CALL_REGEX = /[^\n](\w+)\(.*?\)/.freeze + +class FunctionDigraph + attr_accessor :pairs, :subgraphs + + class Subgraph + attr_accessor :name, :label, :functions + + def initialize(name, label) + @name = name + @label = label + @functions = [] + end + + def emit + puts "subgraph cluster_#{name} {" + puts "label = \"#{label}\"" + functions.each { |f| puts f unless f == 'DEF_WEAK' } + puts '}' + end + end + + class Pair + attr_accessor :to, :from + + def initialize(from, to) + @from = from + @to = to + end + + def emit + puts "#{from} -> #{to}" if to =~ /auth|login|^_/ + end + end + + def initialize + @pairs = [] + @subgraphs = [] + end + + def emit + puts 'digraph G {' + @subgraphs.each(&:emit) + @pairs.uniq { |p| [p.to, p.from] }.each(&:emit) + puts '}' + end + + def parse_files(filenames) + filenames.each do |filename| + contents = File.read(filename) + basename = File.basename filename + subgraph = Subgraph.new(basename.gsub(/\..*/, ''), basename) + functions = contents.scan(FUNCTION_REGEX) + oneliners = contents.scan(ONELINE_FUNCTION_REFGEX) + functions.concat(oneliners) unless oneliners.empty? + functions.each do |function| + function_name = function[0] + function_body = function[1] + puts 'auth_open!' if function_name == 'auth_open' + subgraph.functions << function_name + function_body.scan(CALL_REGEX) do |call| + @pairs << Pair.new(function_name, call[0]) + end + end + @subgraphs << subgraph + end + end +end + +fg = FunctionDigraph.new + +files = FILENAMES.map { |f| File.join(SOURCE_DIR, f) } +fg.parse_files files + +fg.emit |