Beispiel #1
0
char_t *websUrlType(char_t *url, char_t *buf, int charCnt)
{
	sym_t	*sp;
	char_t	*ext, *parsebuf;

	a_assert(url && *url);
	a_assert(buf && charCnt > 0);

	if (url == NULL || *url == '\0') {
		gstrcpy(buf, T("text/plain"));
		return buf;
	}
	if (websUrlParse(url, &parsebuf, NULL, NULL, NULL, NULL, NULL, 
			NULL, &ext) < 0) {
		gstrcpy(buf, T("text/plain"));
		return buf;
	}
	strlower(ext);

/*
 *	Lookup the mime type symbol table to find the relevant content type
 */
	if ((sp = symLookup(websMime, ext)) != NULL) {
		gstrncpy(buf, sp->content.value.string, charCnt);
	} else {
		gstrcpy(buf, T("text/plain"));
	}
	bfree(B_L, parsebuf);
	return buf;
}
Beispiel #2
0
//----------------------------------------------------------------------------
// MQTT client callback, topic=<client-id>/... msg=...
//----------------------------------------------------------------------------
void ICACHE_FLASH_ATTR mqttOnPublish(String strTopic, String strMsg)
{
  tUint32 cbTopic = strTopic.length(), cbMsg = strMsg.length();

  do {
    // make sure topic starts with <client-id>
    Debug.logTxt(CLSLVL_MQTT | 0x0000, "mqttOnPublish,topic=%s,msg=%s", strTopic.c_str(), strMsg.c_str());
    if (strTopic.startsWith(AppSettings.mqttClientId + "/") == 0) {
      Debug.logTxt(CLSLVL_MQTT | 0x0010, "mqttOnPublish,not for us,dropping");
      g_mqttPktRxDropped++;
      return;
      } // if

    g_mqttPktRx++;

    // copy topic/msg to modifiable buffer on stack
    tChar szTopic[cbTopic + 1], szMsg[cbMsg + 1];
    tChar *pTopic = szTopic;
    gstrcpy(szTopic, strTopic.c_str());
    gstrcpy(szMsg, strMsg.c_str());

    // pass topic=<pfx>/<obj>... on to GPIOD
    pTopic += (AppSettings.mqttClientId.length() + 1);
    gpiodOnMqttPublish(pTopic, szMsg);
    } while (FALSE);

  } // mqttOnPublish
Beispiel #3
0
int gmstrcpy(char **dest, const char *source, ...){

    int length = 0;
    char *other_source = NULL;
    char *temp = NULL;
    va_list args;

    if (dest == NULL)
		return -1;
    if (source == NULL)
		return -1;
    length += strlen(source);
    va_start(args, source);
    while ((other_source = va_arg(args, char *)) != NULL)
		length += strlen(other_source);
    va_end(args);
    temp = gstralloc(length);
    strcat(temp, source);
    va_start(args, source);
    while ((other_source = va_arg(args, char *)) != NULL)
		strcat(temp, other_source);
    va_end(args);
    gstrcpy(dest, temp);
    gstrdel(temp);
    return 0;


};
Beispiel #4
0
int gmstrcat(char **main, const char *sufix, ...){

    int length = 0;
    char *other_sufix = NULL;
    char *temp = NULL;
    va_list args;
   
    if (main == NULL)
		return -1;
    if (sufix == NULL)
		return -1;
    
    if ((*main) != NULL)
		length = strlen((*main));
    length += strlen(sufix);
    va_start(args, sufix);
    while ((other_sufix = va_arg(args, char *)) != NULL)
		length += strlen(other_sufix);
    va_end(args);
    
    temp = gstralloc(length);
    if ((*main) != NULL)
		strcpy(temp, (*main));
    strcat(temp, sufix);
    va_start(args, sufix);
    while ((other_sufix = va_arg(args, char *)) != NULL)
		strcat(temp, other_sufix);
    va_end(args);
    
    gstrdel((*main));
    gstrcpy(main, temp);
	gstrdel(temp);
    return 0;
    
};
Beispiel #5
0
int create_tmp_file(stats_t *stats, node_t *node){

#define create_tmp_file_error {				\
	    gstrdel(tmp_template);				\
	    if (desc != -1)						\
			close(desc);					\
	    return -1;							\
	}

    char *tmp_template = NULL;
    int desc = -1;

	debug(3, "Received file %s;\n", stats->path);
    if (gmstrcpy(&tmp_template, data_dir, "/", stats->name, "XXXXXX", 0) != 0)
		create_tmp_file_error;
    desc = mkstemp(tmp_template);
    if (desc == -1)
		create_tmp_file_error;
    close(desc);
    if (gstrcpy(&node->tmp_path, tmp_template) != 0)
		create_tmp_file_error;
    gstrdel(tmp_template);
    return 0;

};
Beispiel #6
0
void parse_mount(char *arg){

    if (mount != NULL)
		fail(ERR_PARAMETRES);
    if (gstrcpy(&mount, arg) != 0)
    	fail(-1);

};
Beispiel #7
0
node_t * add_file(list_t *list, char *path, int rev){
    if (list->head == NULL){
        list->head = list->tail = single(node_t);
        gstrcpy(&list->head->path, path);
        return list->head;
    }
    node_t *node = get_open_file(path);
    if (node)
        return node;
    node = single(node_t);
    list->tail->next = node;
    node->prev = list->tail;
    list->tail = node;
    gstrcpy(&node->path, path);
    node->rev = rev;
    return node;
};
Beispiel #8
0
void copy_stats(stats_t *source, stats_t **dest){
    debug(3, "copying stats for: path %s, internal: %s, name: %s, rev: %d\n",
          source->path, source->internal, source->name, source->rev);
    *dest = single(stats_t);
    memcpy((*dest), source, sizeof(stats_t));
    if (source->path){
        (*dest)->path = 0;
        gstrcpy(&(*dest)->path, source->path);
    }
    if (source->internal)
        (*dest)->internal = (*dest)->path + (source->internal - source->path);
    if (source->name)
        (*dest)->name = (*dest)->path + (source->name - source->path);
    if (source->link) {
        (*dest)->link = 0;
        gstrcpy(&(*dest)->link, source->link);
    }
    debug(4, "done copying stats: path %s, internal %s, name %s, rev: %d\n",
          (*dest)->path, (*dest)->internal, (*dest)->name, (*dest)->rev);
};
Beispiel #9
0
// service *main == sufix
int gstrcat(char **main, const char *sufix){

    if (sufix == NULL)
		return -1;
    if (main == NULL)
		return -1;
    if ((*main) == NULL)
		return gstrcpy(main, sufix);
    return __gstrcat(main, sufix);
	    
};
Beispiel #10
0
int sent_xmsg_stats(User *usr, XMsg *x, char *name) {
	switch(x->type) {
		case XMSG_X:
			usr->xsent++;
			user_dirty(usr, "xsent");
			update_stats(usr);
			inc_stats(STATS_XSENT);
			break;

		case XMSG_EMOTE:
			usr->esent++;
			user_dirty(usr, "esent");
			update_stats(usr);
			inc_stats(STATS_ESENT);
			break;

		case XMSG_FEELING:
			usr->fsent++;
			user_dirty(usr, "fsent");
			update_stats(usr);
			inc_stats(STATS_FSENT);
			break;

		case XMSG_QUESTION:
			usr->qsent++;
			user_dirty(usr, "qsent");
			update_stats(usr);
			inc_stats(STATS_QSENT);
			break;

		case XMSG_ANSWER:
			usr->qansw++;
			user_dirty(usr, "qansw");
			update_stats(usr);
			inc_stats(STATS_QANSW);
			break;

		default:
			;
	}
	if (name != NULL) {							/* add to talked_to list */
		if (usr->talked_to.len <= 0)
			gstrcpy(&(usr->talked_to), name);
		else {
			if (!cstrfind(usr->talked_to.str, name, ',')) {
				gstrcat(&(usr->talked_to), ",");
				gstrcat(&(usr->talked_to), name);
			}
		}
	}
	return 0;
}
Beispiel #11
0
//----------------------------------------------------------------------------
// duplicate string
//----------------------------------------------------------------------------
tChar* xstrdup(tCChar* pStr)
{
	tChar	 *pstr;
	tInt32 nLen;

	if (pStr == NULL) pStr = "";

	nLen = gstrlen(pStr) + 1;
	if ((pstr = (tChar*) malloc(nLen)))
		gstrcpy(pstr, pStr);

	return pstr;
  } // xstrdup
Beispiel #12
0
char_t *bstrdup(B_ARGS_DEC, char_t *s)
{
    char_t	*cp;
    int		len;

    if (s == NULL) {
        s = T("");
    }
    len = gstrlen(s) + 1;
    if ((cp = balloc(B_ARGS, len * sizeof(char_t))) != NULL) {
        gstrcpy(cp, s);
    }
    return cp;
}
Beispiel #13
0
void parse_repo(struct file_system_info *fsinfo, int argc, char** argv, int *index){

    int i = 0;

    if (fsinfo->repo_count != 0)
		fail(ERR_PARAMETRES);
    for (i = *index; (i < argc) && (!isOption(argv[i])); i++){ };
    fsinfo->repo_count = i - *index;
    fsinfo->repos = calloc(fsinfo->repo_count, sizeof(char *));
    for (i = *index; (i < argc) && (!isOption(argv[i])); i++)
		gstrcpy(&fsinfo->repos[i - *index], argv[i]);
    *index += fsinfo->repo_count - 1;
    
};
Beispiel #14
0
// dest != NULL, (*dest) != NULL, sufix != NULL
int __gstrcat(char **dest, const char *sufix){

    int dest_length = strlen((*dest));
    int sufix_length = strlen(sufix);
    int i = 0;
    char temp[dest_length + sufix_length + 1];
    
    for (i = 0; i < dest_length; i++)
		temp[i] = (*dest)[i];
    for (i = 0; i < sufix_length; i++)
		temp[i + dest_length] = sufix[i];
    temp[dest_length + sufix_length] = 0;
    free((*dest));
    (*dest) = gstralloc(dest_length + sufix_length);
    if ((*dest) == NULL)
		return -1;
    gstrcpy(dest, temp);
    return 0;

};
Beispiel #15
0
int set_directory(int argc, char **argv, int *index){

#define set_directory_finish(value) {				\
			if (temp != NULL)						\
				free(temp);							\
			return value;							\
		}

	struct stat *temp = NULL;

	if ((*index + 1 >= argc) || (isOption(argv[*index + 1]) == 1))
		set_directory_finish(-1);
	temp = single(struct stat);
	if ((stat(argv[*index + 1], temp) != 0) || ((temp->st_mode & S_IFDIR) == 0))
		set_directory_finish(-1);
	*index += 1;
	if (gstrcpy(&tmp_dir, argv[*index]) != 0)
		set_directory_finish(-1);
	set_directory_finish(0);
	
};
Beispiel #16
0
int gstrline(char **line, size_t *length, FILE *file){
	
	int filled = 0;
	char next = 0;
	char *temp = NULL;
	
	if (line == NULL)
		return -1;
	if ((*line == NULL) || (*length <= 0)){
		*line = gstralloc(128);
		*length = 129;
	}
	else
		memset(*line, 0, *length);

	while (1){
		next = (char) getc(file);
		if (next == EOF){
			if (filled == 0)
				return -1;
			else
				return filled;
		};
		if (filled == *length){
			gstrcpy(&temp, *line);
			gstrdel(*line);
			*length = (*length - 1) * 2 + 1;
			*line = gstralloc(*length);
			strcpy(*line, temp);
		};
		(*line)[filled] = next;
		filled++;
		if (next == '\n')
			return filled;
	};
	
	gstrdel(temp);
	return filled;
	
};
Beispiel #17
0
int websValidateUrl(webs_t wp, char_t *path)
{
	char_t	*parts[64];					/* Array of ptr's to URL parts */
	char_t	*token, *dir, *lpath;
	int		i, len, npart;

	a_assert(websValid(wp));
	a_assert(path);

	dir = websGetRequestDir(wp);
	if (dir == NULL || *dir == '\0') {
		return -1;
	}

/*
 *	Copy the string so we don't destroy the original
 */
	path = bstrdup(B_L, path);
	websDecodeUrl(path, path, gstrlen(path));

	len = npart = 0;
	parts[0] = NULL;

   /*
    * 22 Jul 02 -- there were reports that a directory traversal exploit was
    * possible in the WebServer running under Windows if directory paths
    * outside the server's specified root web were given by URL-encoding the
    * backslash character, like:
    *
    *  GoAhead is vulnerable to a directory traversal bug. A request such as
    *
    *  GoAhead-server/../../../../../../../ results in an error message
    *  'Cannot open URL'.

    *  However, by encoding the '/' character, it is possible to break out of
    *  the
    *  web root and read arbitrary files from the server.
    *  Hence a request like:
    *
    *  GoAhead-server/..%5C..%5C..%5C..%5C..%5C..%5C/winnt/win.ini returns the
    *  contents of the win.ini file.
    * (Note that the description uses forward slashes (0x2F), but the example
    * uses backslashes (0x5C). In my tests, forward slashes are correctly
    * trapped, but backslashes are not. The code below substitutes forward
    * slashes for backslashes before attempting to validate that there are no
    * unauthorized paths being accessed.
    */
   token = gstrchr(path, '\\');
   while (token != NULL)
   {
      *token = '/';
      token = gstrchr(token, '\\');
   }

	token = gstrtok(path, T("/"));

/*
 *	Look at each directory segment and process "." and ".." segments
 *	Don't allow the browser to pop outside the root web.
 */
	while (token != NULL) {
		if (gstrcmp(token, T("..")) == 0) {
			if (npart > 0) {
				npart--;
			}

		} else if (gstrcmp(token, T(".")) != 0) {
			parts[npart] = token;
			len += gstrlen(token) + 1;
			npart++;
		}
		token = gstrtok(NULL, T("/"));
	}

/*
 *	Create local path for document. Need extra space all "/" and null.
 */
	if (npart || (gstrcmp(path, T("/")) == 0) || (path[0] == '\0')) {
		lpath = balloc(B_L, (gstrlen(dir) + 1 + len + 1) * sizeof(char_t));
		gstrcpy(lpath, dir);

		for (i = 0; i < npart; i++) {
			gstrcat(lpath, T("/"));
			gstrcat(lpath, parts[i]);
		}
		websSetRequestLpath(wp, lpath);
		bfree(B_L, path);
		bfree(B_L, lpath);

	} else {
		bfree(B_L, path);
		return -1;
	}
	return 0;
}
Beispiel #18
0
int websUrlParse(char_t *url, char_t **pbuf, char_t **phost, char_t **ppath, 
	char_t **pport, char_t **pquery, char_t **pproto, char_t **ptag, 
	char_t **pext)
{
	char_t		*tok, *cp, *host, *path, *port, *proto, *tag, *query, *ext;
	char_t		*last_delim, *hostbuf, *portbuf, *buf;
	int			c, len, ulen;

	a_assert(url);
	a_assert(pbuf);

	ulen = gstrlen(url);
/*
 *	We allocate enough to store separate hostname and port number fields.
 *	As there are 3 strings in the one buffer, we need room for 3 null chars.
 *	We allocate MAX_PORT_LEN char_t's for the port number.
 */
	len = ulen * 2 + MAX_PORT_LEN + 3;
	if ((buf = balloc(B_L, len * sizeof(char_t))) == NULL) {
		return -1;
	}
	portbuf = &buf[len - MAX_PORT_LEN - 1];
	hostbuf = &buf[ulen+1];
	gstrcpy(buf, url);
	url = buf;

/*
 *	Convert the current listen port to a string. We use this if the URL has
 *	no explicit port setting
 */
	stritoa(websGetPort(), portbuf, MAX_PORT_LEN);
	port = portbuf;
	path = T("/");
	proto = T("http");
	host = T("localhost");
	query = T("");
	ext = htmExt;
	tag = T("");

	if (gstrncmp(url, T("http://"), 7) == 0) {
		tok = &url[7];
		tok[-3] = '\0';
		proto = url;
		host = tok;
		for (cp = tok; *cp; cp++) {
			if (*cp == '/') {
				break;
			}
			if (*cp == ':') {
				*cp++ = '\0';
				port = cp;
				tok = cp;
			}
		}
		if ((cp = gstrchr(tok, '/')) != NULL) {
/*
 *			If a full URL is supplied, we need to copy the host and port 
 *			portions into static buffers.
 */
			c = *cp;
			*cp = '\0';
			gstrncpy(hostbuf, host, ulen);
			gstrncpy(portbuf, port, MAX_PORT_LEN);
			*cp = c;
			host = hostbuf;
			port = portbuf;
			path = cp;
			tok = cp;
		}

	} else {
		path = url;
		tok = url;
	}

/*
 *	Parse the query string
 */
	if ((cp = gstrchr(tok, '?')) != NULL) {
		*cp++ = '\0';
		query = cp;
		path = tok;
		tok = query;
	} 

/*
 *	Parse the fragment identifier
 */
	if ((cp = gstrchr(tok, '#')) != NULL) {
		*cp++ = '\0';
		if (*query == 0) {
			path = tok;
		}
	}

/*
 *	Only do the following if asked for the extension
 */
	if (pext) {
		if ((cp = gstrrchr(path, '.')) != NULL) {
			if ((last_delim = gstrrchr(path, '/')) != NULL) {
				if (last_delim > cp) {
					ext = htmExt;
				} else {
					ext = cp;
				}
			} else {
				ext = cp;
			}
		} else {
			if (path[gstrlen(path) - 1] == '/') {
				ext = htmExt;
			}
		}
	}

/*
 *	Pass back the fields requested (if not NULL)
 */
	if (phost)
		*phost = host;
	if (ppath)
		*ppath = path;
	if (pport)
		*pport = port;
	if (pproto)
		*pproto = proto;
	if (pquery)
		*pquery = query;
	if (ptag)
		*ptag = tag;
	if (pext)
		*pext = ext;
	*pbuf = buf;
	return 0;
}
Beispiel #19
0
int websValidateUrl(webs_t wp, char_t *path)
{
   /*
     Thanks to Dhanwa T ([email protected]) for this fix -- previously,
     if an URL was requested having more than (the hardcoded) 64 parts,
     the webServer would experience a hard crash as it attempted to
     write past the end of the array 'parts'.
	 Also fixes: http://www.securiteam.com/securitynews/5MP0C1580W.html
    */
	char_t	*parts[MAX_URL_DEPTH];	/* Array of ptr's to URL parts */
	char_t	*token, *dir, *lpath; 
	int	      i, len, npart;

	a_assert(websValid(wp));
	a_assert(path);

	dir = websGetRequestDir(wp);
	if (dir == NULL || *dir == '\0') {
		return -1;
	}

/*
 *	Copy the string so we don't destroy the original
 */
	path = bstrdup(B_L, path);
	websDecodeUrl(path, path, gstrlen(path));

	len = npart = 0;
	parts[0] = NULL;

   /*
    * Fixed by Matt Moore, 22 Jul 02
	* http://www.securiteam.com/securitynews/5RP0I007PG.html
	* http://www.securiteam.com/securitynews/5QP010U3FS.html
	* 
	* There were reports that a directory traversal exploit was
    * possible in the WebServer running under Windows if directory paths
    * outside the server's specified root web were given by URL-encoding the
    * backslash character, like:
    *
    *  GoAhead is vulnerable to a directory traversal bug. A request such as
    *  
    *  GoAhead-server/../../../../../../../ results in an error message
    *  'Cannot open URL'.
    *  However, by encoding the '/' character, it is possible to break out of
    *  the web root and read arbitrary files from the server.
    *  Hence a request like:
    * 
    *  GoAhead-server/..%5C..%5C..%5C..%5C..%5C..%5C/winnt/win.ini returns the
    *  contents of the win.ini file.
    * (Note that the description uses forward slashes (0x2F), but the example
    * uses backslashes (0x5C). In my tests, forward slashes are correctly
    * trapped, but backslashes are not. The code below substitutes forward
    * slashes for backslashes before attempting to validate that there are no
    * unauthorized paths being accessed.
    */
	token = gstrchr(path, '\\');
	while (token != NULL) {
		*token = '/';
		token = gstrchr(token, '\\');
	}
	token = gstrtok(path, T("/"));

/*
 *	Look at each directory segment and process "." and ".." segments
 *	Don't allow the browser to pop outside the root web. 
 */
	while (token != NULL) 
   {
      if (npart >= MAX_URL_DEPTH)
      {
         /*
          * malformed URL -- too many parts for us to process.
          */
         bfree(B_L, path);
         return -1;
      }
		if (gstrcmp(token, T("..")) == 0) 
      {
			if (npart > 0) 
         {
				npart--;
			}
		} else if (gstrcmp(token, T(".")) != 0) {
			parts[npart] = token;
			len += gstrlen(token) + 1;
			npart++;
		}
		token = gstrtok(NULL, T("/"));
	}

#ifdef WIN32
   if (isBadWindowsPath(parts, npart))
   {
      bfree(B_L, path);
      return -1;
   }

#endif

/*
 *	Create local path for document. Need extra space all "/" and null.
 */
	if (npart || (gstrcmp(path, T("/")) == 0) || (path[0] == '\0')) {
		lpath = balloc(B_L, (gstrlen(dir) + 1 + len + 1) * sizeof(char_t));
		gstrcpy(lpath, dir);

		for (i = 0; i < npart; i++) {
			gstrcat(lpath, T("/"));
			gstrcat(lpath, parts[i]);
		}
		websSetRequestLpath(wp, lpath);
		bfree(B_L, path);
		bfree(B_L, lpath);
	} else {
		bfree(B_L, path);
		return -1;
	}
	return 0;
}
Beispiel #20
0
int websLaunchCgiProc( char_t* cgiPath, char_t** argp, char_t** envp,
                       char_t* stdIn, char_t* stdOut )
{
    STARTUPINFO			newinfo;
    SECURITY_ATTRIBUTES security;
    PROCESS_INFORMATION	procinfo;		/*  Information about created proc   */
    DWORD				dwCreateFlags;
    char_t*				cmdLine;
    char_t**				pArgs;
    BOOL				bReturn;
    int					i, nLen;
    unsigned char*		pEnvData;
    /*
     *	Replace directory delimiters with Windows-friendly delimiters
     */
    nLen = gstrlen( cgiPath );

    for ( i = 0; i < nLen; i++ )
    {
        if ( cgiPath[i] == '/' )
        {
            cgiPath[i] = '\\';
        }
    }

    /*
     *	Calculate length of command line
     */
    nLen = 0;
    pArgs = argp;

    while ( pArgs && *pArgs &&** pArgs )
    {
        nLen += gstrlen( *pArgs ) + 1;
        pArgs++;
    }

    /*
     *	Construct command line
     */
    cmdLine = balloc( B_L, sizeof( char_t ) * nLen );
    a_assert( cmdLine );
    gstrcpy( cmdLine, "" );
    pArgs = argp;

    while ( pArgs && *pArgs &&** pArgs )
    {
        gstrcat( cmdLine, *pArgs );
        gstrcat( cmdLine, T( " " ) );
        pArgs++;
    }

    /*
    *	Create the process start-up information
    */
    memset( &newinfo, 0, sizeof( newinfo ) );
    newinfo.cb          = sizeof( newinfo );
    newinfo.dwFlags     = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    newinfo.wShowWindow = SW_HIDE;
    newinfo.lpTitle     = NULL;
    /*
     *	Create file handles for the spawned processes stdin and stdout files
     */
    security.nLength = sizeof( SECURITY_ATTRIBUTES );
    security.lpSecurityDescriptor = NULL;
    security.bInheritHandle = TRUE;
    /*
     *	Stdin file should already exist.
     */
    newinfo.hStdInput = CreateFile( stdIn, GENERIC_READ,
                                    FILE_SHARE_READ, &security, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
    /*
     *	Stdout file is created and file pointer is reset to start.
     */
    newinfo.hStdOutput = CreateFile( stdOut, GENERIC_READ | GENERIC_WRITE,
                                     FILE_SHARE_READ + FILE_SHARE_WRITE, &security, OPEN_ALWAYS,
                                     FILE_ATTRIBUTE_NORMAL, NULL );
    SetFilePointer( newinfo.hStdOutput, 0, NULL, FILE_END );
    /*
     *	Stderr file is set to Stdout.
     */
    newinfo.hStdError =	newinfo.hStdOutput;
    dwCreateFlags = CREATE_NEW_CONSOLE;
    pEnvData = tableToBlock( envp );
    /*
     *	CreateProcess returns errors sometimes, even when the process was
     *	started correctly.  The cause is not evident.  For now: we detect
     *	an error by checking the value of procinfo.hProcess after the call.
     */
    procinfo.hProcess = NULL;
    bReturn = CreateProcess(
                  NULL,				/*  Name of executable module        */
                  cmdLine,			/*  Command line string              */
                  NULL,				/*  Process security attributes      */
                  NULL,				/*  Thread security attributes       */
                  TRUE,				/*  Handle inheritance flag          */
                  dwCreateFlags,		/*  Creation flags                   */
                  pEnvData,			/*  New environment block            */
                  NULL,				/*  Current directory name           */
                  &newinfo,			/*  STARTUPINFO                      */
                  &procinfo );			/*  PROCESS_INFORMATION              */

    if ( procinfo.hThread != NULL )
    {
        CloseHandle( procinfo.hThread );
    }

    if ( newinfo.hStdInput )
    {
        CloseHandle( newinfo.hStdInput );
    }

    if ( newinfo.hStdOutput )
    {
        CloseHandle( newinfo.hStdOutput );
    }

    bfree( B_L, pEnvData );
    bfree( B_L, cmdLine );

    if ( bReturn == 0 )
    {
        return -1;
    }

    else
    {
        return ( int ) procinfo.hProcess;
    }
}