1. c source code
/****************************************************************************
* File: lib_queue.h
* Descript:
* Author: Wenxy, wen_kernel@163.com
* Fix history:
* 1, Wenxy, 20090317,a.m., unite with something, :-)
*
*****************************************************************************/
#ifndef _LIB_QUEUE_H
#define _LIB_QUEUE_H
/* *********************************************************************
* Macros
********************************************************************* */
#define q_init(q) (q)->q_prev = (q), (q)->q_next = (q)
#define q_isempty(q) ((q)->q_next == (q))
#define q_getfirst(q) ((q)->q_next)
#define q_getlast(q) ((q)->q_prev)
/* *********************************************************************
* Types
********************************************************************* */
typedef struct queue_s {
struct queue_s *q_next;
struct queue_s *q_prev;
} queue_t;
/* *********************************************************************
* Prototypes
********************************************************************* */
void q_enqueue(queue_t *,queue_t *);
void q_dequeue(queue_t *);
queue_t *q_deqnext(queue_t *);
int q_map(queue_t *qb,int (*func)(queue_t *,unsigned int,unsigned int),
unsigned int a,unsigned int b);
int q_count(queue_t *);
int q_find(queue_t *,queue_t *);
#endif
/****************************************************************************
* File: lib_types.h
* Descript:
* Author: Wenxy, wen_kernel@163.com
* Fix history:
* 1, Wenxy, 20090317,a.m., unite with something, :-)
*
*****************************************************************************/
#ifndef _LIB_TYPES_H
#define _LIB_TYPES_H
/* *********************************************************************
* Constants
********************************************************************* */
#ifndef NULL
#define NULL 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/* *********************************************************************
* Basic types
********************************************************************* */
typedef int size_t;
typedef char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
#ifdef __long64
typedef int int32_t;
typedef unsigned int uint32_t;
#else
typedef long int32_t;
typedef unsigned long uint32_t;
#endif
#if 0
typedef long long int64_t;
typedef unsigned long long uint64_t;
#define unsigned signed /* Kludge to get unsigned size-shaped type. */
typedef __SIZE_TYPE__ intptr_t;
#undef unsigned
typedef __SIZE_TYPE__ uintptr_t;
#endif
/* *********************************************************************
* Macros
********************************************************************* */
#ifndef offsetof
#define offsetof(type,memb) ((size_t)&((type *)0)->memb)
#endif
/* *********************************************************************
* Structures
********************************************************************* */
typedef struct cons_s {
char *str;
int num;
} cons_t;
#endif
/****************************************************************************
* File: enve_subr.h
* Descript:
* Author: Wenxy, wen_kernel@163.com
* Fix history:
* 1, Wenxy, 20090317,a.m., unite with something, :-)
*
*****************************************************************************/
/* *********************************************************************
* Constants
********************************************************************* */
/*
* TLV types. These codes are used in the "type-length-value"
* encoding of the items stored in the NVRAM device (flash or EEPROM)
*
* The layout of the flash/nvram is as follows:
*
* <type> <length> <data ...> <type> <length> <data ...> <type_end>
*
* The type code of "ENV_TLV_TYPE_END" marks the end of the list.
* The "length" field marks the length of the data section, not
* including the type and length fields.
*
* Environment variables are stored as follows:
*
* <type_env> <length> <flags> <name> = <value>
*
* If bit 0 (low bit) is set, the length is an 8-bit value.
* If bit 0 (low bit) is clear, the length is a 16-bit value
*
* Bit 7 set indicates "user" TLVs. In this case, bit 0 still
* indicates the size of the length field.
*
* Flags are from the constants below:
*
*/
#define ENV_LENGTH_16BITS 0x00 /* for low bit */
#define ENV_LENGTH_8BITS 0x01
#define ENV_TYPE_USER 0x80
#define ENV_CODE_SYS(n,l) (((n)<<1)|(l))
#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER)
/*
* The actual TLV types we support
*/
#define ENV_TLV_TYPE_END 0x00
#define ENV_TLV_TYPE_ENV ENV_CODE_SYS(0,ENV_LENGTH_8BITS)
/*
* Environment variable flags
*/
#define ENV_FLG_NORMAL 0x00 /* normal read/write */
#define ENV_FLG_BUILTIN 0x01 /* builtin - not stored in flash */
#define ENV_FLG_READONLY 0x02 /* read-only - cannot be changed */
#define ENV_FLG_MASK 0xFF /* mask of attributes we keep */
#define ENV_FLG_ADMIN 0x100 /* lets us internally override permissions */
/* *********************************************************************
* Prototypes
********************************************************************* */
int env_delenv(const char *name);
char *env_getenv(const char *name);
int env_setenv(const char *name,char *value,int flags);
int env_load(void);
int env_save(void);
int env_enum(int idx,char *name,int *namelen,char *val,int *vallen);
int env_envtype(const char *name);
int env_getval(const char *name);
/****************************************************************************
* File: env_subr.c
* Descript:
* Author: unkown
* Fix history:
* 1, Wenxy, 20090317,a.m., unite with pack and unpack.
*
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include "lib_queue.h"
#include "lib_types.h"
#include "env_subr.h"
#define CFE_ERR_ENVNOTFOUND -1
#define CFE_ERR_ENVREADONLY -2
#define CFE_ERR_NOMEM -3
#define CFE_INIT_SAFE -4
#define CFE_ERR_IOERR -5
#ifndef LINUX_KERNEL
#define KFREE free
#define KMALLOC malloc
#define lib_atoi atoi
#define strnchr strchr
int nvram_read(char *p, int n1, int n2)
{
return 0;
};
int nvram_getsize()
{
return 0;
}
int nvram_open()
{
return 0;
}
int cfe_startflags;
int nvram_close()
{
return 0;
}
int nvram_write()
{
return 0;
}
int nvram_erase()
{
return 0;
}
#endif
/* *********************************************************************
* Types
********************************************************************* */
typedef struct cfe_envvar_s {
queue_t qb;
int flags;
char *name;
char *value;
/* name and value go here */
} cfe_envvar_t;
/* *********************************************************************
* Globals
********************************************************************* */
queue_t env_envvars = {&env_envvars,&env_envvars};
extern unsigned int cfe_startflags;
/* *********************************************************************
* env_findenv(name)
*
* Locate an environment variable in the in-memory list
*
* Input parameters:
* name - name of env var to find
*
* Return value:
* cfe_envvar_t pointer, or NULL if not found
********************************************************************* */
static cfe_envvar_t *env_findenv(const char *name)
{
queue_t *qb;
cfe_envvar_t *env;
for (qb = env_envvars.q_next; qb != &env_envvars; qb = qb->q_next) {
env = (cfe_envvar_t *) qb;
if (strcmp(env->name,name) == 0) break;
}
if (qb == &env_envvars) return NULL;
return (cfe_envvar_t *) qb;
}
/* *********************************************************************
* env_enum(idx,name,namelen,val,vallen)
*
* Enumerate environment variables. This routine locates
* the nth environment variable and copies its name and value
* to user buffers.
*
* The namelen and vallen variables must be preinitialized to
* the maximum size of the output buffer.
*
* Input parameters:
* idx - variable index to find (starting with zero)
* name,namelen - name buffer and length
* val,vallen - value buffer and length
*
* Return value:
* 0 if ok
* else error code
********************************************************************* */
int env_enum(int idx,char *name,int *namelen,char *val,int *vallen)
{
queue_t *qb;
cfe_envvar_t *env;
for (qb = env_envvars.q_next; qb != &env_envvars; qb = qb->q_next) {
if (idx == 0) break;
idx--;
}
if (qb == &env_envvars) return CFE_ERR_ENVNOTFOUND;
env = (cfe_envvar_t *) qb;
*namelen = strncpy(name,env->name,*namelen);
*vallen = strncpy(val,env->value,*vallen);
return 0;
}
/* *********************************************************************
* env_envtype(name)
*
* Return the type of the environment variable
*
* Input parameters:
* name - name of environment variable
*
* Return value:
* flags, or <0 if error occured
********************************************************************* */
int env_envtype(const char *name)
{
cfe_envvar_t *env;
env = env_findenv(name);
if (env) {
return env->flags;
}
return CFE_ERR_ENVNOTFOUND;
}
/* *********************************************************************
* env_delenv(name)
*
* Delete an environment variable
*
* Input parameters:
* name - environment variable to delete
*
* Return value:
* 0 if ok
* else error code
********************************************************************* */
int env_delenv(const char *name)
{
cfe_envvar_t *env;
env = env_findenv(name);
if (!env) return 0;
if (!(env->flags & ENV_FLG_READONLY)) {
q_dequeue((queue_t *) env);
KFREE(env);
return 0;
}
return CFE_ERR_ENVNOTFOUND;
}
/* *********************************************************************
* env_getenv(name)
*
* Retrieve the value of an environment variable
*
* Input parameters:
* name - name of environment variable to find
*
* Return value:
* value, or NULL if variable is not found
********************************************************************* */
char *env_getenv(const char *name)
{
cfe_envvar_t *env;
env = env_findenv(name);
if (env) {
return env->value;
}
return NULL;
}
/* *********************************************************************
* env_getval(name)
*
* Retrieve the integer value of an environment variable.
*
* Input parameters:
* name - name of environment variable to find
*
* Return value:
* integer value, or -1 if variable is not found
********************************************************************* */
int env_getval(const char *name)
{
char *s;
int val = -1;
s = env_getenv(name);
if( s )
val = lib_atoi(s);
return val;
}
/* *********************************************************************
* env_setenv(name,value,flags)
*
* Set the value of an environment variable
*
* Input parameters:
* name - name of variable
* value - value of variable
* flags - flags for variable (ENV_FLG_xxx)
*
* Return value:
* 0 if ok
* else error code
********************************************************************* */
int env_setenv(const char *name,char *value,int flags)
{
cfe_envvar_t *env;
int namelen;
env = env_findenv(name);
if (env) {
if (!(flags & ENV_FLG_ADMIN)) {
if (env->flags & ENV_FLG_READONLY) return CFE_ERR_ENVREADONLY;
}
q_dequeue((queue_t *) env);
KFREE(env);
}
namelen = strlen(name);
env = KMALLOC(sizeof(cfe_envvar_t) + namelen + 1 + strlen(value) + 1,0);
if (!env) return CFE_ERR_NOMEM;
env->name = (char *) (env+1);
env->value = env->name + namelen + 1;
env->flags = (flags & ENV_FLG_MASK);
strcpy(env->name,name);
strcpy(env->value,value);
q_enqueue(&env_envvars,(queue_t *) env);
return 0;
}
/* *********************************************************************
* env_load()
*
* Load the environment from the NVRAM device.
*
* Input parameters:
* nothing
*
* Return value:
* 0 if ok
* else error code
********************************************************************* */
int env_load(void)
{
int size;
unsigned char *buffer;
unsigned char *ptr;
unsigned char *envval;
unsigned int reclen;
unsigned int rectype;
int offset;
int flg;
int retval = -1;
char valuestr[256];
/*
* If in 'safe mode', don't read the environment the first time.
*/
if (cfe_startflags & CFE_INIT_SAFE) {
cfe_startflags &= ~CFE_INIT_SAFE;
return 0;
}
flg = nvram_open();
if (flg < 0) return flg;
size = nvram_getsize();
buffer = KMALLOC(size,0);
if (buffer == NULL) return CFE_ERR_NOMEM;
ptr = buffer;
offset = 0;
/* Read the record type and length */
if (nvram_read(ptr,offset,1) != 1) {
retval = CFE_ERR_IOERR;
goto error;
}
while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) {
/* Adjust pointer for TLV type */
rectype = *(ptr);
offset++;
size--;
/*
* Read the length. It can be either 1 or 2 bytes
* depending on the code
*/
if (rectype & ENV_LENGTH_8BITS) {
/* Read the record type and length - 8 bits */
if (nvram_read(ptr,offset,1) != 1) {
retval = CFE_ERR_IOERR;
goto error;
}
reclen = *(ptr);
size--;
offset++;
}
else {
/* Read the record type and length - 16 bits, MSB first */
if (nvram_read(ptr,offset,2) != 2) {
retval = CFE_ERR_IOERR;
goto error;
}
reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1);
size -= 2;
offset += 2;
}
if (reclen > size) break; /* should not happen, bad NVRAM */
switch (rectype) {
case ENV_TLV_TYPE_ENV:
/* Read the TLV data */
if (nvram_read(ptr,offset,reclen) != reclen) goto error;
flg = *ptr++;
envval = (unsigned char *) strnchr(ptr,'=',(reclen-1));
if (envval) {
*envval++ = '/0';
memcpy(valuestr,envval,(reclen-1)-(envval-ptr));
valuestr[(reclen-1)-(envval-ptr)] = '/0';
env_setenv(ptr,valuestr,flg);
}
break;
default:
/* Unknown TLV type, skip it. */
break;
}
/*
* Advance to next TLV
*/
size -= (int)reclen;
offset += reclen;
/* Read the next record type */
ptr = buffer;
if (nvram_read(ptr,offset,1) != 1) goto error;
}
retval = 0; /* success! */
error:
KFREE(buffer);
//nvram_close();
return retval;
}
/* *********************************************************************
* env_save()
*
* Write the environment to the NVRAM device.
*
* Input parameters:
* nothing
*
* Return value:
* 0 if ok, else error code
********************************************************************* */
int env_save(void)
{
int size;
unsigned char *buffer;
unsigned char *buffer_end;
unsigned char *ptr;
queue_t *qb;
cfe_envvar_t *env;
int namelen;
int valuelen;
int flg;
flg = nvram_open();
if (flg < 0) return flg;
nvram_erase();
size = nvram_getsize();
buffer = KMALLOC(size,0);
if (buffer == NULL) return CFE_ERR_NOMEM;
buffer_end = buffer + size;
ptr = buffer;
for (qb = env_envvars.q_next; qb != &env_envvars; qb = qb->q_next) {
env = (cfe_envvar_t *) qb;
if (env->flags & (ENV_FLG_BUILTIN)) continue;
namelen = strlen(env->name);
valuelen = strlen(env->value);
if ((ptr + 2 + namelen + valuelen + 1 + 1 + 1) > buffer_end) break;
*ptr++ = ENV_TLV_TYPE_ENV; /* TLV record type */
*ptr++ = (namelen + valuelen + 1 + 1); /* TLV record length */
*ptr++ = (unsigned char)env->flags;
memcpy(ptr,env->name,namelen); /* TLV record data */
ptr += namelen;
*ptr++ = '=';
memcpy(ptr,env->value,valuelen);
ptr += valuelen;
}
*ptr++ = ENV_TLV_TYPE_END;
size = nvram_write(buffer,0,ptr-buffer);
KFREE(buffer);
nvram_close();
return (size == (ptr-buffer)) ? 0 : CFE_ERR_IOERR;
}
/****************************************************************************
* File: lib_queue.c
* Descript:
* Author: unkown
* Fix history:
* 1, Wenxy, 20090317,a.m., unite with pack and unpack.
*
*****************************************************************************/
#include "lib_types.h"
#include "lib_queue.h"
/* *********************************************************************
* Q_ENQUEUE(qb,item)
*
* Add item to a queue
*
* Input Parameters:
* qb - queue block
* item - item to add
*
* Return Value:
* Nothing.
********************************************************************* */
void q_enqueue(queue_t *qb,queue_t *item)
{
qb->q_prev->q_next = item;
item->q_next = qb;
item->q_prev = qb->q_prev;
qb->q_prev = item;
}
/* *********************************************************************
* Q_DEQUEUE(element)
*
* Remove an element from the queue
*
* Input Parameters:
* element - element to remove
*
* Return Value:
* Nothing.
********************************************************************* */
void q_dequeue(queue_t *item)
{
item->q_prev->q_next = item->q_next;
item->q_next->q_prev = item->q_prev;
}
/* *********************************************************************
* Q_DEQNEXT(qb)
*
* Dequeue next element from the specified queue
*
* Input Parameters:
* qb - queue block
*
* Return Value:
* next element, or NULL
********************************************************************* */
queue_t *q_deqnext(queue_t *qb)
{
if (qb->q_next == qb) {
return NULL;
}
qb = qb->q_next;
qb->q_prev->q_next = qb->q_next;
qb->q_next->q_prev = qb->q_prev;
return qb;
}
/* *********************************************************************
* Q_MAP(qb)
*
* "Map" a queue, calling the specified function for each
* element in the queue
*
* If the function returns nonzero, q_map will terminate.
*
* Input Parameters:
* qb - queue block
* fn - function pointer
* a,b - parameters for the function
*
* Return Value:
* return value from function, or zero if entire queue
* was mapped.
********************************************************************* */
int q_map(queue_t *qb, int (*func)(queue_t *,unsigned int,unsigned int),
unsigned int a,unsigned int b)
{
queue_t *qe;
queue_t *nextq;
int res;
qe = qb;
qe = qb->q_next;
while (qe != qb) {
nextq = qe->q_next;
if ((res = (*func)(qe,a,b))) return res;
qe = nextq;
}
return 0;
}
/* *********************************************************************
* Q_COUNT(qb) *
* *
* Counts the elements on a queue (not interlocked) *
* *
* Input Parameters: *
* qb - queue block *
* *
* Return Value: *
* number of elements *
********************************************************************* */
int q_count(queue_t *qb)
{
queue_t *qe;
int res = 0;
qe = qb;
while (qe->q_next != qb) {
qe = qe->q_next;
res++;
}
return res;
}
/* *********************************************************************
* Q_FIND(qb,item)
*
* Determines if a particular element is on a queue.
*
* Input Parameters:
* qb - queue block
* item - queue element
*
* Return Value:
* 0 - not on queue
* >0 - position on queue
********************************************************************* */
int q_find(queue_t *qb,queue_t *item)
{
queue_t *q;
int res = 1;
q = qb->q_next;
while (q != item) {
if (q == qb) return 0;
q = q->q_next;
res++;
}
return res;
}
/****************************************************************************
* File: main.c
* Descript: test this queue
* Author: Wenxy, wen_kernel@163.com
* Fix history:
* 1, Wenxy, 20090317,a.m., unite with something, :-)
*
*****************************************************************************/
#include <stdio.h>
#include "lib_queue.h"
#include "env_subr.h"
static int ui_cmd_printenv(char *cmd,int argc,char *argv[])
{
char varname[80];
char value[256];
int varlen,vallen;
int idx;
printf("Variable Name Value/n");
printf("-------------------- --------------------------------------------------/n");
idx = 0;
for (;;) {
varlen = sizeof(varname);
vallen = sizeof(value);
if (env_enum(idx,varname,&varlen,value,&vallen) < 0) break;
printf("%20s %s/n",varname,value);
idx++;
}
return 0;
}
struct queue_s queue;
int main(int argc, char *argv[])
{
printf("Test a queue(list) .../n");
queue.q_next = queue.q_prev = NULL;
env_setenv("name-1", "value-1", 1);
env_setenv("name-2", "value-2", 1);
env_setenv("name-3", "value-3", 1);
ui_cmd_printenv(NULL, 0, NULL);
return 0;
}
2. result of test by VC++ 6.0
Test a queue(list) ...
Variable Name Value
-------------------- --------------------------------------------------
name-1 value-1
name-2 value-2
name-3 value-3