Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Can one of you C guru's help me please???

Status
Not open for further replies.

jdechirico

Programmer
Jul 11, 2006
13
US
am a new to this board and came here out of desparation....

I need to modifiy a C program to allow the workareas (there could be up to 30) it uses to be defined externally and passed to the C program, also I need to pass the lengths of the work areas.

I have exhausted my limited knowledge of C is there any of you folks that can provide some assistance.

I will tell you right now, i am one of those old dinosaurs that still writes programs in machine language and I guess C is just to modern for me to understand.

Thanks for any help provided.
 
1) What is a workarea? Is it an array of some sort? How are the workareas and their lengths defined?
2) Please post the prototype of the function these workareas are supposed to be passed into.
 
xwb, thanks for the response....

Now the question is how do we establish a common frame of reference...

Lets say that I have program called abc it reads data from a disk file into what I call a workarea or buffer and I guess you would call an array, program abc also saves the length of the data read in a variable.

Next I have a program x123 which is called by program abc, program x123 needs to be passed the address of the workarea (array) that program abc read data into, it also needs to be passed the length of the data in the workarea (array).

Once program x123 is called it operates on the passed workarea(array) from program abc (it may also change length of the data in the passed array by adding more information) once its completed it returns control to program abc which will write the updated workarea(array) for the updated length to an output file.

Does this help?
 
xwb...

I missed your item #2, and now i will show my ignorance, whats a prototype of a function???

Like i said at the beginning, i am not up on these new fangled programming languages...

 
jdechirico said:
i am not up on these new fangled programming languages

LOL, C's only been around 30 years or so.

I believe if you want to share memory addresses between separate processes (it sounds like thats what you mean you want to do), then you'll need to look into shared memory and IPC.

BTW, you don't state your OS and compiler ...

--------------------------------------------------
Free Java/J2EE Database Connection Pooling Software
 
xwb, 30 years huh, i wrote my first application in 1968 in a language called fargo.... long time

anyway, the c functions are running on an ibm mainframe under z/os 1.7 the c compiler is ibm's c.

so, whats ipc and how does one use shared memory?

I will tell you that I have not really gotten into this app, there is a lot more after i figure out how to get data into and out of the c program, perhaps i could use one of those plumbers helpers...

Thanks....
 
Do you really need x123 to be a separate program, or can it be a function within your abc program?
For example:
Code:
void x123( int* workarea, int size );  /* This is a function prototype. */

int main( int argc, char* argv[] )
{
   int i;
   int* workarea;  /* An array of integers. */

   workarea = malloc(100 * sizeof(int));  /* Allocate enough memory for 100 integers. */

   /* Fill workarea with numbers 0 to 99. */
   for ( i = 0; i < 100; ++i )
   {
      workarea[i] = i;
   }

   x123( workarea );
   return 0;
}

void x123( int* workarea, int size )
{
   int i;

   workarea = realloc( size * 2 );  /* Allocate twice as much memory. */

   /*  Append numbers 100 to 199 to the end of the array. */
   for ( i = 100; i < 200; ++i )
   {
      workarea[i] = i;
   }
}
 
Is Z/OS the new variant of MVS?

See cpjust's posting on prototypes. Do you have something similar to this on your system?
 
to cpjust,

yep program 123 needs to be a separate program, infact program 123 is written in assembler language because its functioning at the operating system level, it has a twin called 456 which does the inverse of the functions that 123 does.

the reason for two programs it KISS, to me a program does one thing, it may add 1+1 or move a character string from one point in a record to another. I know that there are those who insist that having such granular programs increases maintainance, but i have found that the less complex a program is the less likely it is to fail, your less likely to introduce errors during coding and if it does fail its much easier to isolate the problem, which most of the time is caused by a creative end user.

to xmb,

yep z/os 1.7 one of the newer variants of what was mvs


to both of you... i appologize for being so cryptic but i am walking a fine line here and trying to avoid giving away company secrets... they will fire your ass for doing that.
 
ok, let me take a different approach...

My c program is being called by another program and is being passed a string of characters which represnet a "key",

how do i capture that string of characters in my c program?

currently the "key" value is hard coded as:

static unsigned char xxxKeyData[10] = {
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12
};

how do i capture the passed "key" value and set xxxKeyData to the passed string, also, the length of the key should also be passed and may not necessarily be 10.

Thanks

Jdechirico
 
If you are passing the data to your program like this:

abc arg1 arg2 arg3

In your main() function, the argc parameter contains the number of arguments that were passed (3), and argv is an array of strings { "arg1", "arg2", "arg3" }
Code:
#include <stdio.h>

int main( int argc, char* argv[] )
{
   int i;

   printf( "There are %d arguments.", argc );
   printf( "argv[0] should always be the name of your program as it was run on a command line: %s", argv[0] );

   for ( i = 1; i <= argc; ++i )
   {
      printf( "argv[%d] = %s", i, argv[i] );
   }

   return 0;
}
 
a little more info on the "key" question from above

there is a little more existing code as follows:

ITEM xxxKeyItem = {NULL, 0};
xxxKeyItem.data = xxxKeyData;
xxxKeyItem.len = xxxKeyDataLen;

so to relate back to the previous post how can i set the xxxkeyitem.data and xxxkeyitem.len to the args passed to the program?
 
How are the args being passed to the program?
What does the ITEM struct look like? I'm guessing it's probably something like this:
Code:
struct ITEM
{
   char* data;   /* or char data[some number]; */
   unsigned int len;
};

Is the program being run from OMVS, TSO, JCL...?
An example of how you plan to invoke the program would be useful.
 
cpjust....

Ok, i will bore you to tears now...

I wish i had a white board to show a more complete flow.... but...

First, this entire process is run in batch on a z/os 1.7.

Next, at the highest level in an assembler language program (A0) that reads a file and creates buffers consisting of multiple logical records

Then it calls the C function (C1) we have been talking about, on the initial call the key and its length are passed to the C program along with the length of the data blocks which will be passed to the C program (C1).

The C program (C1) then begins to execute it allocates its buffers (arrays) based upon the length passed and reaches a point where the key has been processed and its ready to process data.

Top of Loop:

The C program (C1) then calls an external routine (A1) passing the address of its io buffer (array) which pulls data from the original assembler program (A0) and moves it into the passed io buffer and passes back the length of the data in the buffer or passes back an end of file flag.

The assembler program (A1) then returns to the C program (C1) which operates on the data buffer passed back from the assembler program or branchs to End of File: when end of file is set by program (A1).

At some point the C program (C1) wants to write the massaged data buffer out to a file, so it calls another external program assembler (A3) and passes the address of the massaged data buffer and the data length as parameters.

The program (A3) pushes the data back to original assembler program (A0) which actually writes the data back to an output file and the the original assembler program (A0) reads constructs the next data buffer which will be made available to assembler program (A1) later, or it may set a switch that program (A1) will recoginze as end of file flag and pass that indication back C program (C1) later. Program (A2) then returns to program (C1).

Program (C1) then branches to Top of Loop:

End of File:

Program (C1) frees any memory allocated and returns to the original program (A0) which then closes its input and output files and terminates.

This is an extream over simplification of the execution flow in that there is another asssembler program layer (S0) between the calling program (A0) and the C program (C1), the layer (S0) functions as a server attaching multiple instances of program (C1) to permit the processing of multiple files concurrently. I left this layer out to avoid mass confusion.

This entire process is working now except that C program (C1) is currently written in Cobol. This Cobol program needs to be rewritten into C because of the inclusion of a 3rd party tool kit which is written in C and whose functions need to be invoked from a C program.

Sorry if I put you to sleep.

 
I've only been using z/OS for a few months (not programming on it, just using), so I don't know how much help I can provide.
In the "z/OS V1R7.0 Language Environment Programming Reference" book I see in section 2.2.3.3 they talk about invoking callable services from C/C++, and 2.2.5 has a list of the callable services. I'm not sure if any of those services would allow you to share memory or use that bizzare DD syntax that JCL scripts use?

IARVSERV sounds like it would probably be the MVS assembler instruction to use for sharing memory, but I don't have a clue how you'd call that from a C program?

Actually, I think I just found the right functions for you to use... In the "Z/OS V1R7.0 XL C/C++ Run-Time Library Reference" book, in section 3, take a look at the shmat(), shmctl(), shmdt() & shmget() functions.
 
I'm an ex-assembler programmer and consequently I wonder if you're making assumptions about C.
In assembler you might need to keep the key and the length of the key as two separate items since you may have no other way of knowing where the key ends.
In C we usually use NULL terminated strings meaning that there is one extra byte after the data with a binary value of zero.
So long as our data will never contain a null byte we're safe.
If it does then obviously we would have to resort to keeping the length as well as you have suggested.
Now your key is hex so you could pass the whole hex string as a single param if you wanted and break it up in the C program:
Code:
cprogramname 090a0b0c0d0e0f101112
That way you would never have the worry of trying to embed null characters or any other bytes for that matter that your os would not like.
The param would appear as the first arg in "argv" and be null terminated so you would simply have to write a little function that reads that and converts each pair into a byte and stores it in your structure. Obviously it could count as it goes and store the length as well.
If you need help with that routine I suggest you drop another post and I or another will probably write a sampe for you.


Trojan.
 
TrojanWarBlade....

The only assumption I have made is that the program is becomming more and more difficult.

Any suggestions or comments are greatly appreciated.

Thanks
 
OK, I wrote a quick key grabber for you:
Code:
#include <stdio.h>

/* Structure to hold key */
struct KEY
{
       unsigned char* data;
       unsigned int   len;
};

/* Function to store hex key as binary in key strcuture */
void interpret_key(struct KEY *k, char *c)
{
    int index = 0;
    k->len    = 0;
    do {
        int byte = 0;
        sscanf(c, "%2x", &byte);
        k->data[k->len++] = (unsigned char) byte;
        c += 2;
    } while(*c);
}




int main(int argc, char **argv)
{
    struct KEY k;
    /* Test for param to process as key */
    if(argc < 2) {
        fprintf(stderr, "Please supply a key to process\n");
        exit(1);
    }
    /* Ensure key has even number of bytes */
    if(strlen(argv[1]) % 2) {
        fprintf(stderr, "Invalid key.\n");
        exit(2);
    }
    /* Allocate space for key */
    k.data = (unsigned char *)malloc(strlen(argv[1])/2);
    /* Convert from hex to binary and store in key structure */
    interpret_key(&k, argv[1]);
    /* Use key here. */
    printf("Got a key with length of %d\n", k.len);
    /* Finished */
    return 0;
}

Assuming you call the program key.c and build an executable of key you can call it like this:
Code:
./key 090a0b0c0d0e0f101112
What you decide to do with your key after that is up to you.


Trojan.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top