• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nasa / trick / 18572341877

16 Oct 2025 07:21PM UTC coverage: 55.807% (+0.007%) from 55.8%
18572341877

Pull #1980

github

web-flow
Merge 614bd825f into b07fbb83c
Pull Request #1980: Don't use TMM to allocate argv

30 of 34 new or added lines in 2 files covered. (88.24%)

4 existing lines in 2 files now uncovered.

12406 of 22230 relevant lines covered (55.81%)

254570.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

57.78
/trick_source/sim_services/CommandLineArguments/CommandLineArguments.cpp
1
/*
2
   PURPOSE: ( Handle the simulation command line args )
3

4
   REFERENCE: ( Trick Simulation Environment )
5

6
   ASSUMPTIONS AND LIMITATIONS: ( None )
7

8
   CLASS: ( N/A )
9

10
   LIBRARY DEPENDENCY: ( None )
11

12
   PROGRAMMERS: ( Keith Vetter LinCom 6/2003 ) */
13

14

15
#include <cerrno>
16
#include <cstdio>
17
#include <cstdlib>
18
#include <cstring>
19
#include <ctime>
20
#include <iostream>
21
#include <pwd.h>
22
#include <string>
23
#include <sys/stat.h>
24
#include <sys/types.h>
25
#include <unistd.h>
26
#include <vector>
27

28
#include "trick/CommandLineArguments.hh"
29
#include "trick/memorymanager_c_intf.h"
30

31
Trick::CommandLineArguments * the_cmd_args ;
32

33
Trick::CommandLineArguments::CommandLineArguments()
226✔
34
    : argc(0)
226✔
35
{
36
    the_cmd_args = this ;
226✔
37

38
    output_dir = std::string(".");
226✔
39
    default_dir = std::string(".");
226✔
40
}
226✔
41

42
int Trick::CommandLineArguments::get_argc() {
732✔
43
    return(argc) ;
732✔
44
}
45

46
std::vector<std::string>& Trick::CommandLineArguments::get_argv() { return (argv); }
732✔
47

48
std::string Trick::CommandLineArguments::get_output_dir() {
×
49
    return(output_dir) ;
×
50
}
51

52
std::string & Trick::CommandLineArguments::get_output_dir_ref() {
1,479✔
53
    return(output_dir) ;
1,479✔
54
}
55

56
std::string Trick::CommandLineArguments::get_user_output_dir() {
×
57
    return(user_output_dir) ;
×
58
}
59

60
std::string & Trick::CommandLineArguments::get_user_output_dir_ref() {
319✔
61
    return(user_output_dir) ;
319✔
62
}
63

64
std::string Trick::CommandLineArguments::get_input_file() {
×
65
    return(input_file) ;
×
66
}
67

68
std::string & Trick::CommandLineArguments::get_input_file_ref() {
260,143✔
69
    return(input_file) ;
260,143✔
70
}
71

72
std::string Trick::CommandLineArguments::get_default_dir() {
×
73
    return(default_dir) ;
×
74
}
75

76
std::string & Trick::CommandLineArguments::get_default_dir_ref() {
259,784✔
77
    return(default_dir) ;
259,784✔
78
}
79

80
std::string Trick::CommandLineArguments::get_cmdline_name() {
×
81
    return(cmdline_name) ;
×
82
}
83

84
std::string & Trick::CommandLineArguments::get_cmdline_name_ref() {
259,779✔
85
    return(cmdline_name) ;
259,779✔
86
}
87

88
// Helper function - create a full path with error checking along the way
89
int Trick::CommandLineArguments::create_path(const std::string& dirname) {
7✔
90
    size_t cur_index = 0;
7✔
91

92
    std::string full_dir (dirname);
14✔
93

94
    // These syscalls don't seem to take care of home special character, so do it manually
95
    // I think the shell should handle it before it gets here, but just in case check for it
96
    if (dirname.at(0) == '~') {
7✔
97
        struct passwd *pw = getpwuid(getuid());
×
98
        full_dir = std::string(pw->pw_dir) + dirname.substr(1, dirname.size());
×
99
    }
100

101
    while (cur_index != full_dir.size()) {
32✔
102
        cur_index = full_dir.find('/', cur_index+1);
26✔
103
        if (cur_index == std::string::npos) {
26✔
104
            cur_index = full_dir.size();
6✔
105
        }
106
        std::string cur_dir = full_dir.substr(0, cur_index);
26✔
107

108
        struct stat info;
109
        if(stat( cur_dir.c_str(), &info ) != 0) {
26✔
110
            // does not exist - make it
111
            if (mkdir(cur_dir.c_str(), 0775) == -1) {
11✔
112
                std::cerr << "Error creating directory " << cur_dir << std::endl;
×
113
                return 1;
×
114
            }
115
        } else {
116
            // Does exist
117
            if(info.st_mode & S_IFDIR) {
15✔
118
                // Is a directory
119
                if (info.st_mode & S_IWUSR) {
14✔
120
                    // Perfect, nothing to do here
121
                } else {
122
                    // Not writeable
123
                    std::cerr << "Intermediate directory " << cur_dir << " is not writable, unable to create output directory." << std::endl;
×
124
                    return 1;
×
125
                }
126
            } else {
127
                // Does exist, but is a file
128
                std::cerr << "Intermediate directory " << cur_dir << " is not a directory, unable to create output directory." << std::endl;
1✔
129
                return 1;
1✔
130
            }
131
        }
132
    }
133
    return 0;
6✔
134
}
135

136
/**
137
@details
138
-# Save the number of command line arguments.
139
-# Save the command line arguments.
140
-# Determine the directory and simulation executable name from the first
141
   command line argument
142
   -# If no directory is specified
143
      -# Save the simulation executable name as the full first argument
144
      -# Get the current working directory
145
      -# Save the current working directory as the default input directory.
146
   -# If a relative or full directory is present in the command line arguments
147
      -# split the command line argument on the last "/" character
148
      -# Save the back half of the split as the simulation executable name
149
      -# Save the current working directory
150
      -# Change the current working directory to the first half of the split
151
         command line argument.
152
      -# Get the current working directory
153
      -# Save the current working directory as the default input directory.
154
      -# Change the current working directory to the saved working directory
155
-# If present, the second argument will be the run directory and the input file.
156
   -# Save the run input file  name as the full second argument
157
   -# Split the second argument on the last "/" character
158
   -# If no directory is specified set the default output and current output
159
      directories to the current directory
160
   -# Else set the default and the current output directories to the first
161
      half of the split
162
-# Search the remaining command line arguments for "-O" or "-OO"
163
   -# If found set the output direcory to the following argument
164
   -# Attempt to create the output directory if it does not exist.
165
      -# Exit if the simulation cannot be created.
166
*/
167
int Trick::CommandLineArguments::process_sim_args(int nargs , char **args) {
182✔
168

169
    argc = nargs;
182✔
170
    argv.clear();
182✔
171

172
    // c/cpp argument vector is null-terminated, but for trick, the stored arguments array never was
173
    argv.reserve(argc);
182✔
174
    for (int ii = 0; ii < argc; ii++) {
549✔
175
        argv.emplace_back(args[ii]);
367✔
176
    }
177

178
    default_dir = argv[0] ;
182✔
179

180
    char* buf  = (char*)malloc(4096);
182✔
181
    char* buf2 = (char*)malloc(4096);
182✔
182

183
    size_t found = default_dir.find_last_of('/');
182✔
184

185
    if ( found == std::string::npos ) {
182✔
186
        cmdline_name = default_dir ;
×
187
        getcwd(buf, (size_t) 256);
×
188
        default_dir = buf ;
×
189
    } else {
190
        cmdline_name = default_dir.substr(found + 1) ;
182✔
191

192
        // save the current directory
193
        getcwd(buf, (size_t) 256);
182✔
194

195
        // change to the default directory
196
        chdir(default_dir.substr(0,found).c_str());
182✔
197

198
        // get the full path default directory
199
        getcwd(buf2, (size_t) 256);
182✔
200
        default_dir = buf2 ;
182✔
201

202
        // change back to the current directory
203
        chdir(buf);
182✔
204
    }
205

206
    free(buf) ;
182✔
207
    free(buf2) ;
182✔
208

209
    if ( argc > 1 ) {
182✔
210

211
        /* First occurrence of "RUN_*" is the input file name: '<Run_dir>/<file_name>'.
212
           If not found, defaults to first argument */
213

214
        input_file = argv[1];
182✔
215
        run_dir = argv[1];
182✔
216

217
        for (auto& arg : argv) {
371✔
218
            if (arg.find("RUN_") != std::string::npos) {
364✔
219
                input_file = arg;
175✔
220
                run_dir    = arg;
175✔
221
                break;
175✔
222
            }
223
        }
224

225
        if (access(input_file.c_str(), F_OK) != 0) {
182✔
226
          input_file = "";
×
NEW
227
          if (argv[1] != "trick_version" && argv[1] != "sie" && argv[1] != "-help" && argv[1] != "--help"
×
NEW
228
              && argv[1] != "-h" && argv[1] != "help") {
×
NEW
229
              std::cerr << "\nERROR: Invalid input file or command line argument." << std::endl;
×
NEW
230
              exit(1);
×
231
          }
232
        }
233

234
        found = run_dir.find_last_of('/');
182✔
235
        if ( found != std::string::npos ) {
182✔
236
            run_dir.erase(found) ;
182✔
237
        } else {
238
            run_dir = "." ;
×
239
        }
240
        /* check existence of run directory */
241
        if (access(run_dir.c_str(), F_OK) != 0) {
182✔
242
            std::cerr << "\nERROR: while accessing input file directory \"" << run_dir << "\" : " << std::strerror(errno) << std::endl ;
×
243
            exit(1);
×
244
        }
245

246
        output_dir = run_dir ;
182✔
247

248
        for (int ii = 1; ii < argc; ii++) {
367✔
249
            if (argv[ii].compare(0, 3, "-OO") == 0 || argv[ii].compare(0, 2, "-O") == 0) {
185✔
250
                if (ii == ( argc - 1 )) {
1✔
251
                    std::cerr << "\nERROR: No directory specified after -O or -OO argument" << std::endl ;
×
252
                    exit(1) ;
×
253
                }
254
                /* Output data directory */
255
                output_dir = user_output_dir = argv[ii + 1];
1✔
256
                if (argv[ii].compare(0, 3, "-OO") == 0) {
1✔
257
                    output_dir = output_dir + "/" + run_dir;
1✔
258
                }
259
            }
260
        }
261

262
        /* Create output directory if necessary. */
263
        if (access(output_dir.c_str(), F_OK) != 0) {
182✔
264
            if (create_path(output_dir) != 0) {
1✔
265
                std::cerr << "\nERROR: While trying to create output directory \"" << output_dir << "\" : " << std::strerror(errno) << std::endl ;
×
266
                exit(1) ;
×
267
            }
268
        } else {
269
            /* check permissions on output directory */
270
            if (access(output_dir.c_str(), (W_OK|X_OK) ) == -1) {
181✔
271
                std::cerr << "\nERROR: while writing to output directory \"" << output_dir << "\" : " << std::strerror(errno) << std::endl ;
×
272
                exit(2) ;
×
273
            }
274
        }
275
    }
276

277
    return(0) ;
182✔
278

279
}
280

281

282
/**
283
@design
284
-# Get the current system date and time.
285
-# Set the subdirectory within the current output directory to
286
   DATA_<year>_<month>_<day>_<hour>_<minute>_<second>
287
   -# Attempt to create the output directory if it does not exist.
288
      -# Exit if the simulation cannot be created.
289
*/
290
int Trick::CommandLineArguments::output_dir_timestamped_on() {
×
291

292
    time_t date ;
293
    struct tm *curr_time ;
294
    char temp_str[256] ;
295

296
    date = time(NULL) ;
×
297
    curr_time = localtime(&date) ;
×
298

299
    snprintf(temp_str, sizeof(temp_str), "DATA_%4d_%02d_%02d_%02d_%02d_%02d",
×
300
            curr_time->tm_year + 1900 , curr_time->tm_mon + 1 , curr_time->tm_mday,
×
301
            curr_time->tm_hour , curr_time->tm_min , curr_time->tm_sec );
302

303
    time_stamp_dir = std::string(temp_str) ;
×
304

305
    if ( ! user_output_dir.empty() ) {
×
306
        output_dir = user_output_dir + "/" + time_stamp_dir ;
×
307
    } else {
308
        output_dir = run_dir + "/" + time_stamp_dir ;
×
309
    }
310

311
    /* Create directories if necessary. */
312
    if (access(output_dir.c_str(), F_OK) != 0) {
×
313
        if (mkdir(output_dir.c_str(), 0775) == -1) {
×
314
            std::cerr << "\nERROR: While trying to create dir \"" << output_dir << "\" Exiting!" << std::endl ;
×
315
            exit(1) ;
×
316
        }
317
    }
318

319
    output_dir_timestamped = 1 ;
×
320
    return(0) ;
×
321
}
322

323
/**
324
@design
325
-# If the user had specified an output directory reset
326
   the output directory to the user specified directory
327
-# Else set the output directory to the run directory.
328
*/
329
int Trick::CommandLineArguments::output_dir_timestamped_off() {
×
330

331
    if ( ! user_output_dir.empty() ) {
×
332
        output_dir = user_output_dir ;
×
333
    } else {
334
        output_dir = run_dir ;
×
335
    }
336

337
    output_dir_timestamped = 0 ;
×
338
    return(0) ;
×
339

340
}
341

342
/**
343
@design
344
-#  Sets the value of output_dir
345
*/
346
void Trick::CommandLineArguments::set_output_dir(std::string output_directory) {
×
347
    output_dir = output_directory;
×
348
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc