Openwrt下C呼叫UCI API
“uci”是”Unified Configuration Interface”(統一配置介面)的縮寫,意在OpenWrt整個系統的配置集中化。
許多程式在系統某處擁有自己的配置檔案,比如/etc/network/interfaces, /etc/exports, /etc/dnsmasq.conf或者 /etc/samba/samba.conf,有時它們還使用稍有不同的語法。
共同原則
OpenWrt的所有配置檔案皆位於/etc/config/目錄下。每個檔案大致與它所配置的那部分系統相關。可用文字編輯器、”uci” 命令列實用程式或各種程式設計API(比如 Shell, Lua and C)來編輯/修改這些配置檔案。
配置檔案
| 檔案位置 | 描述 |
| 基本配置 |
|/etc/config/dhcp | dnsmasq和DHCP的配置
|/etc/config/dropbear | SSH服務端選項
|/etc/config/firewall | 中央防火牆配置
|/etc/config/network | 交換,介面和路由配置
|/etc/config/system | 雜項與系統配置
|/etc/config/timeserver | rdate的時間伺服器列表
|/etc/config/wireless | 無線設定和無線網路的定義
IPv6
|/etc/config/ahcpd | Ad-Hoc配置協議(AHCP) 服務端配置以及轉發器配置
|/etc/config/aiccu | AICCU 客戶端配置
|/etc/config/dhcp6c | WIDE-DHCPv6 客戶端配置
|/etc/config/dhcp6s | WIDE-DHCPv6 服務端配置
|/etc/config/gw6c | GW6c 客戶端配置
|/etc/config/radvd | 路由通告 (radvd) 配置
其他
|/etc/config/etherwake | 乙太網喚醒: etherwake
|/etc/config/fstab | 掛載點及swap
|/etc/config/hd-idle | 另一個可選的硬碟空閒休眠程序(需要路由器支援usb硬碟)
|/etc/config/httpd | 網頁伺服器配置選項(Busybox 自帶httpd, 已被捨棄)
|/etc/config/luci | 基礎 LuCI 配置
|/etc/config/luci_statistics | 包統計配置
|/etc/config/mini_snmpd | mini_snmpd 配置
|/etc/config/mountd | OpenWrt 自動掛載程序(類似autofs)
|/etc/config/multiwan | 簡單多WAN出口配置
|/etc/config/ntpclient | ntp客戶端配置,用以獲取正確時間
|/etc/config/pure-ftpd | Pure-FTPd 服務端配置
|/etc/config/qos | QoS配置(流量限制與整形)
|/etc/config/samba | samba配置(Microsoft檔案共享)
|/etc/config/snmpd | SNMPd(snmp服務程序) 配置
|/etc/config/sshtunnel | sshtunnel配置
|/etc/config/stund | STUN 服務端配置
|/etc/config/transmission | BitTorrent配置
|/etc/config/uhttpd | Web伺服器配置(uHTTPd)
|/etc/config/upnpd | miniupnpd UPnP伺服器配置
|/etc/config/ushare | uShare UPnP 伺服器配置
|/etc/config/vblade | vblade 使用者空間AOE(ATA over Ethernet)配置
|/etc/config/vnstat | vnstat 下載器配置
|/etc/config/wifitoogle | 使用按鈕來開關WiFi的指令碼
|/etc/config/wol | Wake-on-Lan: wol
|/etc/config/znc | ZNC 配置
檔案語法
在UCI的配置檔案通常包含一個或多個配置語句,包含一個或多個用來定義實際值的選項語句的所謂的節。
下面是一個簡單的配置示例檔案:
package 'example'
config 'example' 'test'
option 'string' 'some value'
option 'boolean' '1'
list 'collection' 'first item'
list 'collection' 'second item'
config ‘example’ ‘test’ 語句標誌著一個節的開始。這裡的配置型別是example,配置名是test。配置中也允許出現匿名節,即自定義了配置型別,而沒有配置名的節。配置型別對應配置處理程式來說是十分重要的,因為配置程式需要根據這些資訊來處理這些配置項。
option ‘string’ ‘some value’ 和 option ‘boolean’ ‘1’ 定義了一些簡單值。文字選項和布林選項在語法上並沒有差異。布林選項中可以用’0’ ,’no’, ‘off’, 或者’false’來表示false值,或者也可以用’1’, ‘yes’,’on’或者’true’來表示真值。
以list關鍵字開頭的多個行,可用於定義包含多個值的選項。所有共享一個名稱的list語句,會組裝形成一個值列表,列表中每個值出現的順序,和它在配置檔案中的順序相同。如上例種中,列表的名稱是’collection’,它包含了兩個值,即’first item’和’second item’。
‘option’和’list’語句的縮排可以增加配置檔案的可讀性,但是在語法不是必須的。
通常不需要為識別符號和值加引號,只有當值包括空格或者製表符的時候,才必須加引號。同時,在使用引號的時候,可以用雙引號代替單引號。
UCI的幾個結構體
1.struct uci_package: 包結構體。它對應一個配置檔案內容
struct uci_package
{
struct uci_element e;
struct uci_list sections;
struct uci_context *ctx;
bool has_delta;
char *path;
/* private: */
struct uci_backend *backend;
void *priv;
int n_section;
struct uci_list delta;
struct uci_list saved_delta;
};
2.struct uci_section:節結構體,它對應配置檔案中的節
struct uci_section
{
struct uci_element e;
struct uci_list options;
struct uci_package *package;
bool anonymous;
char *type;
};
3.struct uci_option:選項結構體,它對應配置檔案裡節中的option或者list
struct uci_option
{
struct uci_element e;
struct uci_section *section;
enum uci_option_type type;
union {
struct uci_list list;
char *string;
} v;
};
4.struct uci_ptr:元素位置指標結構,用來查詢並儲存對應位置元素
struct uci_ptr
{
enum uci_type target;
enum {
UCI_LOOKUP_DONE = (1 << 0),
UCI_LOOKUP_COMPLETE = (1 << 1),
UCI_LOOKUP_EXTENDED = (1 << 2),
} flags;
struct uci_package *p;
struct uci_section *s;
struct uci_option *o;
struct uci_element *last;
const char *package;
const char *section;
const char *option;
const char *value;
};
5.struct uci_context: uci上下文結構,貫穿查詢、更改配置檔案全過程。
struct uci_context
{
/* 配置檔案包列表 */
struct uci_list root;
/* 解析上下文,只用於錯誤處理 */
struct uci_parse_context *pctx;
/* 後端匯入匯出 */
struct uci_backend *backend;
struct uci_list backends;
/* uci 執行標識 */
enum uci_flags flags;
char *confdir;
char *savedir;
/* search path for delta files */
struct uci_list delta_path;
/* 私有資料 */
int err;
const char *func;
jmp_buf trap;
bool internal, nested;
char *buf;
int bufsz;
};
幾個基本的API函式
1.uci_alloc_context:動態申請一個uci上下文結構
struct uci_context *uci_alloc_context(void);
2.uci_free_contex:釋放由uci_alloc_context申請的uci上下文結構且包括它的所有資料
void uci_free_context(struct uci_context *ctx);
3.uci_lookup_ptr:由給定的元組查詢元素
/**
* uci_lookup_ptr: 分離一個uci元組字串且查詢對應元素樹
* @ctx: uci context結構體指標
* @ptr: 存放元素查詢結果的結構體指標
* @str: 待查詢的uci元組字串
* @extended: 允許擴充套件語法查詢
*
*如果extended被設為ture,則uci_lookup_ptr支援下列擴充套件語法:
*
*例子:
* network.@interface[0].ifname (‘ifname‘ option of the first interface section)
* network.@interface[-1] (last interface section)
* Note: 有必要的話uci_lookup_ptr將會自動載入配置檔案包
* @str 不能是一個const型別指標,它在使用的過程中將會被更改且用於將字串填寫到@ptr中,因此
* 它只要@ptr還在使用,它就必須是可用的
*
* 這個函式在指定包元組的的字串未被找到時返回UCI_ERR_NOTFOUND,否則返回UCI_OK
*
* 記住在查詢其他部分失敗的情況,如果它們同樣被指定,包括section和option,同樣會返回UCI_OK,
* 但是ptr->flags * UCI_LOOKUP_COMPLETE標誌位不會被置位
*/
int uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *str, bool extended);
現在我們來看一個示例來進一步瞭解:
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <uci.h>
#define UCI_CONFIG_FILE "/etc/config/meter"
static struct uci_context * ctx = NULL; //定義一個UCI上下文的靜態變數.
/*********************************************
* 載入配置檔案,並遍歷Section.
*/
bool load_config()
{
struct uci_package * pkg = NULL;
struct uci_element *e;
char *tmp;
const char *value;
ctx = uci_alloc_context(); // 申請一個UCI上下文.
if (UCI_OK != uci_load(ctx, UCI_CONFIG_FILE, &pkg))
goto cleanup; //如果開啟UCI檔案失敗,則跳到末尾 清理 UCI 上下文.
/*遍歷UCI的每一個節*/
uci_foreach_element(&pkg->sections, e)
{
struct uci_section *s = uci_to_section(e);
printf("section s's type is %s.\n",s->type);
if(!strcmp)
if(!strcmp("meter",s->type)) //this section is a meter
{
printf("this seciton is a meter.\n");
if (NULL != (value = uci_lookup_option_string(ctx, s, "modbus_id")))
{
tmp = strdup(value); //如果您想持有該變數值,一定要拷貝一份。當 pkg銷燬後value的記憶體會被釋放。
printf("%s's modbus_id is %s.\n",s->e.name,value);
}
if (NULL != (value = uci_lookup_option_string(ctx, s, "num_attr")))
{
tmp = strdup(value); //如果您想持有該變數值,一定要拷貝一份。當 pkg銷燬後value的記憶體會被釋放。
printf("%s's num_attr is %s.\n",s->e.name,value);
}
if (NULL != (value = uci_lookup_option_string(ctx, s, "sender_id")))
{
tmp = strdup(value); //如果您想持有該變數值,一定要拷貝一份。當 pkg銷燬後value的記憶體會被釋放。
printf("%s's sender_id is %s.\n",s->e.name,value);
}
if (NULL != (value = uci_lookup_option_string(ctx, s, "customer_id")))
{
tmp = strdup(value); //如果您想持有該變數值,一定要拷貝一份。當 pkg銷燬後value的記憶體會被釋放。
printf("%s's customer_id is %s.\n",s->e.name,value);
}
if (NULL != (value = uci_lookup_option_string(ctx, s, "customer_name")))
{
tmp = strdup(value); //如果您想持有該變數值,一定要拷貝一份。當 pkg銷燬後value的記憶體會被釋放。
printf("%s's customer_name is %s.\n",s->e.name,value);
}
if (NULL != (value = uci_lookup_option_string(ctx, s, "account_id")))
{
tmp = strdup(value); //如果您想持有該變數值,一定要拷貝一份。當 pkg銷燬後value的記憶體會被釋放。
printf("%s's account_id is %s.\n",s->e.name,value);
}
if (NULL != (value = uci_lookup_option_string(ctx, s, "account_name")))
{
tmp = strdup(value); //如果您想持有該變數值,一定要拷貝一份。當 pkg銷燬後value的記憶體會被釋放。
printf("%s's account_name is %s.\n",s->e.name,value);
}
if (NULL != (value = uci_lookup_option_string(ctx, s, "meter_id")))
{
tmp = strdup(value); //如果您想持有該變數值,一定要拷貝一份。當 pkg銷燬後value的記憶體會被釋放。
printf("%s's meter_id is %s.\n",s->e.name,value);
}
if (NULL != (value = uci_lookup_option_string(ctx, s, "commodity")))
{
tmp = strdup(value); //如果您想持有該變數值,一定要拷貝一份。當 pkg銷燬後value的記憶體會被釋放。
printf("%s's commodity is %s.\n",s->e.name,value);
}
}
// 如果您不確定是 string型別 可以先使用 uci_lookup_option() 函式得到Option 然後再判斷.
// Option 的型別有 UCI_TYPE_STRING 和 UCI_TYPE_LIST 兩種.
}
uci_unload(ctx, pkg); // 釋放 pkg
cleanup:
uci_free_context(ctx);
ctx = NULL;
}
int main(int argc, char* argv[])
{
load_config();
}
遍歷一個UCI_TYPE_LIST 型別
config "server" "webserver"
list "index" "index.html"
list "index" "index.php"
list "index" "default.html"
程式碼段:
// s 為 section.
struct uci_option * o = uci_lookup_option(ctx, s, "index");
if ((NULL != o) && (UCI_TYPE_LIST == o->type)) //o存在 且 型別是 UCI_TYPE_LIST則可以繼續.
{
struct uci_element *e;
uci_foreach_element(&o->v.list, e)
{
//這裡會迴圈遍歷 list
// e->name 的值依次是 index.html, index.php, default.html
}
}
寫配置
UCI提供了一個簡潔的辦法來操作配置資訊,例如有一個配置檔案
#檔名: testconfig
config 'servver'
option 'value' '123' # 我們想修改 'value' 的值為 '456'
程式碼如下:
struct uci_context * ctx = uci_alloc_context(); //申請上下文
struct uci_ptr ptr ={
.package = "config",
.section = "servver",
.option = "value",
.value = "256",
};
uci_set(_ctx,&ptr); //寫入配置
uci_commit(_ctx, &ptr.p, false); //提交儲存更改
uci_unload(_ctx,ptr.p); //解除安裝包
uci_free_context(ctx); //釋放上下文
相關推薦
Openwrt下C呼叫UCI API
“uci”是”Unified Configuration Interface”(統一配置介面)的縮寫,意在OpenWrt整個系統的配置集中化。 許多程式在系統某處擁有自己的配置檔案,比如/etc/network/interfaces, /etc/expor
用Visual C#呼叫Windows API函式
用Visual C#呼叫Windows API函式 Api函式是構築Windws應用程式的基石,每一種Windows應用程式開發工具,它提供的底層函式都間接或直接地呼叫了Windows API函式,同時為了實現功能擴充套
Windows下C++呼叫系統軟鍵盤及其需要注意的點
Windows下系統軟鍵盤的程式名是osk.exe,系統軟鍵盤在有鍵盤的時候一點用都沒有,但是沒有鍵盤的時候想要輸入點東西,系統軟鍵盤就至關重要了。 osk.exe為微軟系統自帶的虛擬鍵盤程式,功能與真的鍵盤差不多.只需要在執行中輸入"osk"即可啟動虛擬鍵盤。 W
Linux下C++呼叫Java簡單例項(jni)
假設工作目錄為/home1. Java端1) mkdir leixf && cd leixf2) 建立SubClass.java檔案,內容如下:package leixf;public class SubClass {private String name
win64下C++呼叫python指令碼
#include <iostream> #include <Python.h> using namespace std; int main() { // D:\Python27\include\pyconfig.h // 修改 https://blog.csdn.n
C#呼叫RESTful API
現在很多的網路服務都用RESTful API來實現。比如百度的搜尋推廣API介紹使用Rest原因:REST+JSON風格的API相比SOAP+XML,好處是:呼叫更加靈活,也更容易擴充套件;JSON格式傳輸資訊比XML減少約30%的資料量,效率更高。因此建議開發
debian系列下c++呼叫mysql, linux下面安裝mysql.h檔案
1.介紹需求: python呼叫資料庫,並做邏輯處理,時間為92.5s,從執行sql到得到資料150w條為22s,邏輯處理(2個for迴圈)為60s。前端處理30s,pending為2min左右,需要處理這個問題 於是思考解決方案: 1. 取資料時資料拆分
用C#呼叫Windows API和其它程序通訊及C# 獲得另外一程式 控制代碼 後控制該程式 控制其透明 窗體大小
作者:邊城浪子◎2005-01-16 關鍵字: C#,API,FindWindow,FindWindowEx,SendMessage,程序,登錄檔 設計初衷:公司為了便於網路管理,使用了IEEE 802.1X的網路訪問控制,這樣每次開機需要輸入兩次登入密碼,於是我就研究了
VS2015下C++呼叫Python指令碼
C++呼叫Python在一些特殊的場景下有一定的價值。比如,要呼叫一個REST服務,c++本身做HTTP Client會很煩,如果使用Python指令碼去呼叫服務,返回結果給c++端就可以繞開這個問題。因為最近在一個原型開發中遇到了這個問題,所以為了快速拿出東西來,我決定使
linux下系統呼叫、API、系統命令,核心函式的區別與聯絡
1.系統呼叫: 應用程式和核心間的橋樑,是應用程式訪問核心的入口點;但通常情況下,應用程式通過作業系統提供的API進行程式設計而不是使用系統呼叫直接程式設計; linux的全部系統呼叫加起來大約只有250個左右。 2.API: API常以c庫(libc)的形式提供,
Linux下c++呼叫自己編寫的matlab函式:通過mcc動態連結庫.so實現
之前在這裡和這裡呼叫了matlab自帶的一些函式,是通過matlab引擎來實現的。那裡呼叫的是matlab自帶的函式,那麼如果想呼叫自己寫的.m函式該怎麼辦呢?其實很簡單,原理類似,方法也不止一種。這篇筆記我先嚐試通過mcc將.m函式編譯成動態連結庫供c++呼叫的方式。在另
C#呼叫Windows API(示例:顯示工作管理員裡的程式名稱)
作為初學者來說,在C#中使用API確是一件令人頭疼的問題。 在使用API之前你必須知道如何在C#中使用結構、型別轉換、安全/不安全程式碼,可控/不可控程式碼等許多知識。 在.Net Framework SDK文件中,關於呼叫Windows API的指示比較零散,並且其中稍全面一點的是針對Visual Basi
C程式碼呼叫uci的API讀openwrt配置檔案指南
實戰背景 倘若我們自己寫了一個應用程式,也想用uci來集中化管理配置該應用的配置檔案,怎麼辦呢? 看了arvik的上一篇部落格後相信新手能很快的使用uci對某個配置檔案進行配置,只是如何讓我們的應用程式讀取配置檔案內容呢,本篇arvik將解答這個問題。 簡單
OpenWRT UCI API的使用——C語言
UCI 是OpenWRT為實現配置集中化而引入的一個軟體包, 通過修改UCI,可以實現對OpenWRT的絕對部分配置的修改.LUCI(OpenWRT 的WEB配置介面)也是通過讀UCI配置檔案的操作來實現使用者對路由的配置的。通過掌握UCI的API的使用,可以方便地將您的軟
centos下C程式設計呼叫libvirt的API訪問KVM虛擬機器
一、簡介 libvirt是一套免費、開源的支援Linux下主流虛擬化工具的C函式庫,其旨在為包括Xen在內的各種虛擬化工具提供一套方便、可靠的程式設計介面,支援與C,C++,Ruby,Python等多種主流開發語言的繫結。當前主流Linux平臺上預設的虛擬
windows 下 c++ 如何呼叫 python 3
本文所使用環境: win10 (x64) + VS2013 + python 3.5.2 (x64) python官網下載地址 一、先配置環境 1.安裝python 2.把 python 新增到VS2013 (1) VS新建一個空的Win3
Linux下C程式動態庫的生成和呼叫
Linux下C程式動態庫的生成和呼叫 文章目錄 Linux下C程式動態庫的生成和呼叫 1 動態庫的打包和呼叫 2 靜態庫打包和呼叫 3 常用命令 4 gcc 和 g++ 區別 5 編譯和連結的理解
windows 下C++動態庫的封裝以及呼叫
1、一個程式從原始檔編譯生成可執行檔案的步驟:預編譯 --> 編譯 --> 彙編 --> 連結(1)預編譯,即預處理,主要處理在原始碼檔案中以“#”開始的預編譯指令,如巨集展開、處理條件編譯指令、處理#include指令等。(2)編譯過程就是把預處理完的檔案進行一系列
c++ 呼叫Python指令碼或者動態庫——環境Ubuntu 16.04下用codeblocks
背景:因為使用的是python版本的程式,最終要整合到C++環境的架構中,也就是說架構是c++的,交付使用者為c++的介面,但是呼叫的是python的庫,因此需要學習在c++環境下呼叫python。因為對python不熟悉,可以說有點一抹黑,因此從簡到難逐步探索。首先在c++
C#呼叫百度api,根據經度和緯度獲取地理位置資訊
/// <summary> /// 百度api 根據經緯度獲取地理位置 /// </summary> /// <param name="lng">經度</param&g