打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
BOA代码笔记 2

boa.c 续

书接上回。
main函数的调用到了 fixup_server_root()
  1. static void fixup_server_root()  
  2. {  
  3.     char *dirbuf;  
  4.   
  5.     if (!server_root) {  
  6. #ifdef SERVER_ROOT  
  7.         server_root = strdup(SERVER_ROOT);  
  8.         if (!server_root) {  
  9.             perror("strdup (SERVER_ROOT)");  
  10.             exit(1);  
  11.         }  
  12. #else  
  13.         fputs("boa: don't know where server root is.  Please #define "  
  14.               "SERVER_ROOT in boa.h\n"  
  15.               "and recompile, or use the -c command line option to "  
  16.               "specify it.\n", stderr);  
  17.         exit(1);  
  18. #endif  
  19.     }  
  20.   
  21.     if (chdir(server_root) == -1) {  
  22.         fprintf(stderr, "Could not chdir to \"%s\": aborting\n",  
  23.                 server_root);  
  24.         exit(1);  
  25.     }  
  26.   
  27.     dirbuf = normalize_path(server_root);  
  28.     free(server_root);  
  29.     server_root = dirbuf;  
  30. }  
该函数的功能主要是由程序运行时的选项和defines.h里的宏定义确定server_root。
如果参数没有指定server_root,那么就由宏指定,如果宏没指定,就报错。

该函数最后调用的normalize_path(),定义在util.c里。功能是,如果给出的是绝对路径,不转化。如果是相对路径转化为绝对路径。
该函数不贴了,用到了getcwd()
       #include <unistd.h>
       char *getcwd(char *buf, size_t size);
       char *getwd(char *buf);
getcwd函数返回当前程序的工作目录。因此,如果相对路径不是"."的话,还需要将两个字符串连接起来。细节上的处理大家有兴趣的话可以看一下。

 fixup_server_root()调用完毕,程序运行到这儿,应该已经有了规范的工作目录了。


main函数继续执行到read_config_files();
程序的注释说,Description: Reads config files via yyparse, then makes sure that  all required variables were set properly.
这个函数解析配置文件,保证所有的全局变量正确初始化。
  1. void read_config_files(void)  
  2. {  
  3.     char *temp;  
  4.     current_uid = getuid();  
  5.     yyin = fopen("boa.conf""r");  
  6.   
  7.     if (!yyin) {  
  8.         fputs("Could not open boa.conf for reading.\n", stderr);  
  9.         exit(1);  
  10.     }  
  11.     if (yyparse()) {  
  12.         fputs("Error parsing config files, exiting\n", stderr);  
  13.         exit(1);  
  14.     }  
  15.   
  16.     if (!server_name) {  
  17.         struct hostent *he;  
  18.         char temp_name[100];  
  19.   
  20.         if (gethostname(temp_name, 100) == -1) {  
  21.             perror("gethostname:");  
  22.             exit(1);  
  23.         }  
  24.   
  25.         he = gethostbyname(temp_name);  
  26.         if (he == NULL) {  
  27.             perror("gethostbyname:");  
  28.             exit(1);  
  29.         }  
  30.   
  31.         server_name = strdup(he->h_name);  
  32.         if (server_name == NULL) {  
  33.             perror("strdup:");  
  34.             exit(1);  
  35.         }  
  36.     }  
  37.     tempdir = getenv("TMP");  
  38.     if (tempdir == NULL)  
  39.         tempdir = "/tmp";  
  40.   
  41.     if (single_post_limit < 0) {  
  42.         fprintf(stderr, "Invalid value for single_post_limit: %d\n",  
  43.                 single_post_limit);  
  44.         exit(1);  
  45.     }  
  46.   
  47.     if (document_root) {  
  48.         temp = normalize_path(document_root);  
  49.         free(document_root);  
  50.         document_root = temp;  
  51.     }  
  52.   
  53.     if (error_log_name) {  
  54.         temp = normalize_path(error_log_name);  
  55.         free(error_log_name);  
  56.         error_log_name = temp;  
  57.     }  
  58.   
  59.     if (access_log_name) {  
  60.         temp = normalize_path(access_log_name);  
  61.         free(access_log_name);  
  62.         access_log_name = temp;  
  63.     }  
  64.   
  65.     if (cgi_log_name) {  
  66.         temp = normalize_path(cgi_log_name);  
  67.         free(cgi_log_name);  
  68.         cgi_log_name = temp;  
  69.     }  
  70.   
  71.     if (dirmaker) {  
  72.         temp = normalize_path(dirmaker);  
  73.         free(dirmaker);  
  74.         dirmaker = temp;  
  75.     }  
  76.   
  77. #if 0  
  78.     if (mime_types) {  
  79.         temp = normalize_path(mime_types);  
  80.         free(mime_types);  
  81.         mime_types = temp;  
  82.     }  
  83. #endif  
  84. }  
首先打开boa.conf文件,yyin被赋值。然后就可以调用yyparse()进行解析了。
关于flex和bison学习,推荐oreilly的flex&bison。

现在把bison和flex部分研究一下吧

boa_grammar.y

  1. %{  
  2. #include <string.h>  
  3. #include <stdio.h>  
  4. #include <stdlib.h>  
  5. #include <unistd.h>  
  6. /* #include "boa.h" */  
  7. #include "parse.h"  
  8. # yyerror的实现在boa_lexer.l里  
  9. int yyerror(char * msg);  
  10.   
  11. /* yydebug = 1; */  
  12.   
  13. #ifdef DEBUG  
  14. #define DBG(x) x  
  15. #else  
  16. #define DBG(x)  
  17. #endif  
  18. # 之后可以看到arg1hold用于临时保存TOKEN的参数内容,mime_type也是临时用于存储mime的名。  
  19. char *arg1hold;  
  20. char mime_type[256];            /* global to inherit */  
  21.   
  22. %}  
  23.   
  24. %union {  
  25.     char *  sval;  
  26.     int     ival;  
  27.     struct ccommand * cval;  
  28. };  
  29.   
  30. /* boa.conf tokens */  
  31. %token <cval> STMT_NO_ARGS STMT_ONE_ARG STMT_TWO_ARGS  
  32.   
  33. /* mime.type tokens */  
  34. %token <sval> MIMETYPE  
  35. %token <sval> STRING  
  36. %token <ival> INTEGER  
  37.   
  38. %start ConfigFiles  
  39.   
  40. %%  
  41.   
  42. ConfigFiles:        BoaConfigStmts MimeTypeStmts  
  43.     ;  
  44.   
  45. BoaConfigStmts:     BoaConfigStmts BoaConfigStmt  
  46.     |       /* empty */  
  47.     ;  
  48.   
  49. BoaConfigStmt:        
  50.             StmtNoArgs  
  51.     |       StmtOneArg  
  52.     |       StmtTwoArgs  
  53.     ;  
  54.   
  55. StmtNoArgs:     STMT_NO_ARGS  
  56.         { if ($1->action) {  
  57.             DBG(printf("StmtNoArgs: %s\n",$1->name);)  
  58.             $1->action(NULL,NULL,$1->object);  
  59.          }  
  60.         }  
  61.     ;  
  62.   
  63. StmtOneArg:     STMT_ONE_ARG STRING  
  64.         { if ($1->action) {  
  65.             DBG(printf("StmtOneArg: %s %s\n",$1->name,$2);)  
  66.             $1->action($2,NULL,$1->object);  
  67.          }  
  68.         }  
  69.     ;  
  70.   
  71. StmtTwoArgs:        STMT_TWO_ARGS STRING  
  72.         { arg1hold = strdup($2); }  
  73.              STRING  
  74.         { if ($1->action) {  
  75.             DBG(printf("StmtTwoArgs: '%s' '%s' '%s'\n",  
  76.                         $1->name,arg1hold,$4);)  
  77.             $1->action($4,arg1hold,$1->object);  
  78.           }  
  79.           free(arg1hold);  
  80.         }  
  81.     ;  
  82.   
  83.   
  84. /******************* mime.types **********************/  
  85.   
  86. MimeTypeStmts:      MimeTypeStmts MimeTypeStmt  
  87.     |       /* empty */  
  88.     ;  
  89.   
  90. MimeTypeStmt:       MIMETYPE   
  91.         { strcpy(mime_type, $1); }  
  92.             ExtensionList  
  93.     ;  
  94.   
  95. ExtensionList:      ExtensionList Extension  
  96.     |       /* empty */  
  97.     ;  
  98.   
  99. Extension:      STRING  
  100.         { add_mime_type($1, mime_type); }  
  101.     ;  
  102.   
  103. %%  

先说说这个宏,DBG(x)
#ifdef DEBUG
#define DBG(x) x
#else
#define DBG(x)
#endif
学了一招!
up主之前用#define DEBUG,然后每一处需要调试时调用的函数前后加上#ifdef DEBUG ......  #endif的方法来达到同样效果,太累。
这里只要在需要调试的函数前后加上DBG()就行了。

将boa.conf文件和mime.types文件的语法规则写在一起,简单的先后关系:ConfigFiles: BoaConfigStmts MimeTypeStmts;

BoaConfigStmts
boa config stmt分三种,无参的,一个参数的,两个参数的。
实际的配置如下:
AccessLog   /var/log/boa/access_log
Alias   /doc   /usr/doc

词法分析得到一条stmt后,调用action函数进行操作。
每一个stmt是struct ccommand *类型,声明如下
struct ccommand{
    char *name;
    int type;
    void (*action) (char *, char *, void *);
    void *object;
};
所有的struct ccommand以数组方式存储
  1. struct ccommand clist[] = {  
  2.     {"Port", S1A, c_set_int, &server_port},    
  3.     ......  
  4.     {"CGIPath", S1A, c_set_string, &cgi_path},  
  5.     {"MaxConnections", S1A, c_set_int, &max_connections},  
  6. };  
词法分析yylex每次找到一个stmt就根据名字从这个数组中查找对应项返回给yyparse,再从yyparse中调用action,完成各自的初始化。

MimeTypeStmts
mimetype的形式类似于 MIMETYPE STRING STRING STRING...
每次解析到一个MIMETYPE,先暂时存储于mime_type字符数组。解析STRING时,就调用add_mime_type($1, mime_type);
这个函数的作用就是将type-extension添加到一个哈系表中,type为key,可以有很多extension,索引方式存储。

语法分析规则boa_grammar.y就到这儿,词法分析规则boa_lexer.l就不说了。
大体功能和yywrap()、yyerror()在前一篇已经提到,具体的词法规则就太细节了。


好了,回到我们的read_config_files(),大家不会忘了这个函数还没完呢吧?^ ^
其实也没什么了,把一些路径转化为绝对路径,host_name什么的验证一下,也就完了。
最后有个#if 0  ......   #endif
我是第一次到见这个用法,查了一下就是相当于多行注释。有的文章推荐这样用。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
boa资料汇总
boa服务器的移植
lighttpd+php(fastcgi) 移植到arm
last_insert_id()不可靠
NGINX conf 配置文件中的变量大全 可用变量列表及说明
说说Rails吧,启动开始。 - 差沙的密码 -- SSHWSFC‘s code - Bl...
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服