📄 main.c
字号:
* will be the user entry point address, argp, envp, stdIn
* and stdOut. vxWebsCgiEntry will convert argp to an argc
* argv pair to pass to the user entry, it will initialize the
* task environment with envp, it will open and redirect stdin
* and stdout to stdIn and stdOut, and then it will call the
* user entry.
* 6. Return the taskSpawn return value.
*/
int websLaunchCgiProc(char_t *cgiPath, char_t **argp, char_t **envp,
char_t *stdIn, char_t *stdOut)
{
SYM_TYPE ptype;
char_t *p, *basename, *pEntry, *pname, *entryAddr, **pp;
int priority, rc, fd;
/*
* Determine the basename, which is without path or the extension.
*/
if ((int)(p = gstrrchr(cgiPath, '/') + 1) == 1) {
p = cgiPath;
}
basename = bstrdup(B_L, p);
if ((p = gstrrchr(basename, '.')) != NULL) {
*p = '\0';
}
/*
* Unload the module, if it is already loaded. Get the current task
* priority.
*/
unld(cgiPath, 0);
taskPriorityGet(taskIdSelf(), &priority);
rc = fd = -1;
/*
* Set the entry point symbol name as described above. Look for an already
* loaded entry point; if it exists, spawn the task accordingly.
*/
for (pp = envp, pEntry = NULL; pp != NULL && *pp != NULL; pp++) {
if (gstrncmp(*pp, T("cgientry="), 9) == 0) {
pEntry = bstrdup(B_L, *pp + 9);
break;
}
}
if (pEntry == NULL) {
fmtAlloc(&pEntry, LF_PATHSIZE, T("%s_%s"), basename, T("cgientry"));
}
entryAddr = 0;
if (symFindByName(sysSymTbl, pEntry, &entryAddr, &ptype) == -1) {
fmtAlloc(&pname, VALUE_MAX_STRING, T("_%s"), pEntry);
symFindByName(sysSymTbl, pname, &entryAddr, &ptype);
bfreeSafe(B_L, pname);
}
if (entryAddr != 0) {
rc = taskSpawn(pEntry, priority, 0, 20000, (void *)vxWebsCgiEntry,
(int)entryAddr, (int)argp, (int)envp, (int)stdIn, (int)stdOut,
0, 0, 0, 0, 0);
goto DONE;
}
/*
* Try to load the module.
*/
if ((fd = gopen(cgiPath, O_RDONLY | O_BINARY, 0666)) < 0 ||
loadModule(fd, LOAD_GLOBAL_SYMBOLS) == NULL) {
goto DONE;
}
if ((symFindByName(sysSymTbl, pEntry, &entryAddr, &ptype)) == -1) {
fmtAlloc(&pname, VALUE_MAX_STRING, T("_%s"), pEntry);
symFindByName(sysSymTbl, pname, &entryAddr, &ptype);
bfreeSafe(B_L, pname);
}
if (entryAddr != 0) {
rc = taskSpawn(pEntry, priority, 0, 20000, (void *)vxWebsCgiEntry,
(int)entryAddr, (int)argp, (int)envp, (int)stdIn, (int)stdOut,
0, 0, 0, 0, 0);
}
DONE:
if (fd != -1) {
gclose(fd);
}
bfree(B_L, basename);
bfree(B_L, pEntry);
return rc;
}
/******************************************************************************/
/*
* This is the CGI process wrapper. It will open and redirect stdin
* and stdout to stdIn and stdOut. It converts argv to an argc, argv
* pair to pass to the user entry. It initializes the task environment
* with envp strings. Then it will call the user entry.
*/
void vxWebsCgiEntry(void *entryAddr(int argc, char_t **argv),
char_t **argp, char_t **envp,
char_t *stdIn, char_t *stdOut)
{
char_t **p;
int argc, taskId, fdin, fdout;
/*
* Open the stdIn and stdOut files and redirect stdin and stdout
* to them.
*/
taskId = taskIdSelf();
if ((fdout = gopen(stdOut, O_RDWR | O_CREAT, 0666)) < 0 &&
(fdout = creat(stdOut, O_RDWR)) < 0) {
exit(0);
}
ioTaskStdSet(taskId, 1, fdout);
if ((fdin = gopen(stdIn, O_RDONLY | O_CREAT, 0666)) < 0 &&
(fdin = creat(stdIn, O_RDWR)) < 0) {
printf("content-type: text/html\n\n"
"Can not create CGI stdin to %s\n", stdIn);
gclose(fdout);
exit (0);
}
ioTaskStdSet(taskId, 0, fdin);
/*
* Count the number of entries in argv
*/
for (argc = 0, p = argp; p != NULL && *p != NULL; p++, argc++) {
}
/*
* Create a private envirnonment and copy the envp strings to it.
*/
if (envPrivateCreate(taskId, -1) != OK) {
printf("content-type: text/html\n\n"
"Can not create CGI environment space\n");
gclose(fdin);
gclose(fdout);
exit (0);
}
for (p = envp; p != NULL && *p != NULL; p++) {
putenv(*p);
}
/*
* Call the user entry.
*/
(*entryAddr)(argc, argp);
/*
* The user code should return here for cleanup.
*/
envPrivateDestroy(taskId);
gclose(fdin);
gclose(fdout);
exit(0);
}
/******************************************************************************/
/*
* Check the CGI process. Return 0 if it does not exist; non 0 if it does.
*/
int websCheckCgiProc(int handle)
{
STATUS stat;
/*
* Verify the existence of a VxWorks task
*/
stat = taskIdVerify(handle);
if (stat == OK) {
return 1;
} else {
return 0;
}
}
/******************************************************************************/
/*
* Default error handler. The developer should insert code to handle
* error messages in the desired manner.
*/
void defaultErrorHandler(int etype, char_t *msg)
{
#if 0
write(1, msg, gstrlen(msg));
#endif
}
/******************************************************************************/
/*
* Trace log. Customize this function to log trace output
*/
void defaultTraceHandler(int level, char_t *buf)
{
/*
* The following code would write all trace regardless of level
* to stdout.
*/
#if 0
if (buf) {
write(1, buf, gstrlen(buf));
}
#endif
}
/******************************************************************************/
/*
* Signal handler. Process the terminate signals SIGTERM and SIGKILL.
* If the signal is SIGTERM, just set the flag so the next time
* through the event loop, the webserver will terminate itself cleanly.
* If the signal is SIGKILL, release the resources and exit immediately.
*/
static void websTermSigHandler(int signo)
{
if (signo == SIGTERM) {
finished = 1;
} else if (signo == SIGKILL) {
#ifdef WEBS_SSL_SUPPORT
websSSLClose();
#endif
#ifdef USER_MANAGEMENT_SUPPORT
umClose();
#endif
websCloseServer();
websDefaultClose();
socketClose();
symSubClose();
#ifdef B_STATS
memLeaks();
#endif
bclose();
exit(1);
}
}
/******************************************************************************/
/*
* Get absolute path. In VxWorks, functions like chdir, ioctl for mkdir
* and ioctl for rmdir, require an absolute path. This function will
* take the path argument and convert it to an absolute path. It is the
* caller's responsibility to deallocate the returned string.
*/
static char_t *getAbsolutePath(char_t *path)
{
char_t *tail;
char_t *dev;
/*
* Determine if path is relative or absolute. If relative, prepend
* the current working directory to the name. Otherwise, use it.
* Note the getcwd call below must not be ggetcwd or else we go into
* an infinite loop
*/
if (iosDevFind(path, &tail) != NULL && path != tail) {
return bstrdup(B_L, path);
}
dev = balloc(B_L, LF_PATHSIZE);
getcwd(dev, LF_PATHSIZE);
strcat(dev, "/");
strcat(dev, path);
return dev;
}
/******************************************************************************/
/*
* Change default working directory.
*/
int vxchdir(char_t *dirname)
{
int rc;
char_t *path;
/*
* Get an absolute path name for the directory.
*/
path = getAbsolutePath(dirname);
/*
* Now change the default working directory. The chdir call
* below must not be replaced with gchdir or else an infinite
* loop will occur.
*/
rc = chdir(path);
bfree(B_L, path);
return rc;
}
/******************************************************************************/
#ifdef B_STATS
static void memLeaks()
{
int fd;
if ((fd = gopen(T("leak.txt"), O_CREAT | O_TRUNC | O_WRONLY, 0644)) >= 0) {
bstats(fd, printMemStats);
close(fd);
}
}
/******************************************************************************/
/*
* Print memory usage / leaks
*/
static void printMemStats(int handle, char_t *fmt, ...)
{
va_list args;
char_t buf[256];
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
write(handle, buf, strlen(buf));
}
#endif
/******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -