最后更新于 .

这几天在做的一个系统中,需要给指定的用户发送email,由于对方只提供了可执行程序,所以需要在CGI中调用。

虽然之前就知道可以通过system()或者popen()来实现,但是在真正用在CGI场景中的时候还是吃了不少苦头。

先来看一下system(),函数声明如下:

int system(const char *command);

入参就是需要执行的命令,函数会返回成功或者失败。
这个函数有两个问题:
1.函数调用的时候会fork进程,对于有些webserver是禁止fork的。(我一开始在CGI调用全是返回-1,即fork失败)
2.命令执行时,如果有向标准输出打印,不会被重定向。即,在CGI中使用的杯具就是,会直接将打印信息返回给浏览器

对于第二条,假设我直接将输出重定向的结果会怎样呢,比如执行命令"ps -ef > x",实际上,在apache中执行的话,apache还是一样能拿到输出。由于我是在http header之前输出,所以报了这样的错误。

1
目前我的解决办法是用popen,函数声明如下:

FILE *popen(const char *command, const char *type);

用popen("mailsend dantezhu"),命令内部的输出就会被重定向。
由于对于发送email这个命令本身我是不关心其成功与否的,所以并没有对其返回值做任何检查。


另外还有一点比较让人困惑,在apache下,我用CGI直接输出301跳转是会失败的,出错信息如下:

2

原来的输出方式是:

#define MMANCGI_REDIRECT(ret)          
{                                                       
 char url[100];          
 if(ret)            
  snprintf(url,sizeof(url),"http://mman.qq.com/mman_error.html?ret=%d",ret);        
 else            
  snprintf(url,sizeof(url),"http://mman.qq.com/mman_succ.html");      
printf("HTTP/1.1 301 Moved Permanently\r\n");       
printf("Connection: close\r\n");                    
printf("Content-Type: text/html\r\n");              
printf("Location: %s\r\n\r\n", url);          
 return ret;           
};

后来改成:

int Output(ret)
{
    char url[100];
    if(ret)
  snprintf(url,sizeof(url),"http://mman.qq.com/mman_error.html?ret=%d",ret);
    else
  snprintf(url,sizeof(url),"http://mman.qq.com/mman_succ.html");
    PrintHttpHeader();
    cout <<
    "<script type=\"text/javascript\">document.domain=\"mman.qq.com\";location=\"" <<  url   << "\";</script>";
    return ret;
};


就没有问题了,应该是apache对支持301跳转需要额外的模块,由于任务在身,所以也就没有时间深究了。

OK,就这样吧~

Pingbacks

Pingbacks已打开。

Trackbacks

引用地址

评论

  1. 依云

    依云 on #

    那个 301,不需要前面的 HTTP/1.1 的,直接 301 (message)。

    另外,使用 HTML 的 meta 标签也可以实现跳转。

    那个 system 重定向为什么不行呢?我在 linux 下的测试成功(ls &gt; b,错误日志显示 sh 尝试创建文件 b 被 Permission denied 了。

    Reply

    1. Dante

      Dante on #

      哦哦,我回公司试一下。

      那个创建文件禁止,会不会你的apache启动用户没有apache bin目录的写权限呢?

      Reply

      1. 依云

        依云 on #

        很明显我没有给它写权限。我的意思是,在Linux上在system里重定向是可行的。我很奇怪在Windows上为什么不行,难道Win下没有把命令交给cmd而是直接执行的?

        Reply

        1. Dante

          Dante on #

          我在win下面没测试过……,应该都是调用的外部命令吧,你不是不小心在win下面用ls吧……

          Reply

发表评论