无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
楼主: chenall
打印 上一主题 下一主题

grub4dos 外部命令 wenv [2010-10-17 ]

  [复制链接]
541#
发表于 2010-10-15 19:31:29 | 只看该作者
回复

使用道具 举报

542#
 楼主| 发表于 2010-10-15 20:54:05 | 只看该作者
原帖由 tuxw 于 2010-10-15 19:31 发表
calc d++
回显示的还是自增前的结果


这个算是正常的,x++,是先使用x然后再x+1.当然显示的就是还没有++之前的值了。
回复

使用道具 举报

543#
发表于 2010-10-16 08:39:43 | 只看该作者
有个BUG:添加一个长度为8的变量名时,会删掉存储空间中紧邻其后的变量(如果存在)

测试:
reset
set a=1
set b=1
set a=  #前面这几句是为了确保添加的新变量后面存在一个有效变量
set a1234567=1 #这里将删掉变量b

这个BUG是 strcpn() 函数引入的,它默认复制后截断(这符合标准库特性),当我们复制长度为8的变量名时,它会在第9字节写入结束符,覆盖了下一个变量名。

建议将这个函数重定义为
static int strcpyn_ex(char *dest, const char *src, int n, int truncate);
#define strcpyn(dest, src, n)        strcpyn_ex(dest, src, n, 1)

在 strcpyn_ex 中,当 truncate 为真或实际写入字符数小于n时才截断。
然后只需将少数几处strcpyn改为strcpyn_ex。
回复

使用道具 举报

544#
发表于 2010-10-16 15:17:00 | 只看该作者
功能变化不大,和chenall的最新版基本保持兼容。

修正了楼上提到的BUG。
修改了一些细节和更精确的语法检查,比如 WENV set a*a,WENV abc 会检查出非法。
readme整理,源码排版、添加注释,和一些可读性方面的改善。目前这个源码基本上懂点C的人都能看懂其框架,多花点时间就能自己DIY了。

增加 WENV GET ?* 显示所内置变量
CALL 命令加了个别名RUN,大部分朋友不会始终关注WENV的更新,可能过了很才再使用WENV,RUN被CALL取代会有问题,让这个别名维持一时间,以后再取消。

偿试添加了一个 SWITCH 命令,可以改变 WENV 的一些默认行为。

    WENV SWITCH      显示当前的开关设置
    WENV SWITCH xxx  设置开关状态为 xxx (非0/1字符会自动格式化为1)

    目前试设置了三个开关, 使用简单语法,SWITCH xxx 时,最少必须有3位。
    因为开关只有两个状态,xxx 可以是任意字符,'0'表示关闭,其它均为打开。
    1. ECHO_LN              ECHO 后面是否自动换行
    2. REVERSE_STR          是否支持反向截取字符
    3. QUESTION_LENGTH    是否支持?{VAR}变量值长度
    初始状态为 "100",和没有SWITCH命令之前保持兼容。

    开关说明:
    1.ECHO_LN
    关闭时,ECHO 命令不自动换行(没有参数的ECHO仍然换行)

    2.REVERSE_STR
    对于通用字符串处理 ${VAR:x:-y}
    须满足 y < x,否则截取不到任何字符

    y >= x 这种情况没有用到
    当 REVERSE_STR 状态为打开时,将 y >= x 这种情况扩展为反向截取
    此时 -y 表示反向截取的字符数。
    WENV set a=123456789
    WENV echo ${a:-3:-2} 将显示7 (同默认情况)
    WENV echo ${a:-3:-3} 将显示 765 (从倒数第3个位置,反向取3个字符)
    WENV echo ${a:-1:-512} 将显示 987654321

    3.QUESTION_LENGTH
    原来用 get VAR 再通过 ${?_GET} 取长度的方法时效性太强,必须先get然后马上使用才比较可靠,且一次只能取一个变量的长度。这个开关是对取长度方法的补充。
    当 QUESTION_LENGTH 状态为打开时,?{VAR}有效,可以随时取任意变量长度。
这个开关打开后,在关闭之前原来取长度的方法失效,${?_GET}也会被删除。

    随着WENV的发展,功能越来越强,使用的人会越来越来多。WENV 默认行为很难满足所有人的需求。
    SWICH 命令试图给 WENV 引入一种可变的机制,使其可以更灵活的使用。
    目前的三个开关属于演示性质,如果有必要,以后会添加更多的开关和更直观的语法,如 WENV switch ECHO_LN=ON/OFF之类。

    注:WENV reset 可将开关状态恢复为默认值100。

wenv-tuxw-2010-10-16.zip (32.02 KB, 下载次数: 24)

#543楼的BUG还没有完全修复,而且手误导致reset VAR* 功能不正常,下面这个已经修复了

wenv-tuxw-2010-10-17.zip (32.04 KB, 下载次数: 24)

[ 本帖最后由 tuxw 于 2010-10-17 00:53 编辑 ]

Test-2010-10-16-15-14-58.png (9.85 KB, 下载次数: 85)

Test-2010-10-16-15-14-58.png
回复

使用道具 举报

545#
发表于 2010-10-16 16:44:51 | 只看该作者
?{var}显示变量值长度的方式不错;
反向取字符串,容易搞混,建议取消,实际可能也没有用处。
回复

使用道具 举报

546#
发表于 2010-10-16 19:44:29 | 只看该作者
嗯,这几个开关都是试验性质的,主要是SWITCH这个模式看有没有用处
回复

使用道具 举报

547#
发表于 2010-10-17 01:06:04 | 只看该作者
@chenall
#543楼的BUG即使采用改良的strcpyn亦不能完全修复,set_envi() 的时候,变量名还是得换回去用memmove()

使用改进后的strcpyn,大多数时候时正常的,但有一种情况会出错
删除一个较长的名字,比如a12345,当下在该位置设置一个较短的名字如a12时,变量设置是成功的,名字空间里保存的是 a12\045,这个没问题,get 所有变量也是正常的。
但再次对变量a12操作将失败,因为 envi_cmd 里查找变量时用 memcmp(VAR, ch, MAX_VAR_LEN) 完全比较8个字节,这种情况比较会失败。
回复

使用道具 举报

548#
 楼主| 发表于 2010-10-17 08:27:20 | 只看该作者
@tuxw
谢谢,这样只需要把设置变量名的那一句改成memmove就好了。
回复

使用道具 举报

549#
 楼主| 发表于 2010-10-17 10:01:09 | 只看该作者
已经更新,没有整合tuxw 的更新(嘻嘻,偷个懒)。只是修正BUG。

如果没有问题这个版本就作为正式版发布。若无BUG年内都不会再更新。

大家可以选择继续使用这个版本或使用tuxw的增强版。

ps: 终于有人接手了,我就可以偷懒了,欢迎大家支持tuxw的新版本。
回复

使用道具 举报

550#
发表于 2010-10-17 10:04:41 | 只看该作者
呵呵,新版本用什么方式比较好.
回复

使用道具 举报

551#
发表于 2010-10-17 15:21:29 | 只看该作者
wenv现在的功能已经够强大了,功能也够多了,不建议在其上面加功能了。
C大和tuxw有时间对文件系统作进一步完善。
回复

使用道具 举报

552#
发表于 2010-10-17 17:54:47 | 只看该作者
确实很强大了。
zhaohj有没有更新SRS_F6纯仿真驱动返回模块和SRS_F6 公用性SRS驱动的F6模块
如果有更新的时候共享一下,grub等软件都更新了。tuxw有时间也关注一下grub吧,人多力量大。
回复

使用道具 举报

553#
发表于 2010-10-17 20:23:23 | 只看该作者
先看张图:

用UD方式启动,进菜单后按c进入命令行,用ls /boot/  能够列出可见区boot下的全部文件,从中选一个文件,无论用大小写都找不到,但UD区/boot/下的文件可以找到。ls看得见的东西,怎么find反而找不到呢?纠结中.....

虽然可能与本主题无关,但还是在这个帖中向chenall大侠反映一下,请指教。
回复

使用道具 举报

554#
发表于 2010-10-17 23:51:07 | 只看该作者

回复 #553 hhh333 的帖子

一直是这样的。ls看得见的东西,find未必找得到。

迄今find是找不到(fd0,0)上的文件的。

可以先执行
map (fd0) (hd)
map --hook
然后再find。
回复

使用道具 举报

555#
发表于 2010-10-18 07:48:33 | 只看该作者

回复 #554 pseudo 的帖子

感谢P大解答,这算不算一个bug?
似乎用syslinux也不能启动,提示什么detect失败。难道这个fd0有些玄妙?
回复

使用道具 举报

556#
发表于 2010-10-18 08:54:49 | 只看该作者
这是我的理解:
一个标准的FD,没有 MBR,没有分区表,也就不应该出现(fd0,0)这种分区情形。
(fd0,0)这种分区是fbinst开发后才出现的一种“怪异”情形,只能被fbinst与相应版本的grldr识别;
目前的grub4dos尚不支持find到(fd0,0)。syslinux等更不能识别,当然不足为奇。
回复

使用道具 举报

557#
发表于 2010-10-18 09:47:53 | 只看该作者
原帖由 chenall 于 2010-10-17 08:27 发表
@tuxw
谢谢,这样只需要把设置变量名的那一句改成memmove就好了。


不修改strcpyn的话,设置变量值也要改成memmove,否则当一个变量的值长度为512或更长时时也会错,它会覆盖下一变量的值。(虽然这种情况比较少,但它是一个潜在的BUG,如果操作的是最后一个变量,就很危险,因为不知道它将覆盖的会是什么)

[ 本帖最后由 tuxw 于 2010-10-18 10:06 编辑 ]
回复

使用道具 举报

558#
发表于 2010-10-18 10:49:03 | 只看该作者

回复 #556 zxw 的帖子

P大的意思我还不是特明白,是fd0上的东西总是不能find,还是用了fbinst后找不到。我现在是要求find可见区的东西,不是UD中的。

我这个机子也有点那个,在其他机子上我这个U盘总是识别为usbhdd,到这里就成了usbzip(启动时按ESC键出启动菜单看到的),进UD后ls /boot/  显示的是可见区的东西。
但find都找不到。
回复

使用道具 举报

559#
发表于 2010-10-18 11:18:59 | 只看该作者
fbinst格式化的U盘,在有些机器上可见区成了usbzip,而且(fd0)会变成(fd0,0)。find是不会搜索(fd0,0)非标准软盘格式的盘的。
加个判断怎么样?
cat --length=0 (fd0,0)/标志文件 && map (fd0,0)+1 (fd0) && map --hook

PS:P大是改成(hd),不知改成(fd0)效果如何?

[ 本帖最后由 zhaohj 于 2010-10-18 11:30 编辑 ]
回复

使用道具 举报

560#
发表于 2010-10-18 11:23:03 | 只看该作者

回复 #559 zhaohj 的帖子

不能改成(fd0),改成(fd0)会读取不到ud区,可改成(fd1)或(hd)。
回复

使用道具 举报

561#
发表于 2010-10-18 11:33:01 | 只看该作者
原帖由 zxw 于 2010-10-18 11:23 发表
不能改成(fd0),改成(fd0)会读取不到ud区,可改成(fd1)或(hd)。


对,这样破坏了UD区,改成(fd1)或(hd)比较好,万一(fd1)要用的话。

[ 本帖最后由 zhaohj 于 2010-10-18 11:34 编辑 ]
回复

使用道具 举报

562#
发表于 2010-10-18 13:18:51 | 只看该作者
for ..do (command1 ; command2 ; ...)
现在有check命令,可以实现IF功能, 但感觉少了返回do的指针命令loop,使其不执行后面的命令体(循环体)。
如果苛刻的话,能实现跳出for的命令exit。
回复

使用道具 举报

563#
发表于 2010-10-18 15:01:15 | 只看该作者

回复 #559 zhaohj 的帖子

改成fd1还可能与F6模块冲突,看来只能用(hd)。但还是希望find功能能够更强大一点。为什么非标准就不能搜呢?期待不点或chenall能解决这个问题。
另外,可不可以不用标志文件,直接查有不有fd0,0
回复

使用道具 举报

564#
 楼主| 发表于 2010-10-18 15:10:01 | 只看该作者
原帖由 zhaohj 于 2010-10-18 13:18 发表
for ..do (command1 ; command2 ; ...)
现在有check命令,可以实现IF功能, 但感觉少了返回do的指针命令loop,使其不执行后面的命令体(循环体)。
如果苛刻的话,能实现跳出for的命令exit。

跳出for,可以考虑直接执行一个不带参数的kernel,
这样就会因为出错而退出了.
回复

使用道具 举报

565#
发表于 2010-10-18 17:27:49 | 只看该作者
想把(fd0)/txtsetup.sif转化为SRSID.TXT,先把[HardwareIdsDatabase]段落放在文件(fd0)/txtsetup.txt
map --mem /SRS_F6/F6.GZ (fd0)
map --hook
fat copy (hd0,0)/TXTSETUP.TXT (fd0)/
fat mkfile size=64k (fd0)/SRSID.TXT
write --offset=0 (fd0)/SRSID.TXT PCI$\r\n
wenv calc p=6
root (fd0)/
wenv for /f "eol=; tokens=1-2 delims==;" %i in ( /TXTSETUP.SIF ) do (set a=%i ; set a1=$${a:3} ; set a2=%j ; set b=$${a:0:3} ; check $${b}==PCI call write --offset=$${p} (fd0)/SRSID.TXT $PCI\\$${a1}=$${a2}\r\n ; get a ; set pp=$${?_GET} ; get a2 ; set pp1=$${?_GET} ; check $${b}==PCI calc p=$${p}+$${pp}+$${pp1}+2+2 ; echo $${p})
生成SRSID.TXT没问题;

问题:
[HardwareIdsDatabase]段落需要人工处理,C大有没有好的办法?
缺少一个象inifile功能的命令。

[ 本帖最后由 zhaohj 于 2010-10-18 17:36 编辑 ]

Snap1.jpg (169.65 KB, 下载次数: 79)

Snap1.jpg
回复

使用道具 举报

566#
发表于 2010-10-18 22:30:01 | 只看该作者
@chenall
子串替换函数replace()有个缓存溢出的BUG
你是先替换,再检查长度,如果溢出的话,已经晚了,应该先检查长度足够再替换
回复

使用道具 举报

567#
 楼主| 发表于 2010-10-18 23:37:52 | 只看该作者
原帖由 tuxw 于 2010-10-18 22:30 发表
@chenall
子串替换函数replace()有个缓存溢出的BUG
你是先替换,再检查长度,如果溢出的话,已经晚了,应该先检查长度足够再替换


这个不会,虽然是先替换后再检查,但是不会发生溢出的.

替换后进入下一个字符替换的时候就进行检测了.只会少不会多.即目前其实REPLACE函数最多允许字符数是510个(带截断).
不带截断是511个.

因为到写入第511个字符之后istr+1就是512了.这时if (istr >= MAX_ENV_LEN)为值就返回失败值了.

目前会出现溢出的函数是replace_str和var_expand函数.这个我没有进行长度检测.

其它的应该不太会.

这些你有空再看着办,我要偷懒去了.

目前只要一条命令(扩展后)不是太长一般来说是没有问题,如果太长的就可能发生错误.

而且一条命令是以" ; "分隔的,一般情况下不可能会出现这么长的命令.

但是()里面的语句不管多少";"都是算成一条这个需要注意.特别在是for命令中,只要不是很长就没有关系.

[ 本帖最后由 chenall 于 2010-10-18 23:38 编辑 ]
回复

使用道具 举报

568#
发表于 2010-10-18 23:42:15 | 只看该作者
如果有跳出do (循环体)的命令,返回开始使指针加1,前面的语法会相当简练,而且效率会高很多。
wenv for /f "eol=; tokens=1-2 delims==;" %i in ( /TXTSETUP.SIF ) do (set a=%i ; set a1=$${a:3} ; set a2=%j ; set b=$${a:0:3} ; check $${b}<>PCI loop ; ......)
上面loop跳出循环体,指针加1,返回for接着运行。

[ 本帖最后由 zhaohj 于 2010-10-18 23:58 编辑 ]
回复

使用道具 举报

569#
发表于 2010-10-18 23:57:30 | 只看该作者
溢出有已经碰到过了,不知现在的限制条件是什么?一行小于511字符?
回复

使用道具 举报

570#
发表于 2010-10-18 23:59:19 | 只看该作者
if (*p_buff == *sub && memcmp(p_buff,sub,isub) == 0)
{
        strcpyn(str,rep,irep); // 这里溢出的话,后面检查长度是没用的
        str += irep;
        p_buff += isub;
        istr += irep;
}
else
{
        *str++ = *p_buff++;//不是这里
        istr++;
}
if (istr >= MAX_ENV_LEN)
        return 0;

这样改一下
if( *p_buff == *sub && 0 == memcmp(p_buff, sub, isub) )        // 找到子串
{
        if( irep > 0 )        // 替换串为空时相当于删除查找的子串
        {
                if( istr + irep > MAX_ENV_LEN )        // 检查缓存是否足够容纳替换串(缓存长度我改为MAX_ENV_LEN+1了)
                        return 0;

                strcpyn_ex(str, rep, irep, 0);
                str  += irep;
                istr += irep;
        }
        p_buff += isub;
}

[ 本帖最后由 tuxw 于 2010-10-19 00:08 编辑 ]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2024-11-23 19:32

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表