| #include "wsIntrn.h" |
| #include <sys/types.h> |
| #include <sys/wait.h> |
| #include "uemf.h" |
| |
| static int cgiMax; |
| typedef struct { |
| webs_t wp; |
| long fplacemark; |
| int handle; |
| char_t **envp; |
| char_t **argp; |
| char_t *cgiPath; |
| char_t *stdOut; |
| char_t *stdIn; |
| } cgiRec; |
| static cgiRec **cgiList; |
| |
| int websCgiProcess(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, |
| char_t *url, char_t *path, char_t* query) |
| { |
| |
| int n, envpsize, argpsize, pHandle, cid; |
| char_t *cp, *cgiName, *cgiPath, **argp, **envp, **ep; |
| char_t cgiBuf[FNAMESIZE], *stdIn, *stdOut, cwd[FNAMESIZE]; |
| sym_t *s; |
| cgiRec *cgip; |
| a_assert(path && *path == '/'); |
| a_assert(url && *url); |
| a_assert(websValid(wp)); |
| websStats.cgiHits++; |
| char *cgipath_temp = NULL; |
| gstrncpy(cgiBuf, path, TSZ(cgiBuf)-1); |
| cgipath_temp = gstrchr(&cgiBuf[1], '/'); |
| if(cgipath_temp!=NULL) |
| { |
| cgipath_temp++; |
| }else |
| { |
| websError(wp, 200, T("cgiBuf error,check path")); |
| |
| return 1; |
| } |
| printf("[goahead]cgipath_temp->%s.\n",cgipath_temp); |
| //if ((cgiName = gstrchr(&cgiBuf[1], '/')) == NULL) { |
| if ((cgiName = gstrchr(cgipath_temp, '/')) == NULL) { |
| |
| if((cgiName = gstrchr(&cgiBuf[1], '/')) == NULL) |
| { |
| websError(wp, 200, T("Missing CGI name")); |
| |
| return 1; |
| } |
| } |
| cgiName++; |
| printf("[goahead]cgiName->%s.\n",cgiName); |
| if ((cp = gstrchr(cgiName, '/')) != NULL) { |
| *cp = '\0'; |
| } |
| // fmtAlloc(&cgiPath, FNAMESIZE, T("%s/%s/%s"), websGetDefaultDir(), |
| // CGI_BIN, cgiName); |
| fmtAlloc(&cgiPath, FNAMESIZE, T("%s/%s"),"/sbin", cgiName); |
| { |
| gstat_t sbuf; |
| if (gstat(cgiPath, &sbuf) != 0 || (sbuf.st_mode & S_IFREG) == 0) { |
| system("rm -rf /tmp/firmware_tmp_file"); |
| websError(wp, 200, T("CGI process file does not exist")); |
| bfree(B_L, cgiPath); |
| return 1; |
| } |
| if (gaccess(cgiPath, X_OK) != 0) { |
| websError(wp, 200, T("CGI process file is not executable")); |
| bfree(B_L, cgiPath); |
| return 1; |
| } |
| } |
| ggetcwd(cwd, FNAMESIZE); |
| if ((cp = gstrrchr(cgiPath, '/')) != NULL) { |
| *cp = '\0'; |
| gchdir(cgiPath); |
| *cp = '/'; |
| } |
| argpsize = 10; |
| argp = balloc(B_L, argpsize * sizeof(char_t *)); |
| if(argp == NULL){ |
| bfreeSafe(B_L, cgiPath); |
| return 1; |
| } |
| *argp = cgiPath; |
| n = 1; |
| if (gstrchr(query, '=') == NULL) { |
| websDecodeUrl(query, query, gstrlen(query)); |
| for (cp = gstrtok(query, T(" ")); cp != NULL; ) { |
| *(argp+n) = cp; |
| n++; |
| if (n >= argpsize) { |
| argpsize *= 2; |
| argp = brealloc(B_L, argp, argpsize * sizeof(char_t *)); |
| if(argp == NULL){ |
| bfreeSafe(B_L, cgiPath); |
| return 1; |
| } |
| } |
| cp = gstrtok(NULL, T(" ")); |
| } |
| } |
| *(argp+n) = NULL; |
| envpsize = WEBS_SYM_INIT; |
| envp = balloc(B_L, envpsize * sizeof(char_t *)); |
| if(envp == NULL){ |
| bfreeSafe(B_L, cgiPath); |
| bfreeSafe(B_L, argp); |
| return 1; |
| } |
| n = 0; |
| fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("PATH_TRANSLATED"), cgiPath); |
| n++; |
| fmtAlloc(envp+n, FNAMESIZE, T("%s=%s/%s"),T("SCRIPT_NAME"), |
| CGI_BIN, cgiName); |
| n++; |
| fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("REMOTE_USER"), wp->userName); |
| n++; |
| fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("AUTH_TYPE"), wp->authType); |
| n++; |
| for (s = symFirst(wp->cgiVars); s != NULL; s = symNext(wp->cgiVars)) { |
| if (s->content.valid && s->content.type == string && |
| gstrcmp(s->name.value.string, T("REMOTE_HOST")) != 0 && |
| gstrcmp(s->name.value.string, T("HTTP_AUTHORIZATION")) != 0) { |
| fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"), s->name.value.string, |
| s->content.value.string); |
| n++; |
| if (n >= envpsize) { |
| envpsize *= 2; |
| envp = brealloc(B_L, envp, envpsize * sizeof(char_t *)); |
| if(envp == NULL){ |
| bfreeSafe(B_L, cgiPath); |
| bfreeSafe(B_L, argp); |
| return 1; |
| } |
| } |
| } |
| } |
| if (wp->flags & WEBS_CGI_UPLOAD) |
| { |
| |
| if((wp->has_firmware_upload_clean)||(wp->flags & WEBS_CGI_FIRMWARE_UPLOAD)) |
| { |
| fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"), T("UPLOAD_FILENAME"), FIRMWARE_TMP_FILE); |
| } |
| else |
| { |
| fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"), T("UPLOAD_FILENAME"), wp->cgiStdin); |
| } |
| n++; |
| } |
| *(envp+n) = NULL; |
| if (wp->cgiStdin == NULL) { |
| wp->cgiStdin = websGetCgiCommName(wp); |
| } |
| stdIn = wp->cgiStdin; |
| stdOut = websGetCgiCommName(wp); |
| printf("[goahead]cgiPath->%s.\n",cgiPath); |
| |
| if ((pHandle = websLaunchCgiProc(cgiPath, argp, envp, stdIn, stdOut)) |
| == -1) { |
| system("rm -rf /tmp/firmware_tmp_file"); |
| websError(wp, 200, T("failed to spawn CGI task")); |
| for (ep = envp; *ep != NULL; ep++) { |
| bfreeSafe(B_L, *ep); |
| } |
| bfreeSafe(B_L, cgiPath); |
| bfreeSafe(B_L, argp); |
| bfreeSafe(B_L, envp); |
| bfreeSafe(B_L, stdOut); |
| } else { |
| cid = hAllocEntry((void***) &cgiList, &cgiMax, sizeof(cgiRec)); |
| if(cgiList){ |
| cgip = cgiList[cid]; |
| cgip->handle = pHandle; |
| cgip->stdIn = stdIn; |
| cgip->stdOut = stdOut; |
| cgip->cgiPath = cgiPath; |
| cgip->argp = argp; |
| cgip->envp = envp; |
| cgip->wp = wp; |
| cgip->fplacemark = 0; |
| websTimeoutCancel(wp); |
| } |
| else |
| { |
| bfreeSafe(B_L, cgiPath); |
| bfreeSafe(B_L, argp); |
| bfreeSafe(B_L, envp); |
| bfreeSafe(B_L, stdOut); |
| } |
| } |
| gchdir(cwd); |
| return 1; |
| |
| } |
| |
| int websCgiHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, |
| char_t *url, char_t *path, char_t* query) |
| { |
| if(!(wp->flags & WEBS_POST_REQUEST)) |
| { |
| //websError(wp, 200, T("NOT POST REQUEST")); |
| printf("[goahead]NOT POST REQUEST.\n"); |
| websDone(wp, 0); |
| return 1; |
| } |
| |
| if (wp->flags & WEBS_CGI_HTTPSHARE_UPLOAD) |
| { |
| printf("[httpshare]call zte_process_cgi_end.\n"); |
| return zte_process_cgi_end(wp); |
| }else if(wp->flags & WEBS_CGI_UPLOAD) |
| { |
| printf("[goahead]call upload cgi.\n"); |
| return websCgiProcess(wp, urlPrefix, webDir, arg,url, path, query); |
| }else |
| { |
| //websError(wp, 200, T("NOT CGI OR HTTPSHARE,RETURN ERROR")); |
| printf("[goahead]wrong cgi request.\n"); |
| websDone(wp, 0); |
| return 1; |
| } |
| |
| } |
| |
| void websCgiGatherOutput (cgiRec *cgip) |
| { |
| gstat_t sbuf; |
| char_t cgiBuf[FNAMESIZE]; |
| if ((gstat(cgip->stdOut, &sbuf) == 0) && |
| (sbuf.st_size > cgip->fplacemark)) { |
| int fdout; |
| fdout = gopen(cgip->stdOut, O_RDONLY | O_BINARY, 0444 ); |
| if (fdout >= 0) { |
| webs_t wp = cgip->wp; |
| int nRead; |
| int rc; |
| if (cgip->fplacemark == 0) { |
| websWrite(wp, T("HTTP/1.0 200 OK\n")); |
| } |
| if(glseek(fdout, cgip->fplacemark, SEEK_SET) < 0) |
| { |
| printf("[goahead]glseek fail.\n"); |
| } |
| while ((nRead = gread(fdout, cgiBuf, FNAMESIZE)) > 0) { |
| rc = websWriteBlock(wp, cgiBuf, nRead); |
| if (rc < 0) { |
| //todo: cov m |
| } |
| cgip->fplacemark += nRead; |
| } |
| gclose(fdout); |
| } |
| } |
| } |
| |
| void websCgiCleanup() |
| { |
| cgiRec *cgip; |
| webs_t wp; |
| char_t **ep; |
| int cid, nTries; |
| for (cid = 0; cid < cgiMax; cid++) { |
| if ((cgip = cgiList[cid]) != NULL) { |
| int exit_status; |
| wp = cgip->wp; |
| websCgiGatherOutput (cgip); |
| if ( websCheckCgiProc(cgip->handle, &exit_status) == 0) { |
| nTries = 0; |
| while ((cgip->fplacemark == 0) && (nTries < 100)) { |
| websCgiGatherOutput(cgip); |
| if (cgip->fplacemark == 0) { |
| } |
| nTries++; |
| } |
| gunlink(cgip->stdIn); |
| gunlink(cgip->stdOut); |
| cgiMax = hFree((void***) &cgiList, cid); |
| for (ep = cgip->envp; ep != NULL && *ep != NULL; ep++) { |
| bfreeSafe(B_L, *ep); |
| } |
| bfreeSafe(B_L, cgip->cgiPath); |
| bfreeSafe(B_L, cgip->argp); |
| bfreeSafe(B_L, cgip->envp); |
| bfreeSafe(B_L, cgip->stdOut); |
| bfreeSafe(B_L, cgip); |
| if(wp->has_firmware_upload_clean){ |
| if (WIFEXITED(exit_status) && WEXITSTATUS(exit_status) != 0) { |
| if (cgip->fplacemark == 0) { //cov h |
| websError(wp, 200, T("CGI generated no output")); |
| } else { |
| websDone(wp, 200); |
| } |
| return; |
| } |
| sync(); |
| //doSystem("sleep 3 && reboot &"); |
| } |
| if (cgip->fplacemark == 0) { //cov h |
| websError(wp, 200, T("CGI generated no output")); |
| } else { |
| websDone(wp, 200); |
| } |
| } |
| } |
| } |
| } |
| |