getvar() {
	eval "echo \"\${$1}\""
}

var2file() {
	local var
	eval "var=\"\${$1}\""
	if [ -n "$var" ]; then echo "$var" > "$2"; fi
}

isset() {
	local var
	eval "var=\"\${$1}\""
	[ -n "$var" ]
}

trapret() {(
	local retvals="$1"; shift
	local cmd="$1"; shift
	for retval in $(echo $retvals); do
		local trap_$retval=1
	done
	"$cmd" "$@" || {
		local retval="$?"
		eval "trapped=\${trap_$retval}"
		[ -n "$trapped" ] || {
			return $retval
		}
	}
)}

md5s() {
	cat "$@" | (
		md5sum 2>/dev/null ||
		md5 
	) | awk '{print $1}'
}
it'><table id='header'>
<tr>
<td class='logo' rowspan='2'><a href='/cgit.cgi/'><img src='/cgit.png' alt='cgit logo'/></a></td>
<td class='main'><a href='/cgit.cgi/'>index</a> : <a title='openwrt/upstream' href='/cgit.cgi/openwrt/upstream/'>openwrt/upstream</a></td><td class='form'><form method='get'>
<input type='hidden' name='id' value='861bf6af49e9347f4c5b03cdb369bc1827f45856'/><select name='h' onchange='this.form.submit();'>
<option value='attitude_adjustment'>attitude_adjustment</option>
<option value='barrier_breaker'>barrier_breaker</option>
<option value='chaos_calmer'>chaos_calmer</option>
<option value='lede-17.01'>lede-17.01</option>
<option value='less-old-master'>less-old-master</option>
<option value='master'>master</option>
<option value='old-master'>old-master</option>
<option value='openwrt-18.06'>openwrt-18.06</option>
<option value='openwrt-19.07'>openwrt-19.07</option>
<option value='upstream'>upstream</option>
</select> <input type='submit' value='switch'/></form></td></tr>
<tr><td class='sub'>upstream openwrt</td><td class='sub right'>James</td></tr></table>
<table class='tabs'><tr><td>
<a href='/cgit.cgi/openwrt/upstream/about/?h=v18.06.7'>about</a><a href='/cgit.cgi/openwrt/upstream/?h=v18.06.7'>summary</a><a href='/cgit.cgi/openwrt/upstream/refs/?h=v18.06.7&amp;id=861bf6af49e9347f4c5b03cdb369bc1827f45856'>refs</a><a href='/cgit.cgi/openwrt/upstream/log/docs/config.tex?h=v18.06.7'>log</a><a class='active' href='/cgit.cgi/openwrt/upstream/tree/docs/config.tex?h=v18.06.7&amp;id=861bf6af49e9347f4c5b03cdb369bc1827f45856'>tree</a><a href='/cgit.cgi/openwrt/upstream/commit/docs/config.tex?h=v18.06.7&amp;id=861bf6af49e9347f4c5b03cdb369bc1827f45856'>commit</a><a href='/cgit.cgi/openwrt/upstream/diff/docs/config.tex?h=v18.06.7&amp;id=861bf6af49e9347f4c5b03cdb369bc1827f45856'>diff</a><a href='/cgit.cgi/openwrt/upstream/stats/docs/config.tex?h=v18.06.7'>stats</a></td><td class='form'><form class='right' method='get' action='/cgit.cgi/openwrt/upstream/log/docs/config.tex'>
<input type='hidden' name='h' value='v18.06.7'/><input type='hidden' name='id' value='861bf6af49e9347f4c5b03cdb369bc1827f45856'/><select name='qt'>
<option value='grep'>log msg</option>
<option value='author'>author</option>
<option value='committer'>committer</option>
<option value='range'>range</option>
</select>
<input class='txt' type='search' size='10' name='q' value=''/>
<input type='submit' value='search'/>
</form>
</td></tr></table>
<div class='path'>path: <a href='/cgit.cgi/openwrt/upstream/tree/?h=v18.06.7&amp;id=861bf6af49e9347f4c5b03cdb369bc1827f45856'>root</a>/<a href='/cgit.cgi/openwrt/upstream/tree/docs?h=v18.06.7&amp;id=861bf6af49e9347f4c5b03cdb369bc1827f45856'>docs</a>/<a href='/cgit.cgi/openwrt/upstream/tree/docs/config.tex?h=v18.06.7&amp;id=861bf6af49e9347f4c5b03cdb369bc1827f45856'>config.tex</a></div><div class='content'>blob: 08318b4b6cfb2468354a6e8f592bef9c1287137b (<a href='/cgit.cgi/openwrt/upstream/plain/docs/config.tex?h=v18.06.7&amp;id=861bf6af49e9347f4c5b03cdb369bc1827f45856'>plain</a>)
<table summary='blob content' class='blob'>
<tr><td class='linenumbers'><pre><a id='n1' href='#n1'>1</a>
<a id='n2' href='#n2'>2</a>
<a id='n3' href='#n3'>3</a>
<a id='n4' href='#n4'>4</a>
<a id='n5' href='#n5'>5</a>
<a id='n6' href='#n6'>6</a>
<a id='n7' href='#n7'>7</a>
<a id='n8' href='#n8'>8</a>
<a id='n9' href='#n9'>9</a>
<a id='n10' href='#n10'>10</a>
<a id='n11' href='#n11'>11</a>
<a id='n12' href='#n12'>12</a>
<a id='n13' href='#n13'>13</a>
<a id='n14' href='#n14'>14</a>
<a id='n15' href='#n15'>15</a>
<a id='n16' href='#n16'>16</a>
<a id='n17' href='#n17'>17</a>
<a id='n18' href='#n18'>18</a>
<a id='n19' href='#n19'>19</a>
<a id='n20' href='#n20'>20</a>
<a id='n21' href='#n21'>21</a>
<a id='n22' href='#n22'>22</a>
<a id='n23' href='#n23'>23</a>
<a id='n24' href='#n24'>24</a>
<a id='n25' href='#n25'>25</a>
<a id='n26' href='#n26'>26</a>
<a id='n27' href='#n27'>27</a>
<a id='n28' href='#n28'>28</a>
<a id='n29' href='#n29'>29</a>
<a id='n30' href='#n30'>30</a>
<a id='n31' href='#n31'>31</a>
<a id='n32' href='#n32'>32</a>
<a id='n33' href='#n33'>33</a>
<a id='n34' href='#n34'>34</a>
<a id='n35' href='#n35'>35</a>
<a id='n36' href='#n36'>36</a>
<a id='n37' href='#n37'>37</a>
<a id='n38' href='#n38'>38</a>
<a id='n39' href='#n39'>39</a>
<a id='n40' href='#n40'>40</a>
<a id='n41' href='#n41'>41</a>
<a id='n42' href='#n42'>42</a>
<a id='n43' href='#n43'>43</a>
<a id='n44' href='#n44'>44</a>
<a id='n45' href='#n45'>45</a>
<a id='n46' href='#n46'>46</a>
<a id='n47' href='#n47'>47</a>
<a id='n48' href='#n48'>48</a>
<a id='n49' href='#n49'>49</a>
<a id='n50' href='#n50'>50</a>
<a id='n51' href='#n51'>51</a>
<a id='n52' href='#n52'>52</a>
<a id='n53' href='#n53'>53</a>
<a id='n54' href='#n54'>54</a>
<a id='n55' href='#n55'>55</a>
<a id='n56' href='#n56'>56</a>
<a id='n57' href='#n57'>57</a>
<a id='n58' href='#n58'>58</a>
<a id='n59' href='#n59'>59</a>
<a id='n60' href='#n60'>60</a>
<a id='n61' href='#n61'>61</a>
<a id='n62' href='#n62'>62</a>
<a id='n63' href='#n63'>63</a>
<a id='n64' href='#n64'>64</a>
<a id='n65' href='#n65'>65</a>
<a id='n66' href='#n66'>66</a>
<a id='n67' href='#n67'>67</a>
<a id='n68' href='#n68'>68</a>
<a id='n69' href='#n69'>69</a>
<a id='n70' href='#n70'>70</a>
<a id='n71' href='#n71'>71</a>
<a id='n72' href='#n72'>72</a>
<a id='n73' href='#n73'>73</a>
<a id='n74' href='#n74'>74</a>
<a id='n75' href='#n75'>75</a>
<a id='n76' href='#n76'>76</a>
<a id='n77' href='#n77'>77</a>
<a id='n78' href='#n78'>78</a>
<a id='n79' href='#n79'>79</a>
<a id='n80' href='#n80'>80</a>
<a id='n81' href='#n81'>81</a>
<a id='n82' href='#n82'>82</a>
<a id='n83' href='#n83'>83</a>
<a id='n84' href='#n84'>84</a>
<a id='n85' href='#n85'>85</a>
<a id='n86' href='#n86'>86</a>
<a id='n87' href='#n87'>87</a>
<a id='n88' href='#n88'>88</a>
<a id='n89' href='#n89'>89</a>
<a id='n90' href='#n90'>90</a>
<a id='n91' href='#n91'>91</a>
<a id='n92' href='#n92'>92</a>
<a id='n93' href='#n93'>93</a>
<a id='n94' href='#n94'>94</a>
<a id='n95' href='#n95'>95</a>
<a id='n96' href='#n96'>96</a>
<a id='n97' href='#n97'>97</a>
<a id='n98' href='#n98'>98</a>
<a id='n99' href='#n99'>99</a>
<a id='n100' href='#n100'>100</a>
<a id='n101' href='#n101'>101</a>
</pre></td>
<td class='lines'><pre><code><style>pre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #ffffff; }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span><span class="k">\subsubsection</span><span class="nb">{</span>Structure of the configuration files<span class="nb">}</span>

The config files are divided into sections and options/values.

Every section has a type, but does not necessarily have a name.
Every option has a name and a value and is assigned to the section
it was written under.

Syntax:

<span class="k">\begin</span><span class="nb">{</span>Verbatim<span class="nb">}</span>
config      &lt;type&gt; [&quot;&lt;name&gt;&quot;]      # Section
    option  &lt;name&gt; &quot;&lt;value&gt;&quot;       # Option
<span class="k">\end</span><span class="nb">{</span>Verbatim<span class="nb">}</span>

Every parameter needs to be a single string and is formatted exactly
like a parameter for a shell function. The same rules for Quoting and
special characters also apply, as it is parsed by the shell.

<span class="k">\subsubsection</span><span class="nb">{</span>Parsing configuration files in custom scripts<span class="nb">}</span>

To be able to load configuration files, you need to include the common
functions with:

<span class="k">\begin</span><span class="nb">{</span>Verbatim<span class="nb">}</span>
. /lib/functions.sh
<span class="k">\end</span><span class="nb">{</span>Verbatim<span class="nb">}</span>

Then you can use <span class="k">\texttt</span><span class="nb">{</span>config<span class="k">\_</span>load <span class="k">\textit</span><span class="nb">{</span>&lt;name&gt;<span class="nb">}}</span> to load config files. The function
first checks for <span class="k">\textit</span><span class="nb">{</span>&lt;name&gt;<span class="nb">}</span> as absolute filename and falls back to loading
it from <span class="k">\texttt</span><span class="nb">{</span>/etc/config<span class="nb">}</span> (which is the most common way of using it).

If you want to use special callbacks for sections and/or options, you
need to define the following shell functions before running <span class="k">\texttt</span><span class="nb">{</span>config<span class="k">\_</span>load<span class="nb">}</span>
(after including <span class="k">\texttt</span><span class="nb">{</span>/lib/functions.sh<span class="nb">}</span>):

<span class="k">\begin</span><span class="nb">{</span>Verbatim<span class="nb">}</span>
config<span class="nb">_</span>cb() <span class="nb">{</span>
    local type=&quot;<span class="s">$</span><span class="m">1</span><span class="nb">&quot;</span>
<span class="nb">    local name</span><span class="o">=</span><span class="nb">&quot;</span><span class="s">$</span>2&quot;
    # commands to be run for every section
<span class="nb">}</span>

option<span class="nb">_</span>cb() <span class="nb">{</span>
    # commands to be run for every option
<span class="nb">}</span>
<span class="k">\end</span><span class="nb">{</span>Verbatim<span class="nb">}</span>

You can also alter <span class="k">\texttt</span><span class="nb">{</span>option<span class="k">\_</span>cb<span class="nb">}</span> from <span class="k">\texttt</span><span class="nb">{</span>config<span class="k">\_</span>cb<span class="nb">}</span> based on the section type.
This allows you to process every single config section based on its type
individually.

<span class="k">\texttt</span><span class="nb">{</span>config<span class="k">\_</span>cb<span class="nb">}</span> is run every time a new section starts (before options are being
processed). You can access the last section through the <span class="k">\texttt</span><span class="nb">{</span>CONFIG<span class="k">\_</span>SECTION<span class="nb">}</span>
variable. Also an extra call to <span class="k">\texttt</span><span class="nb">{</span>config<span class="k">\_</span>cb<span class="nb">}</span> (without a new section) is generated
after <span class="k">\texttt</span><span class="nb">{</span>config<span class="k">\_</span>load<span class="nb">}</span> is done.
That allows you to process sections both before and after all options were
processed.

Another way of iterating on config sections is using the <span class="k">\texttt</span><span class="nb">{</span>config<span class="k">\_</span>foreach<span class="nb">}</span> command.

Syntax:
<span class="k">\begin</span><span class="nb">{</span>Verbatim<span class="nb">}</span>
config<span class="nb">_</span>foreach &lt;function name&gt; [&lt;sectiontype&gt;] [&lt;arguments...&gt;]
<span class="k">\end</span><span class="nb">{</span>Verbatim<span class="nb">}</span>

This command will run the supplied function for every single config section in the currently
loaded config. The section name will be passed to the function as argument 1.
If the section type is added to the command line, the function will only be called for
sections of the given type.


You can access already processed options with the <span class="k">\texttt</span><span class="nb">{</span>config<span class="k">\_</span>get<span class="nb">}</span> command
Syntax:

<span class="k">\begin</span><span class="nb">{</span>Verbatim<span class="nb">}</span>
# print the value of the option
config<span class="nb">_</span>get &lt;section&gt; &lt;option&gt;

# store the value inside the variable
config<span class="nb">_</span>get &lt;variable&gt; &lt;section&gt; &lt;option&gt;
<span class="k">\end</span><span class="nb">{</span>Verbatim<span class="nb">}</span>

In busybox ash the three-option <span class="k">\texttt</span><span class="nb">{</span>config<span class="k">\_</span>get<span class="nb">}</span> is faster, because it does not
result in an extra fork, so it is the preferred way.

Additionally you can also modify or add options to sections by using the
<span class="k">\texttt</span><span class="nb">{</span>config<span class="k">\_</span>set<span class="nb">}</span> command.

Syntax:

<span class="k">\begin</span><span class="nb">{</span>Verbatim<span class="nb">}</span>
config<span class="nb">_</span>set &lt;section&gt; &lt;option&gt; &lt;value&gt;
<span class="k">\end</span><span class="nb">{</span>Verbatim<span class="nb">}</span>

If a config section is unnamed, an automatically generated name will
be assigned internally, e.g. <span class="k">\texttt</span><span class="nb">{</span>cfg1<span class="nb">}</span>, <span class="k">\texttt</span><span class="nb">{</span>cfg2<span class="nb">}</span>, ...

While it is possible, using unnamed sections through these autogenerated names is
strongly discouraged. Use callbacks or <span class="k">\texttt</span><span class="nb">{</span>config<span class="k">\_</span>foreach<span class="nb">}</span> instead.
</pre></div>
</code></pre></td></tr></table>
</div> <!-- class=content -->
<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.3</a> (<a href='https://git-scm.com/'>git 2.25.1</a>) at 2025-01-29 13:40:43 +0000</div>
</div> <!-- id=cgit -->
</body>
</html>
