openssl3.2 - linux脚本(.sh)调用openssl命令行参数的简单确认方法

文章目录

    • openssl3.2 - linux脚本(.sh)调用openssl命令行参数的简单确认方法
    • 概述
    • 笔记
    • 修改openssl实现的前置条件
    • 修改debian12.4下编译好的openssl实现, 将入口参数记录下来
    • 测试效果
    • 备注
    • 补充 - 将管道文件记录到本地文件
    • 效果
    • 备注
    • 补充 - 要考虑到管道的读
    • bug_fix - 补充-extfile时的管道
    • 修正 - 将日志文件改为一个文件
    • 修正 - 需要考虑同一选项出现多次的情况
    • END

openssl3.2 - linux脚本(.sh)调用openssl命令行参数的简单确认方法

概述

在琢磨官方工程中的/test/certs中的2个脚本(setup.sh, mkcert.sh)
这2个脚本有不到500个openssl命令行调用, 应该是openssl内部测试证书操作的脚本.
确定这2个脚本是好东西(将证书操作一网打尽, 弄清了这2个脚本, 就没有不会的证书操作了).

但是脚本调用, 到了调用openssl时, 参数拼接很烦人, 我只想看具体到了openssl的可执行文件, 到底给了啥命令行参数.
有一些参数是用管道给的, 用stdin给的一个buffer代表一个参数文件, 这很烦啊.
官方给用户的正式例子, 都是用 in 参数, 然后给一个文件名. 这样多清爽.
.sh又不熟, 想将.sh改成可以传文件名给openssl的例子, 可能要花多一些时间.
一直在琢磨是否有更好的方法能确定最终的openssl命令行参数, 突然想到, 为啥不直接将openssl实现给改了, 在程序入口, 写几句日志, 将命令行参数记录下来, 这不一了百了啊. 研究啥.sh怎么写啊.
只要确定给了啥命令行参数, 那就好办了.
我已经编译好了在windows下可用的VS2019的openssl.exe的工程, 那就在自己工程中, 舒舒服服的调试好了(openssl3.2 - 自己构建openssl.exe的VS工程(在编译完的源码版本上), openssl3.2 - 在VS2019下源码调试openssl.exe).

笔记

修改openssl实现的前置条件

已经在debian12.4下, 配置, 编译, 测试, 安装都通过了.
且配置了debian12.4, 让本地普通目录中运行openssl命令行已经好使(openssl3.2 - 编译).

修改debian12.4下编译好的openssl实现, 将入口参数记录下来

参照我重建的win版openssl.exe工程, 可知 main()函数在openssl.c
去debian12.4下原版源码目录中确定是./apps/openssl.c

修改如下, 只在程序入口处, 加了一段日志文件的操作, 将openssl可执行文件的命令行参数附加到日志文件.

static char *help_argv[] = { "help", NULL };
static char *version_argv[] = { "version", NULL };int main(int argc, char *argv[])
{FUNCTION f, *fp;LHASH_OF(FUNCTION) *prog = NULL;char *pname;const char *fname;ARGS arg;int global_help = 0;int global_version = 0;int ret = 0;int i = 0;FILE* pfLog = NULL;// 将入参全部写入文件待调试, 去看.sh太繁琐了if (1){pfLog = fopen("/home/lostspeed/openssl/my_openssl_log.txt", "a");if (NULL != pfLog){for (i = 0; i < argc; i++){fwrite(argv[i], sizeof(char), strlen(argv[i]), pfLog);// 每个参数中间加一个空格fwrite(" ", sizeof(char), 1, pfLog);}// 追加完一次openssl命令行调用, 换一行fwrite("\r\n", sizeof(char), 2, pfLog);fclose(pfLog);pfLog = NULL;}}arg.argv = NULL;arg.size = 0;

在正常的工程中, 只进行make, make install

测试效果

在普通目录中运行了2个命令

openssl version -a 
openssl --help

查看自己指定的位置确实有日志文件.

lostspeed@debian12d4x64:~/openssl$ pwd
/home/lostspeed/openssl
lostspeed@debian12d4x64:~/openssl$ ls -l
总计 488136
-rw-r--r--  1 lostspeed lostspeed        38  1月20日 22:29 my_openssl_log.txt
drwxr-xr-x 26 lostspeed lostspeed      4096  1月20日 21:13 openssl-3.2.0_debian
-rw-r--r--  1 lostspeed lostspeed 482136966  1月20日 21:17 openssl-3.2.0_debian.tar.gz
-rwxr-xr-x  1 root      root       17698352  1月20日 13:55 openssl-3.2.0.tar.gz

查看此日志文件

lostspeed@debian12d4x64:~/openssl$ cat ./my_openssl_log.txt 
openssl version -a 
openssl --help 
lostspeed@debian12d4x64:~/openssl$ 

备注

这方法好使.
那我下一步就将setup.sh改成每次只执行一个命令的版本. e.g. setup1.sh, setup2.sh.
知道了具体的命令行操作, 那么就可以去win版的openssl.exe工程去查, 将stdin给出的参数文件流内容, 改为可以落地的参数和文件名.
那我也不用去改debian12.4下的那2个.sh脚本了, 调试强度一下子就降低好多.

补充 - 将管道文件记录到本地文件

脚本传递文件时, 到了openssl入口, 可以看到传进来的是一个管道文件名.

openssl req -new -sha256 -key root-key.pem -config /dev/fd/63

需要将这个管道文件也保存到日志中, 这样就知道了openssl命令行的所有参数, 就可以在windows下的openssl.exe的vs2019中开心的调试了.
将openssl.c又完善了一下, 对openssl.c的修改部分如下:

static char *help_argv[] = { "help", NULL };
static char *version_argv[] = { "version", NULL };// /home/lostspeed/openssl/openssl-3.2.0_debian/test/certs/my_openssl_linux_log.txt
// D:\\my_dev\\my_local_git_prj\\study\\openSSL\\test_certs\\my_openssl_win_log.txt#ifdef _WIN32
#define MY_LOG_DIR "D:\\my_dev\\my_local_git_prj\\study\\openSSL\\test_certs"
#define MY_LOG_FILE "my_openssl_win_log.txt"
#define MY_LOG_FILE_PATH_NAME MY_LOG_DIR "\\" MY_LOG_FILE#define MY_PIPE_FILE "cmd_line_pipe_in_win.txt"
#define MY_PIPE_FILE_OUT_PATH_NAME MY_LOG_DIR "\\" MY_PIPE_FILE
#else
// -config /dev/fd/63
#define MY_LOG_DIR "/home/lostspeed/openssl/openssl-3.2.0_debian/test/certs"
#define MY_LOG_FILE "my_openssl_linux_log.txt"
#define MY_LOG_FILE_PATH_NAME MY_LOG_DIR "/" MY_LOG_FILE#define MY_PIPE_FILE "cmd_line_pipe_in_linux.txt"
#define MY_PIPE_FILE_OUT_PATH_NAME MY_LOG_DIR "/" MY_PIPE_FILE
#endif // #ifdef _WIN32void read_file_write_to_another(const char* pszFileSrc, const char* pszFileDst)
{FILE* fpSrc = NULL;FILE* fpDst = NULL;char szBuf[4096];size_t nRdBk = 0;do {if ((NULL == pszFileSrc) || (NULL == pszFileDst)){break;}fpSrc = fopen(pszFileSrc, "r");if (NULL == fpSrc){break;}fpDst = fopen(pszFileDst, "a");if (NULL == fpDst) {break;}// 在向管道记录文件附加新内容之前, 在每个文件前面加3个空行, 可以区分出多个文件fwrite("\r\n", sizeof(char), 2, fpDst);fwrite("\r\n", sizeof(char), 2, fpDst);fwrite("\r\n", sizeof(char), 2, fpDst);do {nRdBk = fread(szBuf, sizeof(char), sizeof(szBuf), fpSrc);if (nRdBk <= 0){break;}fwrite(szBuf, sizeof(char), nRdBk, fpDst);} while (1);} while (0);if (NULL != fpSrc){fclose(fpSrc);fpSrc = NULL;}if (NULL != fpDst){fclose(fpDst);fpDst = NULL;}
}void wirte_cmd_line_param_to_log_file(int argc, char* argv[])
{int i = 0;FILE* pfLog = NULL;const char* psz_argv = NULL;// 将入参全部写入文件待调试, 去看.sh太繁琐了if (1){// 将程序的命令行参数记录进日志文件pfLog = fopen(MY_LOG_FILE_PATH_NAME, "a");if (NULL != pfLog){for (i = 0; i < argc; i++){// 程序的名称都为"openssl"psz_argv = ((0 != i) ? argv[i] : "openssl");fwrite(psz_argv, sizeof(char), strlen(psz_argv), pfLog);// 每个参数中间加一个空格fwrite(" ", sizeof(char), 1, pfLog);}// 追加完一次openssl命令行调用, 换一行fwrite("\r\n", sizeof(char), 2, pfLog);fclose(pfLog);pfLog = NULL;}// 将管道文件记录进配置文件for (i = 0; i < argc; i++){// -config /dev/fd/63if (0 == strcmp(argv[i], "-config")){if ((i + 1) < argc){if (0 == strcmp(argv[i + 1], "/dev/fd/63")){read_file_write_to_another(argv[i + 1], MY_PIPE_FILE_OUT_PATH_NAME);}}break;}}}
}int main(int argc, char *argv[])
{FUNCTION f, *fp;LHASH_OF(FUNCTION) *prog = NULL;char *pname;const char *fname;ARGS arg;int global_help = 0;int global_version = 0;int ret = 0;wirte_cmd_line_param_to_log_file(argc, argv);arg.argv = NULL;arg.size = 0;

修改后的openssl.c在windows下和debian12.4下是通用的. 编译安装后, 好使.

效果

lostspeed@debian12d4x64:~/openssl/openssl-3.2.0_debian/test/certs$ pwd
/home/lostspeed/openssl/openssl-3.2.0_debian/test/certs
lostspeed@debian12d4x64:~/openssl/openssl-3.2.0_debian/test/certs$ ls -l
总计 104
-rwxr-xr-x 1 lostspeed lostspeed 11679  1月21日 14:05 mkcert.sh
-rwxr-xr-x 1 lostspeed lostspeed 11679  1月21日 14:05 mkcert.sh.bk
-rwxr-xr-x 1 lostspeed lostspeed   111  1月21日 14:05 my_lib.sh
-rwxr-xr-x 1 lostspeed lostspeed 17315  1月21日 14:05 openssl.c
-rwxr-xr-x 1 lostspeed lostspeed  1704  1月21日 14:05 root-key.pem
-rwxr-xr-x 1 lostspeed lostspeed   388  1月21日 14:05 setup001.sh
-rwxr-xr-x 1 lostspeed lostspeed 23948  1月21日 14:05 setup.sh
-rwxr-xr-x 1 lostspeed lostspeed 23948  1月21日 14:05 setup.sh.bk
lostspeed@debian12d4x64:~/openssl/openssl-3.2.0_debian/test/certs$ 
lostspeed@debian12d4x64:~/openssl/openssl-3.2.0_debian/test/certs$ cat ./setup001.sh 
#! /bin/bash# \file setup001.sh# printf "%s\n" "hello openssl"# my_lib.sh fn_to_file <(printf "hello 1")
# ./my_lib.sh fn_to_file param1 param2# fn_to_file()
#{
#    printf ">> fn_to_file\n"
#
#    printf "%s\n" "$@"
#}# printf ">> setup001.sh\n"
# fn_to_file < <(printf "stdin to function\n")# Primary root: root-cert
./mkcert.sh genroot "Root CA" root-key root-certexit 0
lostspeed@debian12d4x64:~/openssl/openssl-3.2.0_debian/test/certs$ ./setup001.sh 
lostspeed@debian12d4x64:~/openssl/openssl-3.2.0_debian/test/certs$ ls -l
总计 112
-rw-r--r-- 1 lostspeed lostspeed    87  1月21日 14:13 cmd_line_pipe_in_linux.txt // 记录管道输入给命令行的配置文件
-rwxr-xr-x 1 lostspeed lostspeed 11679  1月21日 14:05 mkcert.sh
-rwxr-xr-x 1 lostspeed lostspeed 11679  1月21日 14:05 mkcert.sh.bk
-rwxr-xr-x 1 lostspeed lostspeed   111  1月21日 14:05 my_lib.sh
-rw-r--r-- 1 lostspeed lostspeed    64  1月21日 14:13 my_openssl_linux_log.txt // 记录命令行的日志文件
-rwxr-xr-x 1 lostspeed lostspeed 17315  1月21日 14:05 openssl.c
-rwxr-xr-x 1 lostspeed lostspeed  1704  1月21日 14:05 root-key.pem // 干活后的输出文件
-rwxr-xr-x 1 lostspeed lostspeed   388  1月21日 14:05 setup001.sh
-rwxr-xr-x 1 lostspeed lostspeed 23948  1月21日 14:05 setup.sh
-rwxr-xr-x 1 lostspeed lostspeed 23948  1月21日 14:05 setup.sh.bk
lostspeed@debian12d4x64:~/openssl/openssl-3.2.0_debian/test/certs$ cat ./my_openssl_linux_log.txt 
openssl req -new -sha256 -key root-key.pem -config /dev/fd/63 
lostspeed@debian12d4x64:~/openssl/openssl-3.2.0_debian/test/certs$ cat ./cmd_line_pipe_in_linux.txt string_mask=utf8only
[req]
prompt = no
distinguished_name = dn
[dn]
CN = Root CA

备注

调试材料的准备:
将cmd_line_pipe_in_linux.txt中的原来管道传来的配置文件内容保存成一个配置文件. e.g. tmp.cfg
将my_openssl_linux_log.txt 记录的openssl命令行参数中的管道配置文件 /dev/fd/63 改为tmp.cfg
新的可以在本地单步调试的命令行为 : openssl req -new -sha256 -key root-key.pem -config tmp.cfg

这就可以正常单步调试了.
剩下的事情, 就是将官方原来的/test/certs/setup.sh中的不到500条证书操作命令, 全部整理成单条的脚本.
然后单独运行一条脚本, 得到一组openssl的命令行, 自己单步跟一下, 知道了openssl对命令行参数的要求就行了.

一天搞50个, 10天搞定:P

补充 - 要考虑到管道的读

管道读, 读一个字节, 管道里面少一个字节.
如果想将管道中的东西保存成文件供调试用, 那么程序用的管道数据就没有了.
想了一个解决方法, 我从管道读出的内容, 我是知道的. 将管道读出的内容保存成文件供调试.
然后再将自己读出的buffer, 再写入管道. 模拟自己没动过管道的数据
试了一下好使, 不影响openssl自带的功能.

#endif /* OPENSSL_NO_TRACE */static char *help_argv[] = { "help", NULL };
static char *version_argv[] = { "version", NULL };// /home/lostspeed/openssl/openssl-3.2.0_debian/test/certs/my_openssl_linux_log.txt
// D:\\my_dev\\my_local_git_prj\\study\\openSSL\\test_certs\\my_openssl_win_log.txt#ifdef _WIN32
#define MY_LOG_DIR "D:\\my_dev\\my_local_git_prj\\study\\openSSL\\test_certs"
#define MY_LOG_FILE "my_openssl_win_log.txt"
#define MY_LOG_FILE_PATH_NAME MY_LOG_DIR "\\" MY_LOG_FILE#define MY_PIPE_FILE "cmd_line_pipe_in_win.txt"
#define MY_PIPE_FILE_OUT_PATH_NAME MY_LOG_DIR "\\" MY_PIPE_FILE
#else
// -config /dev/fd/63
#define MY_LOG_DIR "/home/lostspeed/openssl/openssl-3.2.0_debian/test/certs"
#define MY_LOG_FILE "my_openssl_linux_log.txt"
#define MY_LOG_FILE_PATH_NAME MY_LOG_DIR "/" MY_LOG_FILE#define MY_PIPE_FILE "cmd_line_pipe_in_linux.txt"
#define MY_PIPE_FILE_OUT_PATH_NAME MY_LOG_DIR "/" MY_PIPE_FILE
#endif // #ifdef _WIN32void read_file_write_to_another(const char* pszFileSrc, const char* pszFileDst)
{
#define MY_BUFFER_SIZE (1024 * 1024)FILE* fpSrc = NULL;FILE* fpDst = NULL;char* pSzBuf = NULL; // 开个1MB的空间, 从管道中读出来后, 保存进文件, 再写进管道, 这样相当于没有动管道size_t nRdBk = 0;size_t nWrBk = 0;size_t nRdBkAll = 0;do {if ((NULL == pszFileSrc) || (NULL == pszFileDst)){break;}pSzBuf = malloc(MY_BUFFER_SIZE);if (NULL == pSzBuf){break;}fpSrc = fopen(pszFileSrc, "r");if (NULL == fpSrc){break;}fpDst = fopen(pszFileDst, "a");if (NULL == fpDst) {break;}// 在向管道记录文件附加新内容之前, 在每个文件前面加3个空行, 可以区分出多个文件fwrite("\r\n", sizeof(char), 2, fpDst);fwrite("\r\n", sizeof(char), 2, fpDst);fwrite("\r\n", sizeof(char), 2, fpDst);nRdBkAll = 0;do {nRdBk = fread(pSzBuf + nRdBkAll, sizeof(char), 1024, fpSrc);if (nRdBk <= 0){break;}nWrBk = fwrite(pSzBuf, sizeof(char), nRdBk, fpDst);if (nWrBk != nRdBk){printf("error : write to fpDst => write to = %zu, return form write = %zu\n", nRdBk, nWrBk);break;}nRdBkAll += nRdBk;} while (1);fclose(fpSrc); // 关掉源文件// 管道读之后, 指针挪动了. 尝试将指针移动到管道开头// fseek(fpSrc, 0, 0); // 不好使, 从管道中读了东西后, 管道中的东西就没有了// 管道中的东西, 读出来后, 就消失了, 再模拟将读出来的东西, 写进入试试. 模拟我没动管道中的东西fpSrc = fopen(pszFileSrc, "w");if (NULL == fpSrc){break;}nRdBk = fwrite(pSzBuf, sizeof(char), nRdBkAll, fpSrc); if (nRdBk != nRdBkAll){printf("error : rewrite to pipe => nRdBkAll = %zu, nRdBk = %zu\n", nRdBkAll, nRdBk);}} while (0);if (NULL != pSzBuf){free(pSzBuf);pSzBuf = NULL;}if (NULL != fpSrc){fclose(fpSrc);fpSrc = NULL;}if (NULL != fpDst){fclose(fpDst);fpDst = NULL;}
}void wirte_cmd_line_param_to_log_file(int argc, char* argv[])
{int i = 0;FILE* pfLog = NULL;const char* psz_argv = NULL;// 将入参全部写入文件待调试, 去看.sh太繁琐了if (1){// 将程序的命令行参数记录进日志文件pfLog = fopen(MY_LOG_FILE_PATH_NAME, "a");if (NULL != pfLog){for (i = 0; i < argc; i++){// 程序的名称都为"openssl"psz_argv = ((0 != i) ? argv[i] : "openssl");fwrite(psz_argv, sizeof(char), strlen(psz_argv), pfLog);// 每个参数中间加一个空格fwrite(" ", sizeof(char), 1, pfLog);}// 追加完一次openssl命令行调用, 换一行fwrite("\r\n", sizeof(char), 2, pfLog);fclose(pfLog);pfLog = NULL;}// 将管道文件记录进配置文件for (i = 0; i < argc; i++){// -config /dev/fd/63if (0 == strcmp(argv[i], "-config")){if ((i + 1) < argc){if (0 == strcmp(argv[i + 1], "/dev/fd/63")){read_file_write_to_another(argv[i + 1], MY_PIPE_FILE_OUT_PATH_NAME);// 如果将管道指着移动到管道的头部还好使, 那就和未修改程序前相同// 管道中的东西, 读出来就没有了, 不过, 我已经又将读出来的东西, 又写回去了// read_file_write_to_another(argv[i + 1], MY_PIPE_FILE_OUT_PATH_NAME);}}break;}}}
}int main(int argc, char *argv[])
{FUNCTION f, *fp;LHASH_OF(FUNCTION) *prog = NULL;char *pname;const char *fname;ARGS arg;int global_help = 0;int global_version = 0;int ret = 0;// 打印自己的版本号标记if ((2 == argc) && (0 == strcmp("-v", argv[1]))){printf("ls modify openSSL3.2.0_build_002 last build 2024/1/21 17:27:00\n");}wirte_cmd_line_param_to_log_file(argc, argv);arg.argv = NULL;arg.size = 0;/* Set up some of the environment. */bio_in = dup_bio_in(FORMAT_TEXT);bio_out = dup_bio_out(FORMAT_TEXT);bio_err = dup_bio_err(FORMAT_TEXT);

bug_fix - 补充-extfile时的管道

调试着, 发现有点不对劲.
看着官方.sh, 每个openssl命令行用管道传进来的东西都不应该为空啊.
查了一下, 原来管道进来时, 前面参数是 -config 或者 -extfile, 这2个参数后面跟的才是管道名.
我看花眼了, 只处理了 -config后面的管道文件内容记录.
修正了一下.

static char *help_argv[] = { "help", NULL };
static char *version_argv[] = { "version", NULL };// /home/lostspeed/openssl/openssl-3.2.0_debian/test/certs/my_openssl_linux_log.txt
// D:\\my_dev\\my_local_git_prj\\study\\openSSL\\test_certs\\my_openssl_win_log.txt#ifdef _WIN32
#define MY_LOG_DIR "D:\\my_dev\\my_local_git_prj\\study\\openSSL\\test_certs"
#define MY_LOG_FILE "my_openssl_win_log.txt"
#define MY_LOG_FILE_PATH_NAME MY_LOG_DIR "\\" MY_LOG_FILE#define MY_PIPE_FILE "cmd_line_pipe_in_win.txt"
#define MY_PIPE_FILE_OUT_PATH_NAME MY_LOG_DIR "\\" MY_PIPE_FILE
#else
// -config /dev/fd/63
#define MY_LOG_DIR "/home/lostspeed/openssl/openssl-3.2.0_debian/test/certs"
#define MY_LOG_FILE "my_openssl_linux_log.txt"
#define MY_LOG_FILE_PATH_NAME MY_LOG_DIR "/" MY_LOG_FILE#define MY_PIPE_FILE "cmd_line_pipe_in_linux.txt"
#define MY_PIPE_FILE_OUT_PATH_NAME MY_LOG_DIR "/" MY_PIPE_FILE
#endif // #ifdef _WIN32void read_file_write_to_another(const char* pszCfgName, const char* pszFileSrc, const char* pszFileDst)
{
#define MY_BUFFER_SIZE (1024 * 1024)FILE* fpSrc = NULL;FILE* fpDst = NULL;char* pSzBuf = NULL; // 开个1MB的空间, 从管道中读出来后, 保存进文件, 再写进管道, 这样相当于没有动管道size_t nRdBk = 0;size_t nWrBk = 0;size_t nRdBkAll = 0;do {if ((NULL == pszCfgName) || (NULL == pszFileSrc) || (NULL == pszFileDst)){break;}pSzBuf = malloc(MY_BUFFER_SIZE);if (NULL == pSzBuf){break;}fpSrc = fopen(pszFileSrc, "r");if (NULL == fpSrc){break;}fpDst = fopen(pszFileDst, "a");if (NULL == fpDst) {break;}// 在向管道记录文件附加新内容之前, 在每个文件前面加3个空行, 可以区分出多个文件fwrite("\r\n", sizeof(char), 2, fpDst);fprintf(fpDst, "%s %s => %s\n", pszCfgName, pszFileSrc, pszFileDst); // tip msgfwrite("\r\n", sizeof(char), 2, fpDst);fwrite("\r\n", sizeof(char), 2, fpDst);fwrite("\r\n", sizeof(char), 2, fpDst);nRdBkAll = 0;do {nRdBk = fread(pSzBuf + nRdBkAll, sizeof(char), 1024, fpSrc);if (nRdBk <= 0){break;}nWrBk = fwrite(pSzBuf, sizeof(char), nRdBk, fpDst);if (nWrBk != nRdBk){printf("error : write to fpDst => write to = %zu, return form write = %zu\n", nRdBk, nWrBk);break;}nRdBkAll += nRdBk;} while (1);fclose(fpSrc); // 关掉源文件// 管道读之后, 指针挪动了. 尝试将指针移动到管道开头// fseek(fpSrc, 0, 0); // 不好使, 从管道中读了东西后, 管道中的东西就没有了// 管道中的东西, 读出来后, 就消失了, 再模拟将读出来的东西, 写进入试试. 模拟我没动管道中的东西fpSrc = fopen(pszFileSrc, "w");if (NULL == fpSrc){break;}nRdBk = fwrite(pSzBuf, sizeof(char), nRdBkAll, fpSrc); if (nRdBk != nRdBkAll){printf("error : rewrite to pipe => nRdBkAll = %zu, nRdBk = %zu\n", nRdBkAll, nRdBk);}} while (0);if (NULL != pSzBuf){free(pSzBuf);pSzBuf = NULL;}if (NULL != fpSrc){fclose(fpSrc);fpSrc = NULL;}if (NULL != fpDst){fclose(fpDst);fpDst = NULL;}
}void wirte_cmd_line_param_to_log_file(int argc, char* argv[])
{int i = 0;FILE* pfLog = NULL;const char* psz_argv = NULL;// 将入参全部写入文件待调试, 去看.sh太繁琐了if (1){// 将程序的命令行参数记录进日志文件pfLog = fopen(MY_LOG_FILE_PATH_NAME, "a");if (NULL != pfLog){for (i = 0; i < argc; i++){// 程序的名称都为"openssl"psz_argv = ((0 != i) ? argv[i] : "openssl");fwrite(psz_argv, sizeof(char), strlen(psz_argv), pfLog);// 每个参数中间加一个空格fwrite(" ", sizeof(char), 1, pfLog);}// 追加完一次openssl命令行调用, 换一行fwrite("\r\n", sizeof(char), 2, pfLog);fclose(pfLog);pfLog = NULL;}// 将管道文件记录进配置文件for (i = 0; i < argc; i++){// -config /dev/fd/63if ((0 == strcmp(argv[i], "-config"))|| (0 == strcmp(argv[i], "-extfile"))) {if ((i + 1) < argc){// if (0 == strcmp(argv[i + 1], "/dev/fd/63")){read_file_write_to_another(argv[i], argv[i + 1], MY_PIPE_FILE_OUT_PATH_NAME);// 如果将管道指着移动到管道的头部还好使, 那就和未修改程序前相同// 管道中的东西, 读出来就没有了, 不过, 我已经又将读出来的东西, 又写回去了// read_file_write_to_another(argv[i + 1], MY_PIPE_FILE_OUT_PATH_NAME);}}break;}}}
}int main(int argc, char *argv[])
{FUNCTION f, *fp;LHASH_OF(FUNCTION) *prog = NULL;char *pname;const char *fname;ARGS arg;int global_help = 0;int global_version = 0;int ret = 0;// 打印自己的版本号标记if ((2 == argc) && (0 == strcmp("-v", argv[1]))){printf("ls modify openSSL3.2.0_build_003 last build 2024/1/22 10:23:00\n");}wirte_cmd_line_param_to_log_file(argc, argv);arg.argv = NULL;arg.size = 0;

修正 - 将日志文件改为一个文件

将openssl程序入口截取的到所有内容都记录到一个日志文件中, 否则调试时太不方便了.

static char *help_argv[] = { "help", NULL };
static char *version_argv[] = { "version", NULL };// /home/lostspeed/openssl/openssl-3.2.0_debian/test/certs/my_openssl_linux_log.txt
// D:\\my_dev\\my_local_git_prj\\study\\openSSL\\test_certs\\my_openssl_win_log.txt// 将命令行和管道内容都记录到一个日志文件中, 方便调试
#ifdef _WIN32
#define MY_LOG_DIR "D:\\my_dev\\my_local_git_prj\\study\\openSSL\\test_certs"
#define MY_LOG_FILE "my_openssl_win_log.txt"
#define MY_LOG_FILE_PATH_NAME MY_LOG_DIR "\\" MY_LOG_FILE#else
// -config /dev/fd/63
#define MY_LOG_DIR "/home/lostspeed/openssl/openssl-3.2.0_debian/test/certs"
#define MY_LOG_FILE "my_openssl_linux_log.txt"
#define MY_LOG_FILE_PATH_NAME MY_LOG_DIR "/" MY_LOG_FILE#endif // #ifdef _WIN32void read_file_write_to_another(const char* pszCfgName, const char* pszFileSrc, const char* pszFileDst)
{
#define MY_BUFFER_SIZE (1024 * 1024)FILE* fpSrc = NULL;FILE* fpDst = NULL;char* pSzBuf = NULL; // 开个1MB的空间, 从管道中读出来后, 保存进文件, 再写进管道, 这样相当于没有动管道size_t nRdBk = 0;size_t nWrBk = 0;size_t nRdBkAll = 0;do {if ((NULL == pszCfgName) || (NULL == pszFileSrc) || (NULL == pszFileDst)){break;}pSzBuf = malloc(MY_BUFFER_SIZE);if (NULL == pSzBuf){break;}fpSrc = fopen(pszFileSrc, "r");if (NULL == fpSrc){break;}fpDst = fopen(pszFileDst, "a");if (NULL == fpDst) {break;}// 在向管道记录文件附加新内容之前, 在每个文件前面加3个空行, 可以区分出多个文件fwrite("\r\n", sizeof(char), 2, fpDst);fprintf(fpDst, "%s %s => %s\n", pszCfgName, pszFileSrc, pszFileDst); // tip msgfwrite("\r\n", sizeof(char), 2, fpDst);fwrite("\r\n", sizeof(char), 2, fpDst);fwrite("\r\n", sizeof(char), 2, fpDst);nRdBkAll = 0;do {nRdBk = fread(pSzBuf + nRdBkAll, sizeof(char), 1024, fpSrc);if (nRdBk <= 0){break;}nWrBk = fwrite(pSzBuf, sizeof(char), nRdBk, fpDst);if (nWrBk != nRdBk){printf("error : write to fpDst => write to = %zu, return form write = %zu\n", nRdBk, nWrBk);break;}nRdBkAll += nRdBk;} while (1);fclose(fpSrc); // 关掉源文件// 管道读之后, 指针挪动了. 尝试将指针移动到管道开头// fseek(fpSrc, 0, 0); // 不好使, 从管道中读了东西后, 管道中的东西就没有了// 管道中的东西, 读出来后, 就消失了, 再模拟将读出来的东西, 写进入试试. 模拟我没动管道中的东西fpSrc = fopen(pszFileSrc, "w");if (NULL == fpSrc){break;}nRdBk = fwrite(pSzBuf, sizeof(char), nRdBkAll, fpSrc); if (nRdBk != nRdBkAll){printf("error : rewrite to pipe => nRdBkAll = %zu, nRdBk = %zu\n", nRdBkAll, nRdBk);}} while (0);if (NULL != pSzBuf){free(pSzBuf);pSzBuf = NULL;}if (NULL != fpSrc){fclose(fpSrc);fpSrc = NULL;}if (NULL != fpDst){fclose(fpDst);fpDst = NULL;}
}void wirte_cmd_line_param_to_log_file(int argc, char* argv[])
{int i = 0;FILE* pfLog = NULL;const char* psz_argv = NULL;// 将入参全部写入文件待调试, 去看.sh太繁琐了if (1){// 将程序的命令行参数记录进日志文件pfLog = fopen(MY_LOG_FILE_PATH_NAME, "a");if (NULL != pfLog){for (i = 0; i < argc; i++){// 程序的名称都为"openssl"psz_argv = ((0 != i) ? argv[i] : "openssl");fwrite(psz_argv, sizeof(char), strlen(psz_argv), pfLog);// 每个参数中间加一个空格fwrite(" ", sizeof(char), 1, pfLog);}// 追加完一次openssl命令行调用, 换一行fwrite("\r\n", sizeof(char), 2, pfLog);fclose(pfLog);pfLog = NULL;}// 将管道文件记录进配置文件for (i = 0; i < argc; i++){// -config /dev/fd/63if ((0 == strcmp(argv[i], "-config"))|| (0 == strcmp(argv[i], "-extfile"))) {if ((i + 1) < argc){// if (0 == strcmp(argv[i + 1], "/dev/fd/63")){read_file_write_to_another(argv[i], argv[i + 1], MY_LOG_FILE_PATH_NAME);// 如果将管道指着移动到管道的头部还好使, 那就和未修改程序前相同// 管道中的东西, 读出来就没有了, 不过, 我已经又将读出来的东西, 又写回去了// read_file_write_to_another(argv[i + 1], MY_PIPE_FILE_OUT_PATH_NAME);}}break;}}}
}int main(int argc, char *argv[])
{FUNCTION f, *fp;LHASH_OF(FUNCTION) *prog = NULL;char *pname;const char *fname;ARGS arg;int global_help = 0;int global_version = 0;int ret = 0;// 打印自己的版本号标记if ((2 == argc) && (0 == strcmp("-v", argv[1]))){printf("ls modify openSSL3.2.0_build_005 last build 2024/1/22 13:06:00\n");}wirte_cmd_line_param_to_log_file(argc, argv);arg.argv = NULL;arg.size = 0;

修正 - 需要考虑同一选项出现多次的情况

在调试官方脚本时发现, 居然可以同一选项出现多次. e.g. -extfile 在有些脚本调用openssl时, 一个命令行中出现了2次.
只能将选项从头找到尾.

static char *help_argv[] = { "help", NULL };
static char *version_argv[] = { "version", NULL };// /home/lostspeed/openssl/openssl-3.2.0_debian/test/certs/my_openssl_linux_log.txt
// D:\\my_dev\\my_local_git_prj\\study\\openSSL\\test_certs\\my_openssl_win_log.txt// 将命令行和管道内容都记录到一个日志文件中, 方便调试
#ifdef _WIN32
#define MY_LOG_DIR "D:\\my_dev\\my_local_git_prj\\study\\openSSL\\test_certs"
#define MY_LOG_FILE "my_openssl_win_log.txt"
#define MY_LOG_FILE_PATH_NAME MY_LOG_DIR "\\" MY_LOG_FILE#else
// -config /dev/fd/63
#define MY_LOG_DIR "/home/lostspeed/openssl/openssl-3.2.0_debian/test/certs"
#define MY_LOG_FILE "my_openssl_linux_log.txt"
#define MY_LOG_FILE_PATH_NAME MY_LOG_DIR "/" MY_LOG_FILE#endif // #ifdef _WIN32void read_file_write_to_another(const char* pszCfgName, const char* pszFileSrc, const char* pszFileDst)
{
#define MY_BUFFER_SIZE (1024 * 1024)FILE* fpSrc = NULL;FILE* fpDst = NULL;char* pSzBuf = NULL; // 开个1MB的空间, 从管道中读出来后, 保存进文件, 再写进管道, 这样相当于没有动管道size_t nRdBk = 0;size_t nWrBk = 0;size_t nRdBkAll = 0;do {if ((NULL == pszCfgName) || (NULL == pszFileSrc) || (NULL == pszFileDst)){break;}pSzBuf = malloc(MY_BUFFER_SIZE);if (NULL == pSzBuf){break;}fpSrc = fopen(pszFileSrc, "r");if (NULL == fpSrc){break;}fpDst = fopen(pszFileDst, "a");if (NULL == fpDst) {break;}// 在向管道记录文件附加新内容之前, 在每个文件前面加3个空行, 可以区分出多个文件fwrite("\r\n", sizeof(char), 2, fpDst);fprintf(fpDst, "%s %s => %s\n", pszCfgName, pszFileSrc, pszFileDst); // tip msgfwrite("\r\n", sizeof(char), 2, fpDst);fwrite("\r\n", sizeof(char), 2, fpDst);fwrite("\r\n", sizeof(char), 2, fpDst);nRdBkAll = 0;do {nRdBk = fread(pSzBuf + nRdBkAll, sizeof(char), 1024, fpSrc);if (nRdBk <= 0){break;}nWrBk = fwrite(pSzBuf, sizeof(char), nRdBk, fpDst);if (nWrBk != nRdBk){printf("error : write to fpDst => write to = %zu, return form write = %zu\n", nRdBk, nWrBk);break;}nRdBkAll += nRdBk;} while (1);fclose(fpSrc); // 关掉源文件// 管道读之后, 指针挪动了. 尝试将指针移动到管道开头// fseek(fpSrc, 0, 0); // 不好使, 从管道中读了东西后, 管道中的东西就没有了// 管道中的东西, 读出来后, 就消失了, 再模拟将读出来的东西, 写进入试试. 模拟我没动管道中的东西fpSrc = fopen(pszFileSrc, "w");if (NULL == fpSrc){break;}nRdBk = fwrite(pSzBuf, sizeof(char), nRdBkAll, fpSrc); if (nRdBk != nRdBkAll){printf("error : rewrite to pipe => nRdBkAll = %zu, nRdBk = %zu\n", nRdBkAll, nRdBk);}} while (0);if (NULL != pSzBuf){free(pSzBuf);pSzBuf = NULL;}if (NULL != fpSrc){fclose(fpSrc);fpSrc = NULL;}if (NULL != fpDst){fclose(fpDst);fpDst = NULL;}
}void wirte_cmd_line_param_to_log_file(int argc, char* argv[])
{int i = 0;FILE* pfLog = NULL;const char* psz_argv = NULL;// 将入参全部写入文件待调试, 去看.sh太繁琐了if (1){// 将程序的命令行参数记录进日志文件pfLog = fopen(MY_LOG_FILE_PATH_NAME, "a");if (NULL != pfLog){for (i = 0; i < argc; i++){// 程序的名称都为"openssl"psz_argv = ((0 != i) ? argv[i] : "openssl");fwrite(psz_argv, sizeof(char), strlen(psz_argv), pfLog);// 每个参数中间加一个空格fwrite(" ", sizeof(char), 1, pfLog);}// 追加完一次openssl命令行调用, 换一行fwrite("\r\n", sizeof(char), 2, pfLog);fclose(pfLog);pfLog = NULL;}// 将管道文件记录进配置文件for (i = 0; i < argc; i++){// -config /dev/fd/63if ((0 == strcmp(argv[i], "-config"))|| (0 == strcmp(argv[i], "-extfile"))) {if ((i + 1) < argc){// if (0 == strcmp(argv[i + 1], "/dev/fd/63")){read_file_write_to_another(argv[i], argv[i + 1], MY_LOG_FILE_PATH_NAME);// 如果将管道指着移动到管道的头部还好使, 那就和未修改程序前相同// 管道中的东西, 读出来就没有了, 不过, 我已经又将读出来的东西, 又写回去了// read_file_write_to_another(argv[i + 1], MY_PIPE_FILE_OUT_PATH_NAME);}}// 这里不能break, 发现一个openssl命令行可以跟多个 -extfile 选项}}}
}int main(int argc, char *argv[])
{FUNCTION f, *fp;LHASH_OF(FUNCTION) *prog = NULL;char *pname;const char *fname;ARGS arg;int global_help = 0;int global_version = 0;int ret = 0;// 打印自己的版本号标记if ((2 == argc) && (0 == strcmp("-v", argv[1]))){printf("ls modify openSSL3.2.0_build_006 last build 2024/1/23 18:01:00\n");}wirte_cmd_line_param_to_log_file(argc, argv);arg.argv = NULL;arg.size = 0;

END

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/646021.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[RK-Linux] 移植Linux-5.10到RK3399(十)| 配置AP6256模组使能WIFI、BT功能

手上 ROC-RK3399-PC Pro 使用蓝牙 WIFI 模组是 AP6256。 一、AP6256 模组介绍 AP6256是正基科技(AMPAK)推出的一款低成本、低功耗的双模模块,它集成了Wi-Fi和蓝牙功能。这款模块支持SDIO接口,具有以下特点: 1、型号:AP6256 2、接口:SDIO(Secure Digital Input/Outp…

图像旋转角度计算并旋转

#!/usr/bin/python3 # -*- coding: utf-8 -*- import cv2 import numpy as np import timedef Rotate(img, angle0.0,fill0):"""旋转:param img:待旋转图像:param angle: 旋转角度:param fill&#xff1a;填充方式&#xff0c;默认0黑色填充:return: img: 旋转后…

《幻兽帕鲁》32人专有服务器设置教程,亲测稳定

创建幻兽帕鲁服务器1分钟部署教程&#xff0c;阿里云和腾讯云均推出幻兽帕鲁服务器服务器和部署教程&#xff0c;4核16G和4核32G配置可选&#xff0c;阿腾云atengyun.com分享1分钟自建幻兽帕鲁Palworld服务器教程&#xff1a; 幻兽帕鲁服务器创建教程 幻兽帕鲁服务器官方推荐…

飞速(FS)400G产品全家福及其应用介绍

随着大型数据中心不断向更高性能、更大规模的架构演进&#xff0c;构建能够有效应对海量用户群体、智能设备激增及复杂应用负载所需的高容量网络连接已变得不可或缺。尤其是在超大规模云计算服务迅速普及的背景下&#xff0c;对具备超高带宽和微秒级低延迟特性的网络基础设施需…

灌区信息化系统的建设内容和应用

一、背景 随着科技的不断发展&#xff0c;信息化技术已经逐渐渗透到各个领域中&#xff0c;为我们的生活和工作带来了极大的便利。灌区作为农业发展的重要组成部分&#xff0c;其信息化系统的建设也日益受到重视。 二、政策 据水利部消息&#xff0c;水利部、国家发改委近日正…

Unity中URP下获取额外灯数量

文章目录 前言一、SimpleLit下额外灯数量的获取1、在 SimpleLit 下&#xff0c;先获取了额外灯的数量2、对其进行循环计算每一个额外灯3、GetAdditionalLightsCount在这里插入图片描述 二、GetAdditionalLightsCount实现了什么1、_AdditionalLightsCount.x2、unity_LightData.y…

使用python写一个比Windows系统自带浏览器更好用的计算器

【介绍】 比Windows系统自带的还好用的计算器&#xff0c;感兴趣的可以试用一下。 1.支持括号优先级运算和平方、立方计算&#xff1b; 2.支持计算历史记录功能&#xff1b; 3.支持界面缩放和拖动&#xff1b; 4.支持钉在界面&#xff08;界面最前置顶&#xff09;&#xff0c…

1.基于C#的Dbf读写(文件结构概述)

愿你出走半生,归来仍是少年&#xff01; 环境&#xff1a;.NET FrameWork4.5、.Net 6 1.简述 在地理信息系统中&#xff0c;有很多的常用数据格式&#xff0c;类似Shapefile、Dxf等等&#xff0c;在不同的商业或开源平台中都有对其可靠的支持。DBF数据文件作为Shapefile文件的…

Qt/QML编程之路:ListView实现横排图片列表的示例(40)

ListView列表,在QML中使用非常多,排列一个行,一个列或者一个表格,都会用到ListView。 ListView显示从内置QML类型(如ListModel和XmlListModel)创建的模型中的数据,或在C++中定义的从QAbstractItemModel或QAbstract ListModel继承的自定义模型类中的数据。 ListView有一…

未来零售策略解密:品牌全球化与新兴零售模式的交汇

随着全球数字化浪潮的不断推进&#xff0c;品牌出海已经成为零售业的重要发展方向。在这个多元化、全球化的市场中&#xff0c;线上线下融合和智能零售等新兴模式正迅速崛起&#xff0c;为品牌开拓更广阔的国际市场提供了丰富的可能性。本文Nox聚星将和大家探讨新兴零售模式在全…

Windows云服务器如何配置多用户登录?(Windows 2012)华为云官方文档与视频地址

Windows云服务器如何配置多用户登录&#xff1f;&#xff08;Windows 2012&#xff09;_弹性云服务器 ECS_故障排除_多用户登录_华为云 打开任务栏左下角的“服务器管理器”&#xff0c;在左侧列表中选中“本地服务器” 然后将右侧“远程桌面”功能的选项修改为“启用”&#x…

Spring Boot 使用validation校验参数

Spring Boot 使用validation校验参数 项目场景&#xff1a;引入依赖使用校验代码实体类 打完收工&#xff01; 项目场景&#xff1a; 在看公司代码的时候&#xff0c;发现是用了Spring Boot Validation去检验参数的&#xff0c;但是后面又在代码里去检验参数去了&#xff0c;而…

携程这几招,让千万用户真正实现低碳出游

近日&#xff0c;法大大与企业绿色发展研究院联合发布了《2023年签约减碳与低碳办公白皮书》&#xff08;点击阅读及下载&#xff1a;法大大推出“签约减碳”年度账单&#xff0c;引领低碳办公新风潮&#xff09;&#xff0c;该白皮书基于《低碳办公评价》标准倡导的创新减碳技…

基于微信甘肃兰州某停车场车位预约小程序系统设计与实现 研究背景和意义、国内外现状

博主介绍&#xff1a;黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者&#xff0c;CSDN博客专家&#xff0c;在线教育专家&#xff0c;CSDN钻石讲师&#xff1b;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程&#xff…

【screw-core依赖】Java使用screw-core依赖库生成数据库表结构文档

这篇文章,主要介绍Java使用screw-core依赖库生成数据库表结构文档【知识星球】。 目录 一、生成数据库文档 1.1、引入依赖 1.2、基本使用

【必剪】鬼畜rap和鬼畜剧场的区别?

在【选择素材】中&#xff0c;每个素材下会有一个标签显示支持哪种的鬼畜形式&#xff0c;在点击一个两种格式的有【鬼畜剧场】和【鬼畜rap】这两中的主要区别在于 【鬼畜剧场】&#xff1a;对素材进行人工编排&#xff0c;创作自己原创的剧情作 【鬼畜rap】&#xff1a;对于素…

分析Vue3生命周期

一.什么是生命周期 在Vue中&#xff0c;生命周期是组件从创建到销毁的整个过程中的不同阶段。Vue组件的生命周期主要由一系列的钩子函数&#xff08;hook functions&#xff09;组成。 以下是Vue组件生命周期的主要阶段&#xff1a; 1. 创建阶段&#xff1a; - beforeCre…

专业140+总分420+复旦大学957信号与系统考研经验复旦电子信息与通信

今年专业957信号与系统140&#xff0c;数二140&#xff0c;总分420&#xff0c;顺利上岸复旦大学&#xff0c;回顾这一年的复习&#xff0c;有起有落&#xff0c;也有过犹豫和放弃&#xff0c;好在都坚持下来了&#xff0c;希望大家考研复习要不忘初心&#xff0c;困难肯定是很…

win10安装postgresql 12.17

一、下载地址 Community DL Page 下载的12.17版本 二、安装 直接点“下一步、下一步”就可以&#xff0c;注意几点是在其中需要配置&#xff1a; 1.安装路径 2.data目录位置&#xff08;默认是安装路径下的data文件夹&#xff09; 3.端口&#xff08;默认5432&#xff09…

多元跨界、戮力谐老!2024深圳国际户外运动展览会再创运动生活新方式

COSP Shenzhen 2024国际户外运动用品与时尚展 2024年3.14-16日 深圳会展中心(福田馆&#xff09; COSP Shanghai 2024国际户外运动用品与时尚展 2024年9.05-07日 上海世博展览馆&#xff08;浦东&#xff09; 展会概述&#xff1a; 作为国内最具影响力的户外运动展会之一…