Publish update-config.py
[kernel-configs.git] / update-config.py
diff --git a/update-config.py b/update-config.py
new file mode 100755 (executable)
index 0000000..fb1adca
--- /dev/null
@@ -0,0 +1,145 @@
+#!/usr/bin/env python
+#
+# update-config.py: A program to help automate updating the
+# kernel configuration.
+#
+# Copyright (C) 2018 Jason Self <j@jxself.org>
+#
+# You will need Python and pexpect.
+#
+# A file named base_config containing config options (without the
+# leading CONFIG_) needs to live in the root level of the kernel
+# source tree. This program will run make oldconfig, responding to
+# prompts for config options using the information in that
+# base_config file. If no match is found it will pause so that you
+# can answer, unless USE_DEFAULT is to true. In that case the program
+# will accept whatever the default answer is and continue on.
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+#
+# This program is free software: you can redistribute it and/or
+# modify it under the terms of the GNU Affero General Public License
+# as published by the Free Software Foundation, either version 3 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public
+# License along with this program. If not, see
+# <https://www.gnu.org/licenses/>.
+
+import subprocess
+import sys
+import pexpect
+import select
+
+TIMEOUT = 1
+USE_DEFAULT = False
+TRACE = False
+CHOICE_PROMPT = False
+
+configs = {}
+
+def readBaseConfig(baseConfigFile):
+    f = open(baseConfigFile)
+    for l in f.readlines():
+        if len(l) < 3 or l.strip()[0] == '#':
+            continue
+        if l.find('=') != -1:
+            optVal = l.split('=')
+            key = '(' + optVal[0].strip().replace('CONFIG_', '') + ')'
+            val = optVal[1].strip().replace('"', '')
+            configs[key] = val
+
+def mainSelect():
+    cmd = 'make oldconfig'
+    proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
+    fLog = open('kernelexpect.log', 'w+')
+    print("Starting")
+    validConfig = False
+    b = ''
+    l = ''
+    timeLimit = TIMEOUT
+    while True:
+        pollResult = select.select([proc.stdout], [], [], timeLimit)[0]
+        if len(pollResult) != 0:
+            c = proc.stdout.read(1)
+            if c == '':
+                break
+            b += c
+            l += c
+            if c == '\r' or c == '\n':
+                l = ''
+            sys.stdout.write(c)
+            sys.stdout.flush()
+            fLog.write(c)
+            fLog.flush()
+        else:
+            print '\n**** Timeout ***'
+            if not validConfig:
+                if b.find('Restart config') != -1:
+                    validConfig = True
+                else:
+                    print 'Waiting for valid config'
+                    continue
+
+            found = False
+            l = l.strip()
+            for k in configs:
+                if l.find(k + ' [') != -1:
+                    print 'Found key', k, 'in line', 'setting value', configs[k]
+                    proc.stdin.write(configs[k] + '\n')
+                    found = True
+
+            if l.startswith('choice'):
+                if CHOICE_PROMPT:
+                    print 'Please enter your option'
+                    v = sys.stdin.readline()
+                    print 'Setting value', v
+                    proc.stdin.write(v)
+                    found = True
+                else:
+                    options = int(l.replace('choice[1-', '').replace('?', '').replace(']', '').replace(':', ''))
+                    print 'Options', options
+                    ls = b.split('\n')[-options-1:-1]
+                    l1 = ls[0]
+                    print 'List', ls
+                    print 'First', l1
+                    for lc in ls:
+                        for k in configs:
+                            if configs[k] != 'y':
+                                continue
+                            if lc.find(k) != -1:
+                                print 'Found key', k, 'in line', 'setting value', configs[k]
+                                lc = lc.replace('>', '').strip()
+                                pos = lc.find('.')
+                                option = lc[:pos]
+                                print 'Using option', option
+                                proc.stdin.write(option + '\n')
+                                found = True
+
+            if not found:
+                if not USE_DEFAULT:
+                    print 'Please enter your option'
+                    v = sys.stdin.readline()
+                    print 'Setting value', v
+                    proc.stdin.write(v)
+                    found = True
+                else:
+                    print 'Using default'
+                    proc.stdin.write('\n')
+
+            print '****************'
+            b = ''
+            l = ''
+
+readBaseConfig('base_config')
+
+if TRACE:
+    for k in configs.keys():
+        print k, configs[k]
+
+mainSelect()