Skip to content

Add COB_SET_RUNTIME_STDOUT_FILE and COB_SET_RUNTIME_STDERR_FILE runtime options to enable redirection of stdout/stderr output - #296

Open
oguzcankirmemis wants to merge 36 commits into
OCamlPro:gitside-gnucobol-3.xfrom
oguzcankirmemis:feature/stdout-stderr-redirect
Open

Add COB_SET_RUNTIME_STDOUT_FILE and COB_SET_RUNTIME_STDERR_FILE runtime options to enable redirection of stdout/stderr output#296
oguzcankirmemis wants to merge 36 commits into
OCamlPro:gitside-gnucobol-3.xfrom
oguzcankirmemis:feature/stdout-stderr-redirect

Conversation

@oguzcankirmemis

Copy link
Copy Markdown
Contributor

This PR adds runtime options COB_SET_RUNTIME_STDOUT_FILE and COB_SET_RUNTIME_STDERR_FILE which allows control over the location where the stdout/stderr output is written.

Motivation

For modules written in C that interact with libcob, it is currently difficult to change the location of stdout/stderr output without disturbing the stdout/stderr of the whole process (i.e., other threads). This is especially useful for thread applications, where it is desired that each thread gets its own stdout/stderr without disturbing the one another.

With these options, the main program can easily redirect the output of the COBOL program (including the messages from the runtime itself) and decide what to do with it. For that reason, the main program is also responsible for managing the lifetime of the passed stdout/stderr files, should they be used.

Implementation

  • Add COB_SET_RUNTIME_STDOUT_FILE and COB_SET_RUNTIME_STDERR_FILE options to cob_runtime_option_switch in common.h.
  • Extend the cob_settings in coblocal.h to store the location of configured stdout/stderr. By default, they are initialized to stdout/stderr of the process.
  • Add support for both options in cob_set_runtime_option and cob_get_runtime_option in common.c.
  • Adjust all print statements in across all various files in the runtime, i.e., under ./libcob, so that they behave accordingly.
  • Document both options in doc/gnucobol.texi.

@oguzcankirmemis

Copy link
Copy Markdown
Contributor Author

@GitMensch Here is the promised PR for stdout/stderr redirection. I opened it in draft for now to clarify a small issue in libcob/cobgetopt.c: Since the cobsetptr is currently not exposed in this file, my naive way of doing the redirection is not possible without further adjustment. How should we proceed here?

I also feel like implementing the redirection in some places seemed unnecessary to me, with the thought that they were meant for direct usage over the command line, rather than a C module interacting with GnuCOBOL. I would appreciate if you could check in general where it makes sense, or whether there are still places missing, where we need to the redirection.

As always, always glad and available for further questions and discussions. Thanks for the support!

@oguzcankirmemis

Copy link
Copy Markdown
Contributor Author

I can confirm that the failing tests in CI (should be seven in total) are related to the PR, will investigate.

@oguzcankirmemis

Copy link
Copy Markdown
Contributor Author

All tests should be fixed now, the issue was cob_runtime_warning, cob_runtime_error and cob_runtime_hint can be called from other modules (like cobc) without initializing the cobsetptr (i.e. cob_settings) in common.c. Upon looking closer, I also discovered that there is also cob_runtime_warning_ss for the signal handler, that directly uses the file descriptor of stderr. I believe, we can't use the FILE pointer there since fileno would not be signal handler safe.. I am leaving as it is for now, is this fine?

@oguzcankirmemis

Copy link
Copy Markdown
Contributor Author

Not sure what is going on with Windows CI tests, and the vbisam one, but I believe it is unrelated?

@GitMensch GitMensch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also add those two as "normal" runtime settings COB_STDOUT_FILE and COB_STDERR_FILE with the common file handling (like + opening the file as append), this allows users to both set the filename within a COBOL thread via SET ENVIRONMENT as well as easily having one per PID (which would be your example).

Not sure, but... would it be reasonable to redirect stdin the same way?

Comment thread libcob/common.c Outdated
Comment thread libcob/fileio.c Outdated
Comment on lines +3637 to +3639
bdb_env->set_errfile (bdb_env, cobsetptr->cob_stderr);
#if (DB_VERSION_MAJOR > 4) || ((DB_VERSION_MAJOR == 4) && (DB_VERSION_MINOR > 2))
bdb_env->set_msgfile (bdb_env, stderr);
bdb_env->set_msgfile (bdb_env, cobsetptr->cob_stderr);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be re-set if the current thread changes the file* ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would I trigger the refresh/re-set in cob_set_runtime_option in that case, by simply adding a non-static getter for bdb_env?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the right way would be to do the same as in screenio - see cob_settings_screenio and its callers... but at least add one exported function into fileio.c that you can call when this specific runtime setting changed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, let me know if it is missing something.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the only question here is shouldn't the code be moved to the setting function (and that function either be called in the caller or inside this function)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense, I guess I was trying to be as uninvasive as possible, hence redundant stuff.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have moved the unused (probably deprecated) part of the ifdef to settings as well. My gut feeling was telling me they should stay together.

Comment thread libcob/common.c
Comment thread tests/testsuite.src/run_misc.at Outdated
Comment thread tests/testsuite.src/run_misc.at Outdated
@oguzcankirmemis

oguzcankirmemis commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

Please also add those two as "normal" runtime settings COB_STDOUT_FILE and COB_STDERR_FILE with the common file handling (like + opening the file as append), this allows users to both set the filename within a COBOL thread via SET ENVIRONMENT as well as easily having one per PID (which would be your example).

Not sure, but... would it be reasonable to redirect stdin the same way?

For stdin, I don't have a clue whether it would be useful, so you can decide. I think it wouldn't be too much of an effort.

For adding them as normal runtime settings, how does "SET ENVIRONMENT" work right now for IO files? I thought GnuCOBOL already implements changing the stdout/stderr via SET ENVIRONMENT inside COBOL, that is why I am a little bit confused. I also think if COBOL is the main process, it is actually relatively easy to redirect stdout/stderr 2> /tmp/stderr-location etc., at least in a conventional OS/Shell, so I don't see the benefit there. What am I missing?

@GitMensch

Copy link
Copy Markdown
Collaborator

If stdin is not a big effort, then please add it the same way, covering all internally used streams. We may even use it later for other tests.

For the SET ENVIRONMENT part (possibly more used with runtime configuration file): see cob_check_trace_file - the setting would name a file and it would be internally opened as soon as the runtime setting is set.

Comment thread libcob/common.c Outdated

@GitMensch GitMensch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there seems to be one missing element used when calling libcob from cobc, but only on Win32 - I guess that's the place where the binary mode is set (unix_lf), as that will only happen this way on win32

That and the stderr_f assignment inlined should fix CI; adding stdin redirection + reassignment for BDB would then finalize the changes.

If you feel that you can't get the part done soon that works on those changes and are likely more often used by "normal" users (three matching runtime settings to assign the streams to a filename) then we can get this in with a follow-up PR or work by someone else.

Comment thread tests/testsuite.src/run_misc.at
@oguzcankirmemis

oguzcankirmemis commented Jul 12, 2026

Copy link
Copy Markdown
Contributor Author

If stdin is not a big effort, then please add it the same way, covering all internally used streams. We may even use it later for other tests.

For the SET ENVIRONMENT part (possibly more used with runtime configuration file): see cob_check_trace_file - the setting would name a file and it would be internally opened as soon as the runtime setting is set.

there seems to be one missing element used when calling libcob from cobc, but only on Win32 - I guess that's the place where the binary mode is set (unix_lf), as that will only happen this way on win32

That and the stderr_f assignment inlined should fix CI; adding stdin redirection + reassignment for BDB would then finalize the changes.

If you feel that you can't get the part done soon that works on those changes and are likely more often used by "normal" users (three matching runtime settings to assign the streams to a filename) then we can get this in with a follow-up PR or work by someone else.

I have added the stdin redirection as well, remaining parts are:

  • Runtime configuration files
  • The issue with Win32

Apart from TODOs I have commented on, some stylings and docs, all parts should be there now. I have changed the test slightly to make it Windows compatible, let's see if CI passes.

Comment thread libcob/cobgetopt.c Outdated
{
if (ambig_fallback)
{
/* TODO: Decide how to do stdout/stderr redirection here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about here? Solve it similarly by adding an exported init function?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if that's the only place here: call into cob_get_runtime_option once to get the fp - if it is NULL use stderr

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two functions, but I think adding it to both doesn't harm too much.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the way, cob_get_runtime_option actually assumes settings is initialized, I have added an if check to bypass it for stdin/stdout/stderr. I can add the same logic to others to make it uniform among all runtime options.

Comment thread libcob/common.c Outdated
@oguzcankirmemis

oguzcankirmemis commented Jul 12, 2026

Copy link
Copy Markdown
Contributor Author

Remaining failing CI tests should be hopefully unrelated.

@oguzcankirmemis

oguzcankirmemis commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

Updated docs/changelogs, will mark the PR non-draft, once all the todos are cleared. The one extra failed CI with Ubuntu+MSYS1 should actually pass (i.e. I haven't touched anything other than docs)? Instead, it got broken pipe in SIGPIPE test for some reason.

Comment thread config/runtime.cfg

@GitMensch GitMensch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ci failures unrelated, most important adjustment is the handling of the setting of the runtime option - the current version won't work if those come from SET ENVIRONMENT (explicit setting in the COBOL main instead of runtime config file / environment)

Comment thread libcob/fileio.c Outdated
Comment on lines +3637 to +3639
bdb_env->set_errfile (bdb_env, cobsetptr->cob_stderr);
#if (DB_VERSION_MAJOR > 4) || ((DB_VERSION_MAJOR == 4) && (DB_VERSION_MINOR > 2))
bdb_env->set_msgfile (bdb_env, stderr);
bdb_env->set_msgfile (bdb_env, cobsetptr->cob_stderr);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the only question here is shouldn't the code be moved to the setting function (and that function either be called in the caller or inside this function)?

Comment thread tests/ChangeLog
Comment thread NEWS Outdated
Comment thread config/runtime.cfg
Comment thread libcob/common.c Outdated
Comment thread libcob/ChangeLog
Comment thread doc/gnucobol.texi
Comment thread libcob/common.c Outdated
Comment thread libcob/common.c Outdated
Comment on lines +10499 to +10529
if (cobsetptr->cob_stdin_filename) {
if (!cobsetptr->cob_unix_lf) {
cobsetptr->cob_stdin =
fopen (cobsetptr->cob_stdin_filename, "r");
} else {
cobsetptr->cob_stdin =
fopen (cobsetptr->cob_stdin_filename, "rb");
}
if (!cobsetptr->cob_stdin) {
cobsetptr->cob_stdin_filename = NULL;
cobsetptr->cob_stdin = stdin;
}
}

if (cobsetptr->cob_stdout_filename) {
cobsetptr->cob_stdout =
cob_open_logfile (cobsetptr->cob_stdout_filename);
if (!cobsetptr->cob_stdout) {
cobsetptr->cob_stdout_filename = NULL;
cobsetptr->cob_stdout = stdout;
}
}

if (cobsetptr->cob_stderr_filename) {
cobsetptr->cob_stderr =
cob_open_logfile (cobsetptr->cob_stderr_filename);
if (!cobsetptr->cob_stderr) {
cobsetptr->cob_stderr_filename = NULL;
cobsetptr->cob_stderr = stderr;
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that part needs to be moved (maybe to termio.c?) and called when one of those runtime settings are changed - and in that case close the old pointer, before opening it again (if the pointer changed and the content differs)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved it, see comment at the bottom.

Comment thread tests/testsuite.src/run_misc.at Outdated
@oguzcankirmemis

Copy link
Copy Markdown
Contributor Author

ci failures unrelated, most important adjustment is the handling of the setting of the runtime option - the current version won't work if those come from SET ENVIRONMENT (explicit setting in the COBOL main instead of runtime config file / environment)

Makes sense, I will take a look.

@codecov-commenter

codecov-commenter commented Jul 15, 2026

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 51.18110% with 124 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (gitside-gnucobol-3.x@93c9924). Learn more about missing BASE report.

Files with missing lines Patch % Lines
libcob/common.c 43.47% 44 Missing and 34 partials ⚠️
libcob/termio.c 53.16% 24 Missing and 13 partials ⚠️
libcob/cobgetopt.c 65.21% 8 Missing ⚠️
libcob/screenio.c 66.66% 1 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@                   Coverage Diff                   @@
##             gitside-gnucobol-3.x     #296   +/-   ##
=======================================================
  Coverage                        ?   67.42%           
=======================================================
  Files                           ?       34           
  Lines                           ?    61700           
  Branches                        ?    16091           
=======================================================
  Hits                            ?    41599           
  Misses                          ?    14112           
  Partials                        ?     5989           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@oguzcankirmemis

oguzcankirmemis commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

I think SET ENVIRONMENT should work now, added a test for it. It is kind of messy how I do it in cobsetptr, i.e. having cob_stdout_filename and cob_stdout_filename_set both to remember the old setting in termio.c. I was against the idea of storing them as globals inside termio.c. Let me know if you think there is a better way to achieve the functionality.

There is also the print_version and print_info functions in common.c, that still print to process stdout. I haven't converted them, because I don't see the use case to be honest. But for completeness sake, if you want it, I can change them as well.

Otherwise, from my side all that is missing is what we should with cobgetopt.c. I will make a final pass for news/changelogs etc. once the other changes are finalized.

@GitMensch

Copy link
Copy Markdown
Collaborator

@oguzcankirmemis please rebase, which should improve the CI results

@oguzcankirmemis
oguzcankirmemis force-pushed the feature/stdout-stderr-redirect branch from e407b35 to d573e9c Compare August 5, 2026 15:28
@oguzcankirmemis

oguzcankirmemis commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

@GitMensch rebase done, I think the failing two tests in Windows are due to runtime mismatch between libcob and the running tests (similar to CBL_GC_HOSTED). The error doesn't make sense to me really otherwise.

Should we try to fix it, or ignore the test in windows debug builds?

You probably already looked into it, but do you know a fast way to experiment/verify with Windows builds, i.e. some ready to use image or machine I can connect to? Then, I can take a look to make the libraries use the same c runtime maybe. It should be helpful for future tests.

@oguzcankirmemis

Copy link
Copy Markdown
Contributor Author

@GitMensch I fixed the Windows CI issues with a little help of AI, i.e. it found the cb_source_debugging and the _DEBUG macro for me. Surprisingly, fixing the issue there also fixes the signal regime tests. Apparently, the runtime abort before signal handler also was happening due to CRT mismatch. As suspected, the fix also fixes the CBL_GC_HOSTED test.

A minor consequence for now is that the debug builds via cobc always uses /Od, ignoring what the user is passing. This created a warning message in the INITIALIZE big table with VALUE test, where I had to delete the optimization flag (-02). If you think having the flag there is necessary, we can add an if check for debug builds in cobc so that it does not pass /0d, if the user has supplied an optimization flag.

Let me know if there are other consequences we need to think about for the fix.

@oguzcankirmemis

Copy link
Copy Markdown
Contributor Author

For curiosity, I also asked AI to decouple CRT selection from the -g flag, effectively adding another variable on top of cb_source_debugging. Using cb_source_debugging adds more than the CRT flag as mentioned, hence the reason. I can push it if you find this idea cleaner.

@GitMensch

Copy link
Copy Markdown
Collaborator

Yes, CRT selection should be independent from the optimization flags.

To not mix/match your MSVC CI fixes (and - very nice - remove some removement of failing tests) with the rest of this PR: please create a separate one (which then @ddeclerck can also merge here + upstream, while I inspect the "real PR = new feature").

@GitMensch

GitMensch commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

As the MSVC debug builds break in the single test for this PR.. there seems something is actually broken in the implementation, no?

901. run_misc.at:16112: testing stdin/stdout/stderr redirection ...
tests/run_misc.at:16266: $COMPILE prog.cob
tests/run_misc.at:16267: $COMPILE caller.c
tests/run_misc.at:16268: $COMPILE_MODULE callee.cob
tests/run_misc.at:16270: $COBCRUN_DIRECT ./prog
tests/run_misc.at:16271: ./caller
--- /dev/null	2026-08-09 15:02:56.000000000 +0000
+++ /d/a/gnucobol/gnucobol/tests/testsuite.dir/at-groups/901/stderr	2026-08-09 15:02:56.829262700 +0000
@@ -0,0 +1 @@
+minkernel\crts\ucrt\src\appcrt\lowio\read.cpp(381) : Assertion failed: _osfile(fh) & FOPEN
tests/run_misc.at:16271: exit code was 127, expected 0
901. run_misc.at:16112:  FAILED (run_misc.at:16271)

@oguzcankirmemis

Copy link
Copy Markdown
Contributor Author

As the MSVC debug builds break in the single test for this PR.. there seems something is actually broken in the implementation, no?

901. run_misc.at:16112: testing stdin/stdout/stderr redirection ...
tests/run_misc.at:16266: $COMPILE prog.cob
tests/run_misc.at:16267: $COMPILE caller.c
tests/run_misc.at:16268: $COMPILE_MODULE callee.cob
tests/run_misc.at:16270: $COBCRUN_DIRECT ./prog
tests/run_misc.at:16271: ./caller
--- /dev/null	2026-08-09 15:02:56.000000000 +0000
+++ /d/a/gnucobol/gnucobol/tests/testsuite.dir/at-groups/901/stderr	2026-08-09 15:02:56.829262700 +0000
@@ -0,0 +1 @@
+minkernel\crts\ucrt\src\appcrt\lowio\read.cpp(381) : Assertion failed: _osfile(fh) & FOPEN
tests/run_misc.at:16271: exit code was 127, expected 0
901. run_misc.at:16112:  FAILED (run_misc.at:16271)

I am confused, the CI fix also fixes this issue, no?

@oguzcankirmemis

Copy link
Copy Markdown
Contributor Author

Yes, CRT selection should be independent from the optimization flags.

To not mix/match your MSVC CI fixes (and - very nice - remove some removement of failing tests) with the rest of this PR: please create a separate one (which then @ddeclerck can also merge here + upstream, while I inspect the "real PR = new feature").

Gotcha, I will revert the fix here once I opened the other PR.

@GitMensch

Copy link
Copy Markdown
Collaborator

I am confused, the CI fix also fixes this issue, no?

hm, now I see all passing... not sure what I've seen before, guess that was an error from "it is a file pointer, but not from this runtime"

@GitMensch GitMensch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're nearly done on this PR. Thanks for your efforts!

Some notes and mostly minor things to adjust in the review below.

Comment thread config/ChangeLog
Comment thread doc/ChangeLog
Comment thread libcob/ChangeLog Outdated
Comment on lines +6 to +10
* common.h (cob_runtime_option_switch): add COB_SET_RUNTIME_STDIN_FILE,
COB_SET_RUNTIME_STDOUT_FILE and COB_SET_RUNTIME_STDERR_FILE enums
* common.c (cob_set_runtime_option, cob_get_runtime_option): extend for
COB_SET_RUNTIME_STDIN_FILE, COB_SET_RUNTIME_STDOUT_FILE and
COB_SET_RUNTIME_STDERR_FILE options

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can combine those two into a single one

Comment thread libcob/common.c
void *
cob_get_runtime_option (enum cob_runtime_option_switch opt)
{
switch (opt) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a check to directly return NULL if cobsetptr is not available (= no init done yet)

Comment thread libcob/cobgetopt.c Outdated
{
if (ambig_fallback)
{
/* TODO: Decide how to do stdout/stderr redirection here

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if that's the only place here: call into cob_get_runtime_option once to get the fp - if it is NULL use stderr

Comment thread libcob/common.c Outdated

(void)_setmode (_fileno (stdin_f), _O_BINARY);
(void)_setmode (_fileno (stdout_f), _O_BINARY);
(void)_setmode (_fileno (stderr_f), _O_BINARY);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure: wouldn't we need that in the termio inits after opening the file?
Maybe move that whole part there?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we need it also in termio. I would suggest that aside from setting stdout/stderr/stdin in cob_init, no further initialization should be done at common, and the rest should happen in termio.

I find even setting the initials in cobsetptr in common is uglyish, but I guess it is an ok compromise unless we we want to introduce a different init routine in termio just for the sake of redirection.

@oguzcankirmemis oguzcankirmemis Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ties back to your review in termio with what happens if the string is null/empty etc.: It should ignore and simply work with whatever set in the cobsetptr, which would be the process stdin/stdout/stderr, and do the configuration for it.

@oguzcankirmemis oguzcankirmemis Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, moving the whole part there sounds problematic, because cob_init_termio expects that settings is initialized, whereas the whole point of cob_common_init is to leave settings unintialized. But as you said, we also need this logic in the termio. Since calling _setmode twice with the same parameter shouldn't hurt, for now, I would just duplicate the relevant part and also put a comment in cob_common_init hinting at the issue.

Comment thread libcob/common.c
void
cob_set_runtime_option (enum cob_runtime_option_switch opt, void *p)
{
switch (opt) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add an explicit check for cobsetptr here and call cob_fatal_error (COB_FERROR_INITIALIZED) if it isn't set.

Comment thread libcob/coblocal.h
AT_CLEANUP


AT_SETUP([stdin/stdout/stderr redirection])

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just seen that the first time after you've added stdin.

That test is super clever and I like it - the only possible issue: if the stdin part does not work (what we want to ensure with this test) this test would hang forever, no?

But that can possibly apply to every test, especially file related... so leaving it in is a good way to catch if that does not work :-)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about running the test with a timeout?, simply like AT_CHECK([timeout 10s $COBCRUN_DIRECT ./prog], [0], [], [])

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would even suggest adding timeout to both, the other one can also hang.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to revert timeout, apparently it does not come pre-installed in MacOS. Disappointing really, it should be part of the standard posix tools if I am not misunderstanding. There is a perl alternative we can probably use, but it looks ugly to me. Or one can install coreutils in Mac and alias gtimeout with timeout, if we want to go there.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure about the portability of that... but at least on GNU/Linux and one checked Solaris that's available.

Comment thread NEWS Outdated
** new runtime configurations: COB_STDIN_FILE, COB_STDOUT_FILE,
COB_STDERR_FILE. They allow redirection of stdin/stdout/stderr input/output
to a file. Alternatively, these configurations are also available as runtime
options which can be used to set them programmatically:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to set them via configuration file, environment variables, or programatically

Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
- introduces following runtime configurations: COB_STDIN_FILENAME, COB_STDOUT_FILENAME, COB_STDERR_FILENAME

Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Introduce COB_STDIN, COB_STDOUT, COB_STDERR, COB_STDERR_OR_DEFAULT
Add timeout to redirection tests
Solve cobgetopt.c with cob_get_runtime_option
Refactor termio for better edge case handling

Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
Signed-off-by: Oguzcan Kirmemis <oguzcan.kirmemis@gmail.com>
@oguzcankirmemis
oguzcankirmemis force-pushed the feature/stdout-stderr-redirect branch from 26c80d9 to d7c9dc5 Compare September 1, 2026 09:45
@oguzcankirmemis

Copy link
Copy Markdown
Contributor Author

Rebased after the merge of #300

@GitMensch GitMensch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - thanks for your work on this, ready for upstream when the CI passes

If neither @lefessan nor @ddeclerck get to commit that upstream, then I'll do so not later than this weekend.

Comment thread libcob/common.c
Comment on lines +8317 to +8319
if (data_loc == offsetof (cob_settings, cob_stdin_filename)
|| data_loc == offsetof (cob_settings, cob_stdout_filename)
|| data_loc == offsetof (cob_settings, cob_stderr_filename)) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (data_loc == offsetof (cob_settings, cob_stdin_filename)
|| data_loc == offsetof (cob_settings, cob_stdout_filename)
|| data_loc == offsetof (cob_settings, cob_stderr_filename)) {
if (data_loc == offsetof (cob_settings, cob_stdin_filename)
|| data_loc == offsetof (cob_settings, cob_stdout_filename)
|| data_loc == offsetof (cob_settings, cob_stderr_filename)) {

minor formatting, can also be applied during upstream commit

Comment thread libcob/termio.c
Comment on lines +1111 to +1115
if (cobsetptr->cob_stdin_filename_set &&
strcmp (cobsetptr->cob_stdin_filename,
cobsetptr->cob_stdin_filename_set) == 0) {
return;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (cobsetptr->cob_stdin_filename_set &&
strcmp (cobsetptr->cob_stdin_filename,
cobsetptr->cob_stdin_filename_set) == 0) {
return;
}
if (cobsetptr->cob_stdin_filename_set
&& strcmp (cobsetptr->cob_stdin_filename,
cobsetptr->cob_stdin_filename_set) == 0) {
return;
}

minor formatting here and similar below in the new code, can also be done during usptream commit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants