Update configs
[kernel-configs.git] / update-config.py
1 #!/usr/bin/env python
2 #
3 # update-config.py: A program to help automate updating the
4 # kernel configuration.
5 #
6 # Copyright (C) 2018 Jason Self <j@jxself.org>
7 #
8 # You will need Python and pexpect.
9 #
10 # A file named base_config containing config options (without the
11 # leading CONFIG_) needs to live in the root level of the kernel
12 # source tree. This program will run make oldconfig, responding to
13 # prompts for config options using the information in that
14 # base_config file. If no match is found it will pause so that you
15 # can answer, unless USE_DEFAULT is to true. In that case the program
16 # will accept whatever the default answer is and continue on.
17 #
18 # SPDX-License-Identifier: AGPL-3.0-or-later
19 #
20 # This program is free software: you can redistribute it and/or
21 # modify it under the terms of the GNU Affero General Public License
22 # as published by the Free Software Foundation, either version 3 of
23 # the License, or (at your option) any later version.
24 #
25 # This program is distributed in the hope that it will be useful, but
26 # WITHOUT ANY WARRANTY; without even the implied warranty of
27 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 # Affero General Public License for more details.
29 #
30 # You should have received a copy of the GNU Affero General Public
31 # License along with this program. If not, see
32 # <https://www.gnu.org/licenses/>.
33
34 import subprocess
35 import sys
36 import pexpect
37 import select
38
39 TIMEOUT = 1
40 USE_DEFAULT = False
41 TRACE = False
42 CHOICE_PROMPT = False
43
44 configs = {}
45
46 def readBaseConfig(baseConfigFile):
47     f = open(baseConfigFile)
48     for l in f.readlines():
49         if len(l) < 3 or l.strip()[0] == '#':
50             continue
51         if l.find('=') != -1:
52             optVal = l.split('=')
53             key = '(' + optVal[0].strip().replace('CONFIG_', '') + ')'
54             val = optVal[1].strip().replace('"', '')
55             configs[key] = val
56
57 def mainSelect():
58     cmd = 'make oldconfig'
59     proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
60     fLog = open('kernelexpect.log', 'w+')
61     print("Starting")
62     validConfig = False
63     b = ''
64     l = ''
65     timeLimit = TIMEOUT
66     while True:
67         pollResult = select.select([proc.stdout], [], [], timeLimit)[0]
68         if len(pollResult) != 0:
69             c = proc.stdout.read(1)
70             if c == '':
71                 break
72             b += c
73             l += c
74             if c == '\r' or c == '\n':
75                 l = ''
76             sys.stdout.write(c)
77             sys.stdout.flush()
78             fLog.write(c)
79             fLog.flush()
80         else:
81             print '\n**** Timeout ***'
82             if not validConfig:
83                 if b.find('Restart config') != -1:
84                     validConfig = True
85                 else:
86                     print 'Waiting for valid config'
87                     continue
88
89             found = False
90             l = l.strip()
91             for k in configs:
92                 if l.find(k + ' [') != -1:
93                     print 'Found key', k, 'in line', 'setting value', configs[k]
94                     proc.stdin.write(configs[k] + '\n')
95                     found = True
96
97             if l.startswith('choice'):
98                 if CHOICE_PROMPT:
99                     print 'Please enter your option'
100                     v = sys.stdin.readline()
101                     print 'Setting value', v
102                     proc.stdin.write(v)
103                     found = True
104                 else:
105                     options = int(l.replace('choice[1-', '').replace('?', '').replace(']', '').replace(':', ''))
106                     print 'Options', options
107                     ls = b.split('\n')[-options-1:-1]
108                     l1 = ls[0]
109                     print 'List', ls
110                     print 'First', l1
111                     for lc in ls:
112                         for k in configs:
113                             if configs[k] != 'y':
114                                 continue
115                             if lc.find(k) != -1:
116                                 print 'Found key', k, 'in line', 'setting value', configs[k]
117                                 lc = lc.replace('>', '').strip()
118                                 pos = lc.find('.')
119                                 option = lc[:pos]
120                                 print 'Using option', option
121                                 proc.stdin.write(option + '\n')
122                                 found = True
123
124             if not found:
125                 if not USE_DEFAULT:
126                     print 'Please enter your option'
127                     v = sys.stdin.readline()
128                     print 'Setting value', v
129                     proc.stdin.write(v)
130                     found = True
131                 else:
132                     print 'Using default'
133                     proc.stdin.write('\n')
134
135             print '****************'
136             b = ''
137             l = ''
138
139 readBaseConfig('base_config')
140
141 if TRACE:
142     for k in configs.keys():
143         print k, configs[k]
144
145 mainSelect()