Calling C from COBOL: trouble with stderr - c

From my COBOL program, I'm calling my C module which itself makes calls to a proprietary library. This library insists on writing to stderr, although there's no stderr available since the main program is written in COBOL. Consequently, the program aborts with this message:
cannnot open stderr
The support guys at HP advised me to issue
PARAM SAVE-ENVIRONMENT ON
in TACL before running the program. This indeed solved my problem. However, my program will be used by several people in a number of scripts and I don't want to force them to issue PARAM SAVE-ENVIRONMENT ON prior to running the program.
Is there some COBOL85 directive which allows me to properly run the program without changing any parameters manually? Something like
?PARAM SAVE-ENVIRONMENT ON
would be great...
EDIT:
Since I'm able to modify the C module (not the library), I'd be completely satisfied with a C-based solution. However, simply opening stderr before calling the library didn't solve my problem.

If you can execute TACL commands from Cobol, that could do it.
Can you open a file in Cobol assinged to stderr? Perhaps discovering exactly what PARAM SAVE-ENVIRONMENT ON does might help as well.
Most of the C contributors are not going to know the operating system on the HP/Tandem, which is going to impact the worth of answers. I have no idea if you can "shell out" from your C program to issue a TACL command or run a TACL script.
A bit of research with your Cobol, TACL, and C manuals for the HP/Tandem might lead you to answers, perhaps a google or two as well.
What is the problem with including the statement in their scripts anyway? If they want the program to work?

Not being an HP NonStop developer, I have some questions. stderr is a special symbol in C. File channel 2 (0 standard in, 1 standard out, 2 standard error), but those are low level channel numbers. stderr is a default pointer to a FILE structure. Falling back to GNU/Linux, /usr/include/stdio.h defines them as
/* Standard streams. */
extern struct _IO_FILE *stdin; /* Standard input stream. */
extern struct _IO_FILE *stdout; /* Standard output stream. */
extern struct _IO_FILE *stderr; /* Standard error output stream. */
/* C89/C99 say they're macros. Make them happy. */
#define stdin stdin
#define stdout stdout
#define stderr stderr
Opening a file named "stderr" isn't the same thing. Any process that is created should have 0, 1, and 2 already open. Should not matter what programming language is used for main. Is HP NonStop that much different than other POSIX-ey systems? stderr (the FILE pointer) is usually global to any code that includes stdio.h
As an aside, coming from an OpenCOBOL and GNU/Linux fanboy:
Regarding your other comment on lessons learned,
DO mix COBOL and C (and Fortran, and Ada, and Vala, and Python, and Java and ...)
DO use COBOL

PARAM SAVE-ENVIRONMENT ON makes HP COBOL-programs save environment variables (which they receive as messages at startup from Guardian) for future calls to getenv() from C modules.
Actually, the library I'm using tries to open stderr because it can't read environment variables. One solution is to set the PARAM SAVE-ENVIRONMENT to ON, so getenv() will properly function again. This has to be done in each TACL session.
Unless: you use the ?SAVE STARTUP- or ?SAVE ALL-directive in your COBOL program to achieve the same effect.
Lessons learned:
Don't mix COBOL and C.
Don't use COBOL at all.

Related

Linux- C program

I have recently(yesterday) started trying to learn linux and to program in this os. Now, one interesting and probably easy problem I came across while surfing the net was something like this:
Consider a C program that takes a directory as an argument in the command line and calculates the sum of all the files' dimensions that are in the directory's tree.
Now, due to the fact that I've been doing a lot of reading and researching in a short matter of time, all my knowledge is piled up in my brian creating a cloud of confusion. If anyone could help me with the code, I'd be really thankful.
what you are asking is a basic task. It can be done in linux but can also be done in microsoft windows with minor code tweaks if you are writing a program in C or C++. you would be writing code, which is sort of at a lower level compared to other ways of doing it, to accomplish what you want.
However you don't need to write a program C, which then requires you to compile it into an executable. Because what you are asking is a basic task, you might be able to do it with a bash shell script which would be linux specific. And if you wanted to do this in Windows then you would write a .bat file which is either the DOS scripting language, or Windows Powershell. I am not that familiar with Windows, i only mention it to help give you a general understanding for "all the knowledge piled up in your brain creating a cloud of confusion".
There is the windirstat program which runs under Microsoft Windows, can get it free from sourceforge and I think it does mostly what you are asking. I am not sure if you can get source code for it.
For linux there is kdirstat and that you can get the source code for from
http://kdirstat.cvs.sourceforge.net/viewvc/kdirstat/
you can download it as GNU tarball.
Look at how that program is written, which is C++ as you'll see a bunch of .cpp files. That would be a good template to work off of, and you can see what libraries they are using to accomplish file system functions. There are 21 .cpp files, look at the file kdirstatmain.cpp first.
For C/C++ code the start of execution is with the function int main(int argc, char *argv[]).
Regarding accomplishing this task with a bash shell script in linux, the best i can tell you is web search on bash shell scripting for linux.
And in linux to calculate the sum of all the files' dimensions that are in the directory's tree we can quickly do that at the linux prompt with the du -sh . command. In linux at the prompt do man du so read about the disk usage command. And then consider looking for the source code for du to use it as a template, and work off how they implemented du to learn and then modify their ways to meet your needs.
linux du command source code
Use opendir(3) to "open" the directory. Since you are interested in learning how to program in GNU/Linux, start by typing man opendir in the terminal to read how this function works. The (3) in opendir(3) means that the help for this function can be found in the section 3 of the manpages. Notice, at the top of the page, that the manpage tells you which #includes you'll need.
If everything goes right, opendir(3) will return a DIR* object. To know which files or subdirectories it contains, you use this object with readdir(3). This should return a pointer of type struct dirent*. You can heck the manual pages for details on the fields of this structure, but the most important for you will probably be d_type and d_name. A second call to this function will return the next entry. When it returns NULL, that either means you have read all files or an error occurred. To know which happened, you should check errno.
Here's a short example that list all entries in /tmp:
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
int main(void)
{
DIR *dir;
struct dirent *entry;
dir = opendir("/tmp");
/* should check if dir != NULL */
while ((entry = readdir(dir)) != NULL) {
printf("Found %s\n", entry->d_name);
}
/* You may want to check errno here to see if readdir returned
* NULL because all files were read or because of some error;
* but this is beyond the purposes of my example.
*/
closedir(dir);
return 0;
}
Now you have to process each entry. If it is a directory, you have to descend into it an read its contents. A recursive function will probably help you here. If it is a file, then you have at least two options:
Open it with fopen(3), then use fseek(3) to seek the end of file. Use the return value of fseek(3) to calculate the size of the file in bytes;
Use stat(2) to get a structure with information on the file. Do not confuse it with stat(1). If you simply type man stat, you'll get information about the latter. To force man to read from section 2, type man 2 stat in the command line.
The first approach is certainly simpler. The second will require you to do a bit of reading on how stat(2) works. My advice: you should do it. Not only because it's more in the lines of Linux, but also because it gives you information that fseek(3) doesn't give. For instance, you can use stat(2) to see not only how many bytes the file contains, but how many bytes it occupies in the disk (like du does).
While reading the directory, you may stumble on other types of entries other than files and directories. stat(2) will probably help you figure the sizes of them as well. But you may want to simply ignore them for now.

How to display a custom prompt during the execution of C program?

I'm trying to emulate a terminal using a C program in Linux and need my program to display a custom prompt while the program executes. Is there a way to display it using my C program? (I can always try to printf "My-prompt" every line manually, but I'm looking for a better way). Also I can't use any additional libraries other than the basic ones so GNU Readline library and editline library wouldn't work (as suggested in another thread).
for example:
user#mypc:~$ ./a.out
my_custom_prompt>3+5
my_custom_prompt>8
my_custom_prompt>exit
user#mypc:~$
I believe what the OP wants is to simply have the "prompt" printed along with any program output, without having to add this manually every time. There is a way to do this, if you write a wrapper function on top of printf to do this, and call that instead of printf directly.
Probably this will help: http://www.ozzu.com/cpp-tutorials/tutorial-writing-custom-printf-wrapper-function-t89166.html
In your example, you already have got a terminal. You want to write a command-line interface with a prompt, not a terminal.
I can always try to printf "My-prompt" every line manually, but I'm looking for a better way
There’s nothing wrong with this approach. You have a loop which prints the prompt and waits for input afterwards. As Kunerd said in the comment, one line of code.
Normally, a prompt is printed to stderr rather than stdout. This has the advantage, that the prompt appears before a newline is written, as stderr is unbuffered (and in combination with piping and redirection it seems reasonable to me, that this stuff doesn’t go to the same stream as the actual output).
Also I can't use any additional libraries other than the basic ones so GNU Readline library and Editline library wouldn't work
Doing this in a way strictly conforming to the C standard and not using any libraries but the standard one makes things like line editing (other than using backspace) or a command history (close to) impossible. If that’s OK for you, look for fgets etc. and keep in mind, that stdin is usually line-buffered.
POSIX specifies some additional properties of terminals, see e.g. http://pubs.opengroup.org/onlinepubs/9699919799/. Maybe curses is also of interest for you.
Perhaps you're looking for fgets() documentation?

hidden routines linked in c program

Hullo,
When one disasembly some win32 exe prog compiled by c compiler it
shows that some compilers links some 'hidden' routines in it -
i think even if c program is an empty one and has a 5 bytes or so.
I understand that such 5 bytes is enveloped in PE .exe format but
why to put some routines - it seem not necessary for me and even
somewhat annoys me. What is that? Can it be omitted? As i understand
c program (not speaking about c++ right now which i know has some
initial routines) should not need such complementary hidden functions..
Much tnx for answer, maybe even some extended info link, cause this
topic interests me much
//edit
ok here it is some disasembly Ive done way back then
(digital mars and old borland commandline (i have tested also)
both make much more code, (and Im specialli interested in bcc32)
but they do not include readable names/symbols in such dissassembly
so i will not post them here
thesse are somewhat readable - but i am not experienced in understending
what it is ;-)
https://dl.dropbox.com/u/42887985/prog_devcpp.htm
https://dl.dropbox.com/u/42887985/prog_lcc.htm
https://dl.dropbox.com/u/42887985/prog_mingw.htm
https://dl.dropbox.com/u/42887985/prog_pelles.htm
some explanatory comments whats that heere?
(I am afraid maybe there is some c++ sh*t here, I am
interested in pure c addons not c++ though,
but too tired now to assure that it was compiled in c
mode, extension of compiled empty-main prog was c
so I was thinking it will be output in c not c++)
tnx for longer explanations what it is
Since your win32 exe file is a dynamically linked object file, it will contain the necessary data needed by the dynamic linker to do its job, such as names of libraries to link to, and symbols that need resolving.
Even a program with an empty main() will link with the c-runtime and kernel32.dll libraries (and probably others? - a while since I last did Win32 dev).
You should also be aware that main() is only the entry point of your program - quite a bit has already gone on before this point such as retrieving and tokening the command-line, setting up the locale, creating stderr, stdin, and stdout and setting up the other mechanism required by the c-runtime library such a at_exit(). Similarly, when your main() returns, the runtime does some clean-up - and at the very least needs to call the kernel to tell it that you're done.
As to whether it's necessary? Yes, unless you fancy writing your own program prologue and epilogue each time. There are probably are ways of writing minimal, statically linked applications if you're sufficiently masochistic.
As for storage overhead, why are you getting so worked up? It's not enough to worry about.
There are several initialization functions that load whenever you run a program on Windows. These functions, among other things, call the main() function that you write - which is why you need either a main() or WinMain() function for your program to run. I'm not aware of other included functions though. Do you have some disassembly to show?
You don't have much detail to go on but I think most of what you're seeing is probably the routines of the specific C runtime library that your compiler works with.
For instance there will be code enabling it to run from the entry point 'main' which portable executable format understands to call the main(char ** args) that you wrote in your C program.

Ncurses programs in pseudo-terminals

In my continuing attempt to understand how pseudo-terminals work, I have written a small program to try to run bash.
The problem is, my line-breaking seems to be off. (The shell prompt only appears AFTER I press enter.)
Furthermore, I still cannot properly use ncurses programs, like vi. Can anyone tell me how to setup the pseudo-terminal for this?
My badly written program can be found here, I encourage you to compile it. The operating system is GNU/Linux, thanks.
EDIT: Compile like this: gcc program.c -lutil -o program
EDIT AGAIN: It looks like the issue with weird spacing was due to using printf(), still doesn't fix the issue with ncurses programs though.
There are several issues in your program. Some are relatively easy to fix - others not so much:
forkpty() and its friends come from BSD and are not POSIX compatible. They should be avoided for new programs. From the pty(7) manual page:
Historically, two pseudoterminal APIs have evolved: BSD and System V. SUSv1 standardized a pseudoterminal API based on the System V API, and this API should be employed in all new programs that use pseudoterminals.
You should be using posix_openpt() instead. This issue is probably not critical, but you should be aware of it.
You are mixing calls to raw system calls (read(), write()) and file-stream (printf(), fgets()) functions. This is a very good way to confuse yourself. In general you should choose one approach and stick with it. In this case, it's probably best to use the low-level system calls (read(), write()) to avoid any issues that would arise from the presence of the I/O buffers that the C library functions use.
You are assuming a line-based paradigm for your terminals, by using printf() and fgets(). This is not always true, especially when dealing with interactive programs like vim.
You are assuming a C-style single-byte null-terminated string paradigm. Terminals normally deal with characters and bytes - not strings. And while most character set encodings avoid using a zero byte, not all do so.
As a result of (2), (3) and (4) above, you are not using read() and write() correctly. You should be using their return values to determine how many bytes they processed, not string-based functions like strlen().
This is the issue that, in my opinion, will be most difficult to solve: You are implicitly assuming that:
The terminal (or its driver) is stateless: It is not. Period. There are at least two stateful controls that I suspect are the cause of ncurses-based programs not working correctly: The line mode and the local echo control of the terminal. At least these have to match between the parent/master and the slave terminal in order to avoid various strange artifacts.
The control-interface of a terminal can be passed-through just by passing the bytes back and forth: It is not always so. Modern virtual terminals allow for a degree of out-of-band control via ioctl() calls, as described for Linux here.
The simplest way to deal with this issue is probably to set the parent terminal to raw mode and let the slave pseudo-terminal driver deal with the awkward details.
You may want to have a look at this program which seems to work fine. It comes from the book The Linux Programming Interface and the full source code is here. Disclaimer: I have not read the book, nor am I promoting it - I just found the program using Google.

Can stdio be used while coding for a Kernel...?

I need to build a OS, a very small and basic one, with actually least functionality, coded in C.
Probably a CUI OS which does some memory management and has at least a text editor and a calculator, its just going to be a experimentation about how to make a code that has full and direct control over your hardware.
Still I'll be requiring an interface, that will need input/output functions like printf(&args), scanf(&args). Now my basic question is should I use existing headers or go for coding actually from scratch, and why so ?
I'd be more than very thankful to you guys for and help.
First, you can't link against anything from libc ... you're going to have to code everything from scratch.
Now having worked on a micro-kernel myself, I would not use the actual stdio headers that come with libc since they are going to be cluttered with a lot of extra information that will be either irrelevant for your OS, or will create compiler errors due to missing definitions, etc. What I would do though is keep the function signatures for these standard functions the same ... so in the end you would have a file called stdio.h for your OS, but it would be a very stripped down header file with the basic minimum requirements for your needs, and only having the standard I/O functions you need, with the correct standard signatures.
Keep in mind on the back-end, i.e., in your stdio.c file, you're going to have to point these functions to a custom console-driver or some other type of character drive for your display. Either that, or you could just use them as wrappers for some other kernel-level display printing routine. You are also going to want to make sure that even though you may use a #include <stdio.h> directive in your other OS code modules to access these printing functions, you do not link against libc. This can be done using gcc -ffreestanding.
Just retarget newlib.
printf, scanf, etc relies on implementation specific funcions to get a single char or print a single char. You can then make your stdin and stdout the UART 1 for example.
Kernel itself would not require the printf and scanf functions, if you do not want to keep the kernel in kernel mode and work the apps you have planned for. But for basic printf and scanf features, you can write your own printf and scanf functions, which would provide basic support for printing ans taking input. I do not have much experience on this, but you can try make a console buffer, where the keyboard driver puts the read in ASCII characters (after conversion from scan codes), and then make the printf and scanf work on it. I have one basic implementation were i have wrote a gets instead of scanf and kept things simple. To get integer output you can write an atoi function to convert the string to a number.
To port in other libraries, you need to make the components which the libraries depend on. You need to make the decision if you can code in those support in the kernel so that the libraries could be ported in. If it is more difficult then coding some basic input output functions i think won't be bad at this stage,

Resources