I am reading from a txt file into an array of structures. Example txt:
-4.5 -1 0 0
4.0 1 0 0
8 0 1 2
12.1 0 -6 1
-3.2 2.5 -3.0 4
The 4 values of each line correspond to the 4 values in the structure. The file may contain up to 100 lines (MAX is defined as 100). With the following code I am trying to store each line into the respective index of the struct array and then print:
FILE *fileName = NULL;
typedef struct chargeData_struct {
double Q, x, y, z;
} ChargeData;
ChargeData values[MAX], *p = values;
fileName = fopen("charge2.txt", "r");
if (fileName == NULL)
{
printf("ERROR: Could not open file.");
}
int k = 0;
while (fscanf(fileName, "%lf %lf %lf %lf", &p[k].Q, &p[k].x, &p[k].y, &p[k].z) != EOF);
{
printf("%f %f %f %f\n", p[k].Q, p[k].x, p[k].y, p[k].z);
k++;
}
fclose(fileName);
However, only the last line of the txt file is printed. Is the same index of the struct array being overwritten each time?
You are using an extra semicolon which makes all the trouble, here:
while (fscanf(...) != EOF);
{
...
Remove it and you should be fine.
What happens with your code is that while(..); is equivalent to this:
while(...)
{
; // do nothing
}
thus does not enter the body (the one you think is the body) of your loop (since the actual body does nothing). However scanf() continues to parse the file, and then this section of your code executes:
{
printf("%f %f %f %f\n", p[k].Q, p[k].x, p[k].y, p[k].z);
k++;
}
independently, where the curly braces are treated like they wanted to state scope.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define LINE_BUFFER_LEN (512)
#define RESERVE_NEWLINDE 0
#define AUTO_FILTER_NEWLINDE 1
typedef int (* LINE_READER)(char * pstrLine, int uiBufferLen, void * pvData);
typedef struct st_HW_SSP_CONFIG
{
const char * pstrConfigPath;
LINE_READER pfLineReader;
FILE * pstFile;
void * pvData;
int CurrentLine;
int Flag;
} CONFIG_ST;
int CloseConfig(CONFIG_ST * pstConfig)
{
if (!pstConfig)
{
// record error
return -1;
}
if (fclose(pstConfig->pstFile))
{
// record error
}
return 0;
}
int OpenConfigFile(const char * pstrFilePath, CONFIG_ST * pstConfig)
{
FILE * pstFile = NULL;
if ((!pstrFilePath) || (!pstConfig))
{
return -1;
}
pstFile = fopen(pstrFilePath, "r");
if (!pstFile)
{
return -1;
}
pstConfig->pstFile = pstFile;
pstConfig->pstrConfigPath = pstrFilePath;
pstConfig->Flag = RESERVE_NEWLINDE;
return 0;
}
int IsNullStr(const char *pcStr)
{
const char *pcTmp = pcStr;
while ('\0' != *pcTmp)
{
if (!isspace(*pcTmp))
{
return 0;
}
pcTmp++;
}
return 1;
}
int IsEffectiveLine(char acFileLineBuffer[LINE_BUFFER_LEN])
{
if (0 == strlen(&acFileLineBuffer[0]))
{
return 0;
}
if ('#' == acFileLineBuffer[0]) // strip as a comment line
{
return 0;
}
if (IsNullStr(&acFileLineBuffer[0]))
{
return 0;
}
return 1;
}
void FilterNewLine(char* pcLine, int MaxNumLen)
{
int uiLen = strlen(pcLine);
if (uiLen > 1)
{
if ('\n' == pcLine[uiLen - 1])
{
pcLine[uiLen - 1] = '\0';
if (uiLen > 2)
{
if ('\r' == pcLine[uiLen - 2])
{
pcLine[uiLen - 2] = '\0';
}
}
}
}
return;
}
int ReadConfigFile(CONFIG_ST * pstConfig)
{
char acFileLineBuffer[LINE_BUFFER_LEN] = {0};
char * pstrRead = NULL;
int Ret = 0;
if (!pstConfig)
{
return -1;
}
if ((!pstConfig->pstFile) || (!pstConfig->pfLineReader))
{
return -1;
}
rewind(pstConfig->pstFile);
pstConfig->CurrentLine = 0;
do
{
memset((void *)&acFileLineBuffer[0], 0, LINE_BUFFER_LEN);
pstrRead = fgets(&acFileLineBuffer[0], LINE_BUFFER_LEN - 1, pstConfig->pstFile);
if (pstrRead)
{
pstConfig->CurrentLine ++;
if (0 == IsEffectiveLine(acFileLineBuffer))
{
continue;
}
if (AUTO_FILTER_NEWLINDE == pstConfig->Flag)
{
FilterNewLine(acFileLineBuffer, LINE_BUFFER_LEN - 1);
}
if (pstConfig->pfLineReader)
{
Ret = pstConfig->pfLineReader(&acFileLineBuffer[0],
LINE_BUFFER_LEN,
pstConfig->pvData);
if (Ret)
{
break;
}
}
}
}
while (pstrRead);
return Ret;
}
int ReadConfigFileEx(const char * pFilePath,
LINE_READER pfReader,
void * pData, int Flag)
{
int Ret = 0;
CONFIG_ST stConfig = {0};
Ret = OpenConfigFile(pFilePath, &stConfig);
if (Ret)
{
return Ret;
}
stConfig.pfLineReader = pfReader;
stConfig.pvData = pData;
stConfig.Flag = Flag;
Ret = ReadConfigFile(&stConfig);
CloseConfig(&stConfig);
return Ret;
}
int StringSplit(char *pcStr, char cFlag,
char * pstArray[], int MaxNum,
int *pNum)
{
char * pcStrTemp = 0;
unsigned int uiIndex = 0;
pcStrTemp = pcStr;
while (pcStrTemp)
{
pstArray[uiIndex] = pcStrTemp;
pcStrTemp = strchr(pcStrTemp, cFlag);
if (pcStrTemp)
{
*pcStrTemp = '\0';
pcStrTemp ++;
uiIndex ++;
}
if (uiIndex >= MaxNum)
{
break;
}
}
if (0 != MaxNum)
{
*pNum = uiIndex >= MaxNum ? (MaxNum - 1) : uiIndex;
}
else
{
*pNum = 0;
}
return 0;
}
int MyLineReader(char * pstrLine, int uiBufferLen, void * pvData)
{
printf("Read line:[%s]\r\n", pstrLine);
char *pArray[8] = {0};
int Num = 0;
int index = 0;
StringSplit(pstrLine, ' ', pArray, 8, &Num);
for (index = 0; index <= Num; index ++)
{
printf("Get value :[%s]\r\n", pArray[index]);
}
return 0;
}
int main(int argc, char * argv[])
{
int ret = 0;
if (argc != 2)
{
printf("Please input file to read.\r\n");
return 0;
}
ret = ReadConfigFileEx(argv[1], MyLineReader, NULL, AUTO_FILTER_NEWLINDE);
if (ret)
{
printf("Open file error.\r\n");
}
return 0;
}
I am writing the following program to parse the text file (attached) but it keeps crashing after couple of iterations of while loop or it seems that the buffer storing file contents is corrupted somehow?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
char * pick_question(char *, char, int);
char * print_answer(char *, char, int);
int no_of_questions(char*, char);
void clear();
int debug = 0;
int main(int argc, char* argv[])
{
system("cmd /c chcp 1252");
// system("cmd /c chcp 65001");
if (argc < 2)
{
perror("Please enter a filename!\n");
exit(0);
}
if (argc > 2)
{
debug = atoi(argv[2]);
}
char const* const fileName = argv[1];
FILE* file = fopen(fileName, "r");
if (!file)
{
perror("Unable to read file!\n");
exit(0);
}
else
{
if (debug == 1)
{
printf("File opened successfully\n");
}
}
static char *buffer;
int fileSz;
fseek(file, 0, SEEK_END);
fileSz = ftell(file);
fseek(file, 0, SEEK_SET);
buffer = (char*) malloc((fileSz + 1) * sizeof(char));
if (!buffer)
{
perror("Unable to allocate buffer!");
exit(0);
}
fread(buffer, sizeof(char), fileSz, file);
while (1)
{
time_t t;
srand((unsigned) time(&t));
int sub = rand() % 5 + 1;
char del;
switch (sub)
{
case 1:
del = 'A';
break;
case 2:
del = 'B';
break;
case 3:
del = 'C';
break;
case 4:
del = 'D';
break;
case 5:
del = 'E';
}
int nrOfQues = no_of_questions(buffer, del);
if (nrOfQues == 0)
{
perror("main(): no_of_questions() returned 0. Unsupported text structure in file or incorrect file encoding!");
fclose(file);
exit(0);
}
int qNo = rand() % nrOfQues + 1;
char *ques = pick_question(buffer, del, qNo);
if (ques)
{
printf("\n\n");
puts(ques);
printf("\n\n");
}
else
{
perror("main(): pick_question() returned NULL. Unsupported text structure in file!");
fclose(file);
exit(0);
}
printf("\n\n");
printf("Do you want to see the answer(y/n)?");
char ans, repeat;
scanf("%c", &ans);
if ( ans == 'Y' || ans == 'y')
{
char *ans = print_answer(buffer, del, qNo);
if (ans)
{
printf("\n\n");
puts(ans);
printf("\n\n");
}
else
{
printf("\n\n");
perror("main(): print_answer() returned NULL. Unsupported text structure in file!");
fclose(file);
exit(0);
}
}
printf("Do you want to try more questions (y/n)?");
clear();
scanf("%c", &repeat);
if (repeat == 'N' || repeat == 'n')
{
break;
}
clear();
}
printf("\n\n");
printf("******** Thank you for using TULE Master! ********");
printf("\n\n");
fclose(file);
return 0;
}
char * pick_question(char * buffer, char sub, int qNo)
{
char tmpBuff[20];
char tmpBuff2[20];
const char * searchStr = "FRÅGA";
const char * searchStr2 = "A 1 SVAR:";
const char * searchStr3 = "*****************************************";
char *pStr, *currPos, *nStr, *tmpStr, *tmpStr2;
currPos = buffer;
int count = snprintf(tmpBuff, 20, "FRÅGA %c %d", sub, qNo);
if (count >= 0 || count < 20)
{
if (debug)
{
printf("tmpBuff is %s\n", tmpBuff);
}
currPos = strstr(currPos, tmpBuff);
if (currPos)
{
pStr = currPos;
nStr = currPos + 1;
nStr = strstr(nStr, searchStr);
if (!nStr)
{
nStr = currPos;
nStr = strstr(nStr, searchStr2);
if (!nStr)
{
printf("pick_qestion(): nStr is NULL. Unsupported "
"text structure");
return NULL;
}
}
// Check if it is a scenario based question
count = snprintf(tmpBuff2, 20, "FRÅGA %c %d", sub, qNo-1);
if (count >= 0 || count < 20)
{
tmpStr = strstr(buffer, tmpBuff2);
tmpStr2 = strstr(tmpStr, searchStr3);
if (tmpStr < tmpStr2 && tmpStr2 < pStr)
{
pStr = tmpStr2;
}
}
int qLen = nStr - pStr;
char *ques = malloc(sizeof(char) * (qLen+1));
snprintf(ques,qLen,"%s", pStr);
return ques;
}
else
{
printf("pick_qestion(): string \"FRÅGA\" not found in file!");
return NULL;
}
}
printf("pick_qestion(): snprintf was not successful!");
return NULL;
}
char * print_answer(char * buffer, char sub, int qNo)
{
char tmpBuff[20];
char *pStr, *currPos, *nStr;
int count = snprintf(tmpBuff, 20, "%c %d SVAR:", sub, qNo);
if (count >= 0 || count < 20)
{
currPos = strstr(buffer, tmpBuff);
if (!currPos)
{
printf("print_answer(): string \"SVAR\" not found in file!");
}
pStr = currPos;
nStr = currPos + 1;
char tmpBuff2[20];
int count = snprintf(tmpBuff2, 20, "%c %d SVAR:", sub, qNo+1);
if (count < 0 || count >= 20)
{
printf("print_answer(): snprint was not successful!");
return NULL;
}
nStr = strstr(nStr, tmpBuff2);
if (!nStr)
{
nStr = buffer + strlen(buffer);
}
int ansLen = nStr - pStr;
char *ans = malloc(sizeof(char) * (ansLen+1));
snprintf(ans, ansLen, "%s", pStr);
return ans;
}
printf("print_answer(): snprint was not successful!");
return NULL;
}
int no_of_questions(char *buffer, char sub)
{
char tmpBuff[20];
char *currPos, *pStr;
int count = snprintf(tmpBuff, 20, "FRÅGA %c", sub);
if (count >= 0 || count < 20)
{
if (debug)
{
printf("tmpBuff is %s\n", tmpBuff);
}
currPos = strstr(buffer, tmpBuff);
while (currPos != NULL)
{
pStr = currPos;
currPos = currPos + 1;
currPos = strstr(currPos, tmpBuff);
}
if (pStr != buffer)
{
pStr += 9;
char tmpBuff2[20];
memcpy(tmpBuff2, pStr, 2);
if (debug)
{
printf("No. of questions for %c DEL is are %d\n", sub,
atoi(tmpBuff2));
}
return atoi(tmpBuff2);
}
return 0;
}
return 0;
}
void clear()
{
int c;
while ((c = getchar()) != '\n' && c != EOF) { }
}
This is the file that is given as input to the program:
Link
I am trying to get a simple django app up on Http Server. The server is IBM Websphere Application Server. I have successfully compiled mod_scgi.c to the iseries.
I proceeded to create a server and edit the configuration file with the following code:
#Load the mod_scgi module
LoadModule scgi_module /qsys.lib/qgpl.lib/mod_scgi.srvpgm
# Set up location to be server by an SCGI server process
SCGIMount /dynamic 127.0.0.1:8080
This produces an error on the configuration file: "Directive name "SCGIMount" is not recognized."
I am not sure how to proceed from here. Also, the mod_scgi.c file has been modified to allow it to be compiled to the iseries. I have provided the code below:
/* mod_scgi.c
*
* Apache 2 implementation of the SCGI protocol.
*
*/
#define MOD_SCGI_VERSION "1.14"
#define SCGI_PROTOCOL_VERSION "1"
#include "ap_config.h"
#include "apr_version.h"
#include "apr_lib.h"
#include "apr_strings.h"
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "http_request.h"
#include "http_log.h"
#include "http_protocol.h"
#include "util_script.h"
#ifdef AS400
#include <strings.h>
#endif
#define DEFAULT_TIMEOUT 60 /* default socket timeout */
#define UNSET 0
#define ENABLED 1
#define DISABLED 2
#if APR_MAJOR_VERSION == 0
#define apr_socket_send apr_send
#define GET_PORT(port, addr) apr_sockaddr_port_get(&(port), addr)
#define CREATE_SOCKET(sock, family, pool) \
apr_socket_create(sock, family, SOCK_STREAM, pool)
#else
#define GET_PORT(port, addr) ((port) = (addr)->port)
#define CREATE_SOCKET(sock, family, pool) \
apr_socket_create(sock, family, SOCK_STREAM, APR_PROTO_TCP, pool)
#endif
typedef struct {
char *path;
char *addr;
apr_port_t port;
} mount_entry;
/*
* Configuration record. Used per-directory configuration data.
*/
typedef struct {
mount_entry mount;
int enabled; /* mod_scgi is enabled from this directory */
int timeout;
} scgi_cfg;
/* Server level configuration */
typedef struct {
apr_array_header_t *mounts;
int timeout;
} scgi_server_cfg;
/*
* Declare ourselves so the configuration routines can find and know us.
* We'll fill it in at the end of the module.
*/
module AP_MODULE_DECLARE_DATA scgi_module;
/*
* Locate our directory configuration record for the current request.
*/
static scgi_cfg *
our_dconfig(request_rec *r)
{
return (scgi_cfg *) ap_get_module_config(r->per_dir_config, &scgi_module);
}
static scgi_server_cfg *our_sconfig(server_rec *s)
{
return (scgi_server_cfg *) ap_get_module_config(s->module_config,
&scgi_module);
}
static int
mount_entry_matches(const char *url, const char *prefix,
const char **path_info)
{
int i;
for (i=0; prefix[i] != '\0'; i++) {
if (url[i] == '\0' || url[i] != prefix[i])
return 0;
}
if (url[i] == '\0' || url[i] == '/') {
*path_info = url + i;
return 1;
}
return 0;
}
static int scgi_translate(request_rec *r)
{
scgi_cfg *cfg = our_dconfig(r);
if (cfg->enabled == DISABLED) {
return DECLINED;
}
if (cfg->mount.addr != UNSET) {
ap_assert(cfg->mount.port != UNSET);
r->handler = "scgi-handler";
r->filename = r->uri;
return OK;
}
else {
int i;
scgi_server_cfg *scfg = our_sconfig(r->server);
mount_entry *entries = (mount_entry *) scfg->mounts->elts;
for (i = 0; i < scfg->mounts->nelts; ++i) {
const char *path_info;
mount_entry *mount = &entries[i];
if (mount_entry_matches(r->uri, mount->path, &path_info)) {
r->handler = "scgi-handler";
r->path_info = apr_pstrdup(r->pool, path_info);
r->filename = r->uri;
ap_set_module_config(r->request_config, &scgi_module, mount);
return OK;
}
}
}
return DECLINED;
}
static int scgi_map_location(request_rec *r)
{
if (r->handler && strcmp(r->handler, "scgi-handler") == 0) {
return OK; /* We don't want directory walk. */
}
return DECLINED;
}
static void log_err(const char *file, int line, request_rec *r,
apr_status_t status, const char *msg)
{
ap_log_rerror(file, line, APLOG_ERR, status, r, "scgi: %s", msg);
}
static void log_debug(const char *file, int line, request_rec *r, const
char *msg)
{
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, msg);
}
static char *http2env(apr_pool_t *p, const char *name)
{
char *env_name = apr_pstrcat(p, "HTTP_", name, NULL);
char *cp;
for (cp = env_name + 5; *cp != 0; cp++) {
if (*cp == '-') {
*cp = '_';
}
else {
*cp = apr_toupper(*cp);
}
}
return env_name;
}
static char *lookup_name(apr_table_t *t, const char *name)
{
const apr_array_header_t *hdrs_arr = apr_table_elts(t);
apr_table_entry_t *hdrs = (apr_table_entry_t *) hdrs_arr->elts;
int i;
for (i = 0; i < hdrs_arr->nelts; ++i) {
if (hdrs[i].key == NULL)
continue;
if (strcasecmp(hdrs[i].key, name) == 0)
return hdrs[i].val;
}
return NULL;
}
static char *lookup_header(request_rec *r, const char *name)
{
return lookup_name(r->headers_in, name);
}
static void add_header(apr_table_t *t, const char *name, const char *value)
{
if (name != NULL && value != NULL)
apr_table_addn(t, name, value);
}
static int find_path_info(const char *uri, const char *path_info)
{
int n;
n = strlen(uri) - strlen(path_info);
ap_assert(n >= 0);
return n;
}
/* This code is a duplicate of what's in util_script.c. We can't use
* r->unparsed_uri because it gets changed if there was a redirect. */
static char *original_uri(request_rec *r)
{
char *first, *last;
if (r->the_request == NULL) {
return (char *) apr_pcalloc(r->pool, 1);
}
first = r->the_request; /* use the request-line */
while (*first && !apr_isspace(*first)) {
++first; /* skip over the method */
}
while (apr_isspace(*first)) {
++first; /* and the space(s) */
}
last = first;
while (*last && !apr_isspace(*last)) {
++last; /* end at next whitespace */
}
return apr_pstrmemdup(r->pool, first, last - first);
}
/* buffered socket implementation (buckets are overkill) */
#define BUFFER_SIZE 8000
struct sockbuff {
apr_socket_t *sock;
char buf[BUFFER_SIZE];
int used;
};
static void binit(struct sockbuff *s, apr_socket_t *sock)
{
s->sock = sock;
s->used = 0;
}
static apr_status_t sendall(apr_socket_t *sock, char *buf, apr_size_t len)
{
apr_status_t rv;
apr_size_t n;
while (len > 0) {
n = len;
if ((rv = apr_socket_send(sock, buf, &n))) return rv;
buf += n;
len -= n;
}
return APR_SUCCESS;
}
static apr_status_t bflush(struct sockbuff *s)
{
apr_status_t rv;
ap_assert(s->used >= 0 && s->used <= BUFFER_SIZE);
if (s->used) {
if ((rv = sendall(s->sock, s->buf, s->used))) return rv;
s->used = 0;
}
return APR_SUCCESS;
}
static apr_status_t bwrite(struct sockbuff *s, char *buf, apr_size_t len)
{
apr_status_t rv;
if (len >= BUFFER_SIZE - s->used) {
if ((rv = bflush(s))) return rv;
while (len >= BUFFER_SIZE) {
if ((rv = sendall(s->sock, buf, BUFFER_SIZE))) return rv;
buf += BUFFER_SIZE;
len -= BUFFER_SIZE;
}
}
if (len > 0) {
ap_assert(len < BUFFER_SIZE - s->used);
memcpy(s->buf + s->used, buf, len);
s->used += len;
}
return APR_SUCCESS;
}
static apr_status_t bputs(struct sockbuff *s, char *buf)
{
return bwrite(s, buf, strlen(buf));
}
static apr_status_t bputc(struct sockbuff *s, char c)
{
char buf[1];
buf[0] = c;
return bwrite(s, buf, 1);
}
static apr_status_t
send_headers(request_rec *r, struct sockbuff *s)
{
/* headers to send */
apr_table_t *t;
const apr_array_header_t *hdrs_arr, *env_arr;
apr_table_entry_t *hdrs, *env;
unsigned long int n = 0;
char *buf;
int i;
apr_status_t rv = 0;
apr_port_t port = 0;
GET_PORT(port, r->connection->remote_addr);
log_debug(APLOG_MARK,r, "sending headers");
t = apr_table_make(r->pool, 40);
if (!t)
return APR_ENOMEM;
/* CONTENT_LENGTH must come first and always be present */
buf = lookup_header(r, "Content-Length");
if (buf == NULL)
buf = "0";
add_header(t, "CONTENT_LENGTH", buf);
add_header(t, "SCGI", SCGI_PROTOCOL_VERSION);
add_header(t, "SERVER_SOFTWARE", ap_get_server_version());
add_header(t, "SERVER_PROTOCOL", r->protocol);
add_header(t, "SERVER_NAME", ap_get_server_name(r));
add_header(t, "SERVER_ADMIN", r->server->server_admin);
add_header(t, "SERVER_ADDR", r->connection->local_ip);
add_header(t, "SERVER_PORT", apr_psprintf(r->pool, "%u",
ap_get_server_port(r)));
add_header(t, "REMOTE_ADDR", r->connection->remote_ip);
add_header(t, "REMOTE_PORT", apr_psprintf(r->pool, "%d", port));
add_header(t, "REMOTE_USER", r->user);
add_header(t, "REQUEST_METHOD", r->method);
add_header(t, "REQUEST_URI", original_uri(r));
add_header(t, "QUERY_STRING", r->args ? r->args : "");
if (r->path_info) {
int path_info_start = find_path_info(r->uri, r->path_info);
add_header(t, "SCRIPT_NAME", apr_pstrndup(r->pool, r->uri,
path_info_start));
add_header(t, "PATH_INFO", r->path_info);
}
else {
/* skip PATH_INFO, don't know it */
add_header(t, "SCRIPT_NAME", r->uri);
}
add_header(t, "CONTENT_TYPE", lookup_header(r, "Content-type"));
add_header(t, "DOCUMENT_ROOT", ap_document_root(r));
/* HTTP headers */
hdrs_arr = apr_table_elts(r->headers_in);
hdrs = (apr_table_entry_t *) hdrs_arr->elts;
for (i = 0; i < hdrs_arr->nelts; ++i) {
if (hdrs[i].key) {
add_header(t, http2env(r->pool, hdrs[i].key), hdrs[i].val);
}
}
/* environment variables */
env_arr = apr_table_elts(r->subprocess_env);
env = (apr_table_entry_t*) env_arr->elts;
for (i = 0; i < env_arr->nelts; ++i) {
add_header(t, env[i].key, env[i].val);
}
hdrs_arr = apr_table_elts(t);
hdrs = (apr_table_entry_t*) hdrs_arr->elts;
/* calculate length of header data (including nulls) */
for (i = 0; i < hdrs_arr->nelts; ++i) {
n += strlen(hdrs[i].key) + 1;
n += strlen(hdrs[i].val) + 1;
}
buf = apr_psprintf(r->pool, "%lu:", n);
if (!buf)
return APR_ENOMEM;
rv = bputs(s, buf);
if (rv)
return rv;
for (i = 0; i < hdrs_arr->nelts; ++i) {
rv = bputs(s, hdrs[i].key);
if (rv) return rv;
rv = bputc(s, '\0');
if (rv) return rv;
rv = bputs(s, hdrs[i].val);
if (rv) return rv;
rv = bputc(s, '\0');
if (rv) return rv;
}
rv = bputc(s, ',');
if (rv)
return rv;
return APR_SUCCESS;
}
static apr_status_t send_request_body(request_rec *r, struct sockbuff *s)
{
if (ap_should_client_block(r)) {
char buf[BUFFER_SIZE];
apr_status_t rv;
apr_off_t len;
while ((len = ap_get_client_block(r, buf, sizeof buf)) > 0) {
if ((rv = bwrite(s, buf, len))) return rv;
}
if (len == -1)
return HTTP_INTERNAL_SERVER_ERROR; /* what to return? */
}
return APR_SUCCESS;
}
#define CONFIG_VALUE(value, fallback) ((value) != UNSET ? (value) : (fallback))
static apr_status_t
open_socket(apr_socket_t **sock, request_rec *r)
{
int timeout;
int retries = 4;
int sleeptime = 1;
apr_status_t rv;
apr_sockaddr_t *sockaddr;
scgi_server_cfg *scfg = our_sconfig(r->server);
scgi_cfg *cfg = our_dconfig(r);
mount_entry *m = (mount_entry *) ap_get_module_config(r->request_config,
&scgi_module);
if (!m) {
m = &cfg->mount;
}
timeout = CONFIG_VALUE(cfg->timeout, CONFIG_VALUE(scfg->timeout,
DEFAULT_TIMEOUT));
rv = apr_sockaddr_info_get(&sockaddr,
CONFIG_VALUE(m->addr, "localhost"),
APR_UNSPEC,
CONFIG_VALUE(m->port, 4000),
0,
r->pool);
if (rv) {
log_err(APLOG_MARK, r, rv, "apr_sockaddr_info_get() error");
return rv;
}
restart:
*sock = NULL;
rv = CREATE_SOCKET(sock, sockaddr->family, r->pool);
if (rv) {
log_err(APLOG_MARK, r, rv, "apr_socket_create() error");
return rv;
}
rv = apr_socket_timeout_set(*sock, apr_time_from_sec(timeout));
if (rv) {
log_err(APLOG_MARK, r, rv, "apr_socket_timeout_set() error");
return rv;
}
rv = apr_socket_connect(*sock, sockaddr);
if (rv) {
apr_socket_close(*sock);
if ((APR_STATUS_IS_ECONNREFUSED(rv) |
APR_STATUS_IS_EINPROGRESS(rv)) && retries > 0) {
/* server may be temporarily down, retry */
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, rv, r,
"scgi: connection failed, retrying");
apr_sleep(apr_time_from_sec(sleeptime));
--retries;
sleeptime *= 2;
goto restart;
}
log_err(APLOG_MARK, r, rv, "scgi: can't connect to server");
return rv;
}
#ifdef APR_TCP_NODELAY
/* disable Nagle, we don't send small packets */
apr_socket_opt_set(*sock, APR_TCP_NODELAY, 1);
#endif
return APR_SUCCESS;
}
#ifdef AS400
static int getsfunc_BRIGADE(char *buf, int len, void *arg)
{
apr_bucket_brigade *bb = (apr_bucket_brigade *)arg;
const char *dst_end = buf + len - 1; /* leave room for terminating null */
char *dst = buf;
apr_bucket *e = APR_BRIGADE_FIRST(bb);
apr_status_t rv;
int done = 0;
while ((dst < dst_end) && !done && e != APR_BRIGADE_SENTINEL(bb)
&& !APR_BUCKET_IS_EOS(e)) {
const char *bucket_data;
apr_size_t bucket_data_len;
const char *src;
const char *src_end;
apr_bucket * next;
rv = apr_bucket_read(e, &bucket_data, &bucket_data_len,
APR_BLOCK_READ);
if (rv != APR_SUCCESS || (bucket_data_len == 0)) {
*dst = '\0';
return APR_STATUS_IS_TIMEUP(rv) ? -1 : 0;
}
src = bucket_data;
src_end = bucket_data + bucket_data_len;
while ((src < src_end) && (dst < dst_end) && !done) {
if (*src == '\n') {
done = 1;
}
else if (*src != '\r') {
*dst++ = *src;
}
src++;
}
if (src < src_end) {
apr_bucket_split(e, src - bucket_data);
}
next = APR_BUCKET_NEXT(e);
APR_BUCKET_REMOVE(e);
apr_bucket_destroy(e);
e = next;
}
*dst = 0;
return done;
}
#endif
static int scgi_handler(request_rec *r)
{
apr_status_t rv = 0;
int http_status = 0;
struct sockbuff s;
apr_socket_t *sock;
apr_bucket_brigade *bb = NULL;
apr_bucket *b = NULL;
const char *location;
if (strcmp(r->handler, "scgi-handler"))
return DECLINED;
http_status = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
if (http_status != OK)
return http_status;
log_debug(APLOG_MARK, r, "connecting to server");
rv = open_socket(&sock, r);
if (rv) {
return HTTP_INTERNAL_SERVER_ERROR;
}
binit(&s, sock);
rv = send_headers(r, &s);
if (rv) {
log_err(APLOG_MARK, r, rv, "error sending request headers");
return HTTP_INTERNAL_SERVER_ERROR;
}
rv = send_request_body(r, &s);
if (rv) {
log_err(APLOG_MARK, r, rv, "error sending request body");
return HTTP_INTERNAL_SERVER_ERROR;
}
rv = bflush(&s);
if (rv) {
log_err(APLOG_MARK, r, rv, "error sending request");
return HTTP_INTERNAL_SERVER_ERROR;
}
log_debug(APLOG_MARK, r, "reading response headers");
bb = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc);
b = apr_bucket_socket_create(sock, r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
b = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
#ifdef AS400
rv = ap_scan_script_header_err_core(r, NULL, getsfunc_BRIGADE, bb);
#else
rv = ap_scan_script_header_err_brigade(r, bb, NULL);
#endif
if (rv) {
if (rv == HTTP_INTERNAL_SERVER_ERROR) {
log_err(APLOG_MARK, r, rv, "error reading response headers");
}
else {
/* Work around an Apache bug whereby the returned status is
* ignored and status_line is used instead. This bug is
* present at least in 2.0.54.
*/
r->status_line = NULL;
}
apr_brigade_destroy(bb);
return rv;
}
location = apr_table_get(r->headers_out, "Location");
if (location && location[0] == '/' &&
((r->status == HTTP_OK) || ap_is_HTTP_REDIRECT(r->status))) {
apr_brigade_destroy(bb);
/* Internal redirect -- fake-up a pseudo-request */
r->status = HTTP_OK;
/* This redirect needs to be a GET no matter what the original
* method was.
*/
r->method = apr_pstrdup(r->pool, "GET");
r->method_number = M_GET;
/* We already read the message body (if any), so don't allow
* the redirected request to think it has one. We can ignore
* Transfer-Encoding, since we used REQUEST_CHUNKED_ERROR.
*/
apr_table_unset(r->headers_in, "Content-Length");
ap_internal_redirect_handler(location, r);
return OK;
}
rv = ap_pass_brigade(r->output_filters, bb);
if (rv) {
log_err(APLOG_MARK, r, rv, "ap_pass_brigade()");
return HTTP_INTERNAL_SERVER_ERROR;
}
return OK;
}
static int scgi_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
server_rec *base_server)
{
ap_add_version_component(p, "mod_scgi/" MOD_SCGI_VERSION);
return OK;
}
static void *
create_dir_config(apr_pool_t *p, char *dirspec)
{
scgi_cfg *cfg = apr_pcalloc(p, sizeof(scgi_cfg));
cfg->enabled = UNSET;
cfg->mount.addr = UNSET;
cfg->mount.port = UNSET;
cfg->timeout = UNSET;
return cfg;
}
#define MERGE(b, n, a) (n->a == UNSET ? b->a : n->a)
static void *
merge_dir_config(apr_pool_t *p, void *basev, void *newv)
{
scgi_cfg* cfg = apr_pcalloc(p, sizeof(scgi_cfg));
scgi_cfg* base = basev;
scgi_cfg* new = newv;
cfg->enabled = MERGE(base, new, enabled);
cfg->mount.addr = MERGE(base, new, mount.addr);
cfg->mount.port = MERGE(base, new, mount.port);
cfg->timeout = MERGE(base, new, timeout);
return cfg;
}
static void *
create_server_config(apr_pool_t *p, server_rec *s)
{
scgi_server_cfg *c =
(scgi_server_cfg *) apr_pcalloc(p, sizeof(scgi_server_cfg));
c->mounts = apr_array_make(p, 20, sizeof(mount_entry));
c->timeout = UNSET;
return c;
}
static void *
merge_server_config(apr_pool_t *p, void *basev, void *overridesv)
{
scgi_server_cfg *c = (scgi_server_cfg *)
apr_pcalloc(p, sizeof(scgi_server_cfg));
scgi_server_cfg *base = (scgi_server_cfg *) basev;
scgi_server_cfg *overrides = (scgi_server_cfg *) overridesv;
c->mounts = apr_array_append(p, overrides->mounts, base->mounts);
c->timeout = MERGE(base, overrides, timeout);
return c;
}
static const char *
cmd_mount(cmd_parms *cmd, void *dummy, const char *path, const char *addr)
{
int n;
apr_status_t rv;
char *scope_id = NULL; /* A ip6 parameter - not used here. */
scgi_server_cfg *scfg = our_sconfig(cmd->server);
mount_entry *new = apr_array_push(scfg->mounts);
n = strlen(path);
while (n > 0 && path[n-1] == '/') {
n--; /* strip trailing slashes */
}
new->path = apr_pstrndup(cmd->pool, path, n);
rv = apr_parse_addr_port(&new->addr, &scope_id, &new->port, addr,
cmd->pool);
if (rv)
return "error parsing address:port string";
return NULL;
}
static const char *
cmd_server(cmd_parms *cmd, void *pcfg, const char *addr_and_port)
{
apr_status_t rv;
scgi_cfg *cfg = pcfg;
char *scope_id = NULL; /* A ip6 parameter - not used here. */
if (cmd->path == NULL)
return "not a server command";
rv = apr_parse_addr_port(&cfg->mount.addr, &scope_id, &cfg->mount.port,
addr_and_port, cmd->pool);
if (rv)
return "error parsing address:port string";
return NULL;
}
static const char *
cmd_handler(cmd_parms* cmd, void* pcfg, int flag)
{
scgi_cfg *cfg = pcfg;
if (cmd->path == NULL) /* server command */
return "not a server command";
if (flag)
cfg->enabled = ENABLED;
else
cfg->enabled = DISABLED;
return NULL;
}
static const char *
cmd_timeout(cmd_parms *cmd, void* pcfg, const char *strtimeout)
{
scgi_cfg *dcfg = pcfg;
int timeout = atoi(strtimeout);
if (cmd->path == NULL) {
scgi_server_cfg *scfg = our_sconfig(cmd->server);
scfg->timeout = timeout;
}
else {
dcfg->timeout = timeout;
}
return NULL;
}
static const command_rec scgi_cmds[] =
{
AP_INIT_TAKE2("SCGIMount", cmd_mount, NULL, RSRC_CONF,
"path prefix and address of SCGI server"),
AP_INIT_TAKE1("SCGIServer", cmd_server, NULL, ACCESS_CONF,
"Address and port of an SCGI server (e.g. localhost:4000)"),
AP_INIT_FLAG( "SCGIHandler", cmd_handler, NULL, ACCESS_CONF,
"On or Off to enable or disable the SCGI handler"),
AP_INIT_TAKE1("SCGIServerTimeout", cmd_timeout, NULL, ACCESS_CONF|RSRC_CONF,
"Timeout (in seconds) for communication with the SCGI server."),
{NULL}
};
static void scgi_register_hooks(apr_pool_t *p)
{
ap_hook_post_config(scgi_init, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_handler(scgi_handler, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_translate_name(scgi_translate, NULL, NULL, APR_HOOK_LAST);
ap_hook_map_to_storage(scgi_map_location, NULL, NULL, APR_HOOK_FIRST);
}
/* Dispatch list for API hooks */
module AP_MODULE_DECLARE_DATA scgi_module = {
STANDARD20_MODULE_STUFF,
create_dir_config, /* create per-dir config structs */
merge_dir_config, /* merge per-dir config structs */
create_server_config, /* create per-server config structs */
merge_server_config, /* merge per-server config structs */
scgi_cmds, /* table of config file commands */
scgi_register_hooks, /* register hooks */
};
UPDATE to the UPDATE:
I have narrowed down the problem to the following Error Message MCH3601:
MCH3601 Escape 40 06/05/15 15:41:10.884937 MOD_SCGI QGPL *STMT MOD_SCGI QGPL *STMT
From module . . . . . . . . : MOD_SCGI
From procedure . . . . . . : our_dconfig
Statement . . . . . . . . . : 1
To module . . . . . . . . . : MOD_SCGI
To procedure . . . . . . . : our_dconfig
Statement . . . . . . . . . : 1
Thread . . . . : 00000039
Message . . . . : Pointer not set for location referenced.
Cause . . . . . : A pointer was used, either directly or as a basing
pointer, that has not been set to an address.
It looks like the web server is actually Apache, not WAS. What does the Apache log say?
Is the Apache user profile authorised to the mod_scgi service program, and to the library QGPL?
in the following code when ran will produce a Segmentation Fault, due to a FILE* being passed to fclose which contains no address (NULL).
I'm wondering why this is happening, the FILE* isn't being used what so over.
The FILE* is named urandom and is passed to fclose in the main function.
Thanks
#include <stdio.h>
#include <stdlib.h>
struct property
{
char *name;
unsigned int value;
unsigned int owner;
unsigned int type;
};
struct player
{
unsigned int id;
unsigned int money;
unsigned int position;
};
int rollDice(FILE *);
int amountOfLines(FILE *);
int createArrayOfPtrs(int ,void ***);
int makeArryOfPropertyPtrs(int ,struct property **);
int FillArryPropertyData(struct property **,int ,FILE *);
int splitBuffer(char *,unsigned int *,char **);
int bufferPropertyFile(FILE *,char **,int );
i nt fillPropertyStruct(struct property *,unsigned int ,char *);
int main(void)
{
int linesInPropertyFile = 0;
struct property **arrayForProperties = 0;
//Open /dev/urandom for rollDice
FILE *urandom = fopen("/dev/urandom","rb");
FILE *propertyFile = fopen("/home/jordan/Documents/Programming/Monopoly Project/properties","rb");
if(propertyFile == NULL || urandom == NULL)
{
puts("ERROR: error in opening file(s)");
return 1;
}
linesInPropertyFile = amountOfLines(propertyFile);
//DEBUG
printf("%d is contained within \"linesInPropertyFile\"\n",linesInPropertyFile);
if(createArrayOfPtrs(linesInPropertyFile,(void ***)&arrayForProperties))
{
puts("ERROR: error from createArrayOfPointers()");
return 1;
}
//DEBUG
printf("Outside Pointer: %p\n",arrayForProperties);
if(makeArryOfPropertyPtrs(linesInPropertyFile,arrayForProperties))
{
puts("ERROR: error from createArrayOfPointersForProperties()");
return 1;
}
if(FillArryPropertyData(arrayForProperties,linesInPropertyFile,propertyFile))
{
puts("ERROR: error from FillArryPropertyData()");
}
//Close FILE stream for /dev/urandom
fclose(urandom);
fclose(propertyFile);
return 0;
}
int FillArryPropertyData(struct property **array,int amntOfProperties,FILE *fp)
{
int bufferUsed = 100;
int i = 0;
int returnValue = 0;
int returnValue2 = 0;
unsigned int money = 0;
char *name;
char *buffer;
rewind(fp);
while(returnValue == 0)
{
buffer = malloc(bufferUsed);
returnValue = bufferPropertyFile(fp,&buffer,bufferUsed);
if(returnValue && returnValue != -1)
{
puts("ERROR: error from bufferPropertyFile()");
return -1;
}
if(returnValue == -1)
{
break;
}
if(buffer[0] != '\0')
{
returnValue2 = splitBuffer(buffer,&money,&name);
}
if(returnValue2)
{
puts("ERROR: error in splitBuffer()");
return 1;
}
if(fillPropertyStruct(array[i],money,name))
{
puts("ERROR: error in fillPropertyStruct()");
return 1;
}
money = 0;
i++;
}
free(buffer);
return 0;
}
int fillPropertyStruct(struct property *array,unsigned int money,char *name)
{
int nameSize = 100;
int i = 0;
array->name = malloc(nameSize);
array->value = money;
while(1)
{
if(i >= nameSize)
{
void *tmp = realloc(array->name,nameSize * 2);
nameSize *= 2;
if(tmp)
{
array->name = tmp;
}
else
{
return -1;
}
}
if(name[i] == '\0')
{
break;
}
array->name[i] = name[i];
i++;
}
array->name[i] = '\0';
return 0;
}
int splitBuffer(char *buffer,unsigned int *money,char **name)
{
int i = 0;
int j = 1;
int nameSize = 100;
*name = malloc(nameSize);
while(1)
{
if(buffer[j] != '"')
{
(*name)[j-1] = buffer[j];
}
else
{
i++;
}
j++;
if(i)
{
break;
}
if(j >= nameSize)
{
void *tmp = 0;
tmp = realloc(*name,nameSize * 2);
nameSize = nameSize * 2;
if(tmp != NULL)
{
*name = tmp;
}
else
{
puts("ERROR: error in splitBuffer");
return -1;
}
}
}
name[j-1] = '\0';
while(buffer[j] != '$')
{
if(buffer[j] == '\0')
{
puts("ERROR: error in splitBuffer()");
return -2;
}
j++;
}
j++;
while(buffer[j] != '\0')
{
*money += (buffer[j] - '0');
if(buffer[j+1] != '\0')
{
*money *= 10;
}
j++;
}
printf("BUFFER: %s\n",buffer);
printf("NAME: %s\n",*name);
printf("MONEY: %d\n",*money);
return 0;
}
int bufferPropertyFile(FILE *fp,char **buffer,int i)
{
int j = (i - i);
if(feof(fp))
{
//-1 Returned if EOF detected
return -1;
}
char retr = 0;
while(1)
{
if(j + 1 >= i)
{
void *tmp = realloc(*buffer,i * 2);
if(tmp != NULL)
{
*buffer = tmp;
i = i * 2;
}
else
{
puts("ERROR: error in bufferPropertyFile()");
return -2;
}
}
retr = fgetc(fp);
if(retr == '\n' || feof(fp))
{
break;
}
(*buffer)[j] = retr;
j++;
}
(*buffer)[j] = '\0';
if(**buffer == '\0')
{
return -1;
}
return 0;
}
int rollDice(FILE *fp)
{
int seed = fgetc(fp);
srand(seed);
return (rand() % 6) + 1;
}
int amountOfLines(FILE *file)
{
int i = 0;
int retr = 0;
while(1)
{
retr = fgetc(file);
if(retr == EOF)
{
break;
}
if(retr == '\n' )
{
i++;
}
}
return i;
}
int createArrayOfPtrs(int numberOfPointers,void ***pointer)
{
void *tmp = malloc(numberOfPointers * sizeof (tmp));
if(tmp != NULL)
{
*pointer = tmp;
//DEBUG
printf("Pointer: %p\n",*pointer);
}
else
{
return 1;
}
return 0;
}
int makeArryOfPropertyPtrs(int numberOfPointers,struct property **pointer)
{
int i = 0;
void *tmp;
for(i = 0;i < numberOfPointers;i++)
{
tmp = malloc(sizeof(struct property));
if(tmp == NULL)
{
return 1;
}
pointer[i] = (struct property *)tmp;
}
return 0;
}
here it givest an access violation in splitBuffer on this line:
name[j-1]='\0';
which probably should be
(*name)[j-1]='\0';
indeed that memory is not allocated anywhere, in other words, undefined behaviour, which indeed in your case might overwrite the urandom variable: both urandom and name are allocated on stack so depending on value of j it might write over urandom..
apart from that, there might be more errors, the number and use of pointers/mallocs/reallocs and lack of frees is a bit scary
int createArrayOfPtrs(int ,void ***);
if(createArrayOfPtrs(linesInPropertyFile,(void ***)&arrayForProperties))
This is undefined behaviour, a (void***) is not compatible to a (struct property ***). Why do you even use it here, all the other functions use struct property pointers?
Since the array is located right before the file pointer in the local variables of main, maybe the problem is that the array creation/initialization overwrites urandom?