summaryrefslogtreecommitdiffstats
path: root/content/posts/WIP-how-bsd-authentication-works/gen_dot.rb
diff options
context:
space:
mode:
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.rb82
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