Beginner Question about exit or return

Hi,

I have a really simple program in C++ that is supposed to run in DOS real mode (not Windows DOS). It basically uses spawn to call another program and then processes some files. Then put some stuff on the screen and quit. The problem I'm having is when it exits (no matter whether I use return 0 or exit 0, the program just hangs instead of returning to the DOS prompt. It is doing everything else the way its supposed to, so I don't know why it's hanging.

BTW - how does one post code on this site. Just copy and paste?

Thanks in advance for your help.
Another thing you might want to know is I'm using Borland 4.52 (I know, really old).
To past code you pres on the button "<>" and this button will insert [code ] your code here [/code ] tags. You past your code between this tags.
It is to hard to say about your problem without code.
Thanks, here is the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
//Version 1.0 by Elena Quinn 
//Versioon 1.1 by Elena Quinn 

#include <iostream.h>
#include <dos.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <dir.h>
#include <process.h>
#include <conio.h>
#include <errno.h>
//#include <iomanip.h>

//Global Variables

//End Global Variables

//Function Prototypes
void getdata(char *source, char *target, int start, int length)
//This function takes the data from the source at the indicated starting point
//and copies each character to the target for the specified length.
{
 int i;
 int j;


 for(i=0, j=start;i<length;i++, j++)
	*(target + i) = *(source + j);

	*(target + length) = '\0';
}

//End Prototypes

//End Prototypes

int main(void)
{
int retval;				// Scratch variable to test functions.

FILE *input, *output;	                //input is tsbiqc.dat file, output is log file
char string[150];			//Test string from each line of file
char year[5];
char month[10];
char day[3];
struct tm *datetime;
char *filename = "scr.dat";
char *logfile;
char *serial;

printf("%s\n", "SCR Version 1.0 ");

retval = spawnlp(P_WAIT, "test.exe", "test.exe", "scr.bc", NULL);
if(errno == E2BIG)
{
	printf("\nCannot Spawn Child Process - ARG LIST TOO LONG");
//	return 1;
}
if(errno == EINVAL)
{
	printf("\nCannot Spawn Child Process - INVALID ARGUMENT");
//	return 1;
}
if(errno == ENOENT)
{
	printf("\nCannot Spawn Child Process - PATH OR FILENAME NOT FOUND");
//	return 1;
}
if(errno == ENOEXEC)
{
	printf("\nCannot Spawn Child Process - EXEC FORMAT ERROR");
///	return 1;
}
if(errno == ENOMEM)
{
	printf("\nCannot Spawn Child Process - NOT ENOUGH CORE MEMORY");
//	return 1;
}



//retval = 1;
// if log already exists, no need to create a new one
  time_t current_time;
  tzset();
  time(&current_time);
  datetime = localtime(&current_time);
  strftime(year, sizeof(year), "%Y", datetime);
  strftime(month, sizeof(month), "%b", datetime);
  strftime(day, sizeof(day), "%d", datetime);

  printf("Year = %s, Month = %s, Day = %s", year, month, day);

  char dirname[128] = "C:\\";
  char current[128];
  getcwd(current, sizeof(current));
  strcat(dirname, year);
  if (chdir(dirname) == -1)
	{
		 if(mkdir(dirname) == -1)
		 {
	  printf("\nCan't Create Directory %s!", dirname);
	  exit(1);
		 }
	}
  strcat(dirname, "\\");
  strcat(dirname, month);
  if (chdir(dirname) == -1)
	{
		 if(mkdir(dirname) == -1)
		 {
	  printf("\nCan't Create Directory %s!", dirname);
	  exit (1);
		 }
	}
	 chdir(current);
	 printf("\nDirectory Name = %s", dirname);
  printf("\nCurrent Directory = %s", current);
  chdir(current);

	//Open the input file
	if((input = fopen(filename, "r")) != NULL)
	{
			  while(!feof(input))
			  {
				fgets(string, 150, input);   //get next line of input file
				if (strncmp(string, "Serial", 6) == 0)
					{
						getdata(string, serial, 26, 8);
						break;
					}
			  }//end while(!feof(input))

			}//end input != NULL




	 fclose(input); //close input file
			 input = NULL;

	 chdir(current);
	 printf("\nDirectory Name = %s", dirname);
  printf("\nCurrent Directory = %s", current);
  chdir(current);
  logfile = dirname;
  strcat(logfile, "\\");
  strcat(logfile, serial);
  strcat(logfile, ".log");

  //Open the input file
	if((input = fopen(filename, "r")) != NULL)
	{    if ((output = fopen(logfile, "a")) != NULL)
			{
			  while(!feof(input))
			  {
				fgets(string, 150, input);   //get next line of input file
				if (strncmp(string, "=====", 5) == 0)
					{
						fputs (string, output);
						break;
					}
			  }//end while(!feof(input))
			  while(!feof(input))
			  {
				fgets(string, 150, input);   //get next line of input file
				fputs (string, output);

				}//end while(!feof(input))

			}//end input != NULL
	 }

	fclose(input); //close input file
	input = NULL;

	fclose(output);
	output = NULL;

	chdir(current);
	if (remove(filename) != 0)
	{
		if (errno == EACCES)
			{
				printf("Access Denied\n");
			}
		if (errno == ENOENT)
			{
				printf("File not found.\n");
			}
	}

	if((input = fopen(logfile, "r")) != NULL)
	{
			  while(!feof(input))
			  {
				fgets(string, 150, input);   //get next line of input file
				if (strncmp(string, "Summary", 7) == 0)
					{
						clrscr();
						gotoxy(5,11);
						cprintf("%s\n", string);
						break;
					}
			  }//end while(!feof(input))
			  while(!feof(input))
			  {
				fgets(string, 150, input);   //get next line of input file
				cprintf("%s", string);

				}//end while(!feof(input))


	 }
	 fclose(input);
	 input = NULL;




//Now check whether we pass or fail.
	if (retval == 1)
	{
		//clrscr();
		gotoxy(5, 5);
		textcolor(WHITE);
		textbackground(RED);
		cprintf("                      \r\n");
		gotoxy(5, 6);
		cprintf("                      \r\n");
		gotoxy(5, 7);
		cprintf("        FAILED        \r\n");
		gotoxy(5, 8);
		cprintf("                      \r\n");
		gotoxy(5, 9);
		cprintf("                      \r\n");
		exit(0);
	}
	if (retval == 2)
	{
		//clrscr();
		gotoxy(5, 5);
		textcolor(WHITE);
		textbackground(BLUE);
		cprintf("                       \r\n");
		gotoxy(5, 6);
		cprintf("      ABNORMAL         \r\n");
		gotoxy(5, 7);
		cprintf("     TERMINATION       \r\n");
		gotoxy(5, 8);
		cprintf("                       \r\n");
		gotoxy(5, 9);
		cprintf("                       \r\n");
		exit(0);
	}

		//clrscr();
		gotoxy(5, 5);
		textcolor(WHITE);
		textbackground(GREEN);
		cprintf("                      \r\n");
		gotoxy(5, 6);
		cprintf("                      \r\n");
		gotoxy(5, 7);
		cprintf("        PASSED        \r\n");
		gotoxy(5, 8);
		cprintf("                      \r\n");
		gotoxy(5, 9);
		cprintf("                      \r\n");
		exit (0);



}//end main



A short code review which does possibly not solve your problem:

1. errno usually will not be set on success. So you should check first whether your function call failed then check errno. Otherwise you may detect an error although everything was ok.

2. Your way of reading input from a file may result in unexpected behavior at end of file

1
2
3
4
5
6
7
8
9
while(!feof(input))
{
    fgets(string, 150, input);   //get next line of input file
    if (strncmp(string, "Serial", 6) == 0)
    {
        getdata(string, serial, 26, 8);
        break;
    }
}//end while(!feof(input)) 


If the file ends up with a valid line (terminated by the line termination character(s)) fgets() will be called for another line because feof() wasn't just detected. You'll take the now undefined input for comparison... The background is that feof() doesn't actually check the real end of file condition but only an internal flag which is part of input. And this flag will only be set on any read operation. But the last read operation terminated at the line termination character and so didn't detected EOF.

Better read your file like:

1
2
3
4
5
6
7
8
while(fgets(string, 150, input) != NULL)
{
    if (strncmp(string, "Serial", 6) == 0)
    {
        getdata(string, serial, 26, 8);
        break;
    }
}//end while(!feof(input)) 
tsc - thank you. That information was helpful in that when copying one file to the other I was off by a few lines, so at the end I was getting repetition. With your suggestion, that was fixed.

However, the hang is still there. Like I said it is doing everything it's supposed to do, so it gets to the end of the program where it is putting up the Green 'PASS' or the Red 'FAIL', but when it exits, it hangs up.
Its really a very long time ago when I've written a DOS program. So I don't really know why exit() may fail under DOS conditions.
But maybe there's something wrong with your call to getdata()? F.e. variable serial isn't initialized when applied to getdata(). And it won't be on return from getdata(). So strcat() at line 150 will also result in something undefined. F.e. strcat() may fill up logfile with more than 150 characters. And this in turn may destroy some "DOS memory"...

What does getdata() exactly?
getdata() takes a string and copies a part of the string to another string based on a starting point and length.

So I am getting the string from the file and extracting the serial from it. Serial starts from position 26 and is 8 characters long.
But as I've noted above serial as target argument of getdata() isn't initialized! It points to anywhere - and may be to your process nirvana.

So it might help to define serial as array of 9 characters like

1
2
static const unsigned int SERIAL_SIZE = 8 + sizeof((char) '\0'); 
char serial[SERIAL_SIZE];


Now serial is well defined.
Do you mean in main()? or in getdata()? I have it defined in main(). Do you think this is not defined correctly?

1
2
3
4
5
char *filename = "scr.dat";
char *logfile;
char *serial;

printf("%s\n", "SCR Version 1.0 ");


Sorry, I'm not getting this.
Yes, it's not defined correctly, or:

1
2
char *logfile; // Points to unknown memory, probably you cannot access
char *serial; // Same 


You should:

1
2
char logfile[ (max size) ];
char serial[ (max size) ];


Also: printf("%s\n", "SCR Version 1.0 ") is a waste of performance, use printf("SCR Version 1.0 \n") instead.

Setting logfile and serial's sizes too big may result in a crash.
Keep their size under 8000, or 4000.

Another tip:

Instead of using char *filename = "scr.dat"; use char filename[] = "scr.dat";
Last edited on
Thanks! that worked. I haven't cleaned up all the variable yet. But changing the serial one fixed my problem.

You've defined serial as of type char* but never assigned any value to it. Because the C runtime system doesn't initialize pointers to any well defined value, say f.e. NULL, serial stays uninitialized and may point to any piece of memory. This may be a piece of memory of the DOS operating system. DOS has no memory protection so the assignment taken in getdata() may (or may not. Who knows?) overwrite some internal structures of the operating system resulting in a full system crash.

1
2
3
4
5
6
7
static const unsigned int SERIAL_SIZE = 8 + sizeof((char) '\0'); 

char *filename = "scr.dat";
char *logfile;
char serial[SERIAL_SIZE];

printf("%s\n", "SCR Version 1.0 ");


This should help!
@EssGeEich:
Instead of using char *filename = "scr.dat"; use char filename[] = "scr.dat";
Why this? Aren't both equivalent?
No.
The first does not allow you to edit that variable's content.
In fact, sizeof(filename) returns the size of a pointer.
The second does allow you to edit its content.
sizeof(filename) returns its length, in case char's size is a byte's size.

Also the first assignment on modern compilers is illegal.

Filename is a char*.
"scr.dat" is a const char*.
You cannot assign a const char* to a char*.
Last edited on
@EssGeEich: Thanks!
Topic archived. No new replies allowed.