@@ -1036,6 +1036,100 @@ char *cmdline_parm::str()
10361036 return args;
10371037}
10381038
1039+ #ifdef SCP_UNIX
1040+ // Return a vector with all filesystem names of "parent/dir" relative to parent.
1041+ // dir must not contain a slash.
1042+ static SCP_vector<SCP_string> unix_get_single_dir_names (SCP_string parent, SCP_string dir)
1043+ {
1044+ SCP_vector<SCP_string> ret;
1045+
1046+ DIR *dp;
1047+ if ((dp = opendir (parent.c_str ())) == NULL ) {
1048+ Warning (LOCATION, " Can't open directory '%s' when searching mod paths. Ignoring. errno=%d" , parent.c_str (), errno);
1049+ return ret;
1050+ }
1051+
1052+ dirent *dirp;
1053+ while ((dirp = readdir (dp)) != NULL ) {
1054+ if (!stricmp (dirp->d_name , dir.c_str ())) {
1055+ ret.push_back (dirp->d_name );
1056+ }
1057+ }
1058+ (void )closedir (dp);
1059+
1060+ return ret;
1061+ }
1062+
1063+ // Return a vector with all filesystem names of "parent/dir" relative to parent.
1064+ // Recurses to deal with slashes in dir.
1065+ static SCP_vector<SCP_string> unix_get_dir_names (SCP_string parent, SCP_string dir)
1066+ {
1067+ size_t slash = dir.find_first_of (" /\\ " );
1068+
1069+ // no subdirectories, no need to recurse
1070+ if (slash == std::string::npos) {
1071+ return unix_get_single_dir_names (parent, dir);
1072+ }
1073+
1074+ // get the names of the first component of dir
1075+ SCP_vector<SCP_string> this_dir_names = unix_get_single_dir_names (parent, dir.substr (0 , slash));
1076+
1077+ SCP_string rest = dir.substr (slash + 1 );
1078+
1079+ SCP_vector<SCP_string> ret;
1080+
1081+ // search for the rest of dir in each of these
1082+ SCP_vector<SCP_string>::iterator ii, end = this_dir_names.end ();
1083+ for (ii = this_dir_names.begin (); ii != end; ++ii) {
1084+ SCP_string this_dir_path = parent + " /" + *ii;
1085+ SCP_vector<SCP_string> mod_path = unix_get_dir_names (this_dir_path, rest);
1086+
1087+ // add all found paths relative to parent
1088+ SCP_vector<SCP_string>::iterator ii2, end2 = mod_path.end ();
1089+ for (ii2 = mod_path.begin (); ii2 != end2; ++ii2) {
1090+ ret.push_back (*ii + " /" + *ii2);
1091+ }
1092+ }
1093+
1094+ return ret;
1095+ }
1096+
1097+ // For case sensitive filesystems (e.g. Linux/BSD) perform case-insensitive dir matches.
1098+ static void handle_unix_modlist (char **modlist, int *len)
1099+ {
1100+ // search filesystem for given paths
1101+ SCP_vector<SCP_string> mod_paths;
1102+ for (char *cur_mod = strtok (*modlist, " ," ); cur_mod != NULL ; cur_mod = strtok (NULL , " ," ))
1103+ {
1104+ SCP_vector<SCP_string> this_mod_paths = unix_get_dir_names (" ." , cur_mod);
1105+ if (this_mod_paths.empty ()) {
1106+ ReleaseWarning (LOCATION, " Can't find mod '%s'. Ignoring." , cur_mod);
1107+ }
1108+ mod_paths.insert (mod_paths.end (), this_mod_paths.begin (), this_mod_paths.end ());
1109+ }
1110+
1111+ // create new char[] to replace modlist
1112+ size_t total_len = 0 ;
1113+ SCP_vector<SCP_string>::iterator ii, end = mod_paths.end ();
1114+ for (ii = mod_paths.begin (); ii != end; ++ii) {
1115+ total_len += ii->length () + 1 ;
1116+ }
1117+
1118+ char *new_modlist = new char [total_len + 1 ];
1119+ memset (new_modlist, 0 , total_len + 1 );
1120+ end = mod_paths.end ();
1121+ for (ii = mod_paths.begin (); ii != end; ++ii) {
1122+ strcat_s (new_modlist, total_len + 1 , ii->c_str ());
1123+ strcat_s (new_modlist, total_len + 1 , " ," ); // replace later with NUL
1124+ }
1125+
1126+ // make the rest of the modlist manipulation unaware that anything happened here
1127+ delete [] *modlist;
1128+ *modlist = new_modlist;
1129+ *len = total_len;
1130+ }
1131+ #endif /* SCP_UNIX */
1132+
10391133// external entry point into this modules
10401134
10411135bool SetCmdlineParams ()
@@ -1318,47 +1412,8 @@ bool SetCmdlineParams()
13181412 strcpy_s (modlist, len+2 , Cmdline_mod);
13191413
13201414#ifdef SCP_UNIX
1321- // for case sensitive filesystems (e.g. Linux/BSD) perform case-insensitive dir matches
1322- DIR *dp;
1323- dirent *dirp;
1324- char *cur_pos, *temp;
1325- char cur_dir[CF_MAX_PATHNAME_LENGTH], delim[] = " ," ;
1326- SCP_vector<SCP_string> temp_modlist;
1327- size_t total_len = 0 ;
1328-
1329- if ( !_getcwd (cur_dir, CF_MAX_PATHNAME_LENGTH ) ) {
1330- Error (LOCATION, " Can't get current working directory -- %d" , errno );
1331- }
1332-
1333- for (cur_pos = strtok (modlist, delim); cur_pos != NULL ; cur_pos = strtok (NULL , delim))
1334- {
1335- if ((dp = opendir (cur_dir)) == NULL ) {
1336- Error (LOCATION, " Can't open directory '%s' -- %d" , cur_dir, errno );
1337- }
1338-
1339- while ((dirp = readdir (dp)) != NULL ) {
1340- if (!stricmp (dirp->d_name , cur_pos)) {
1341- temp_modlist.push_back (dirp->d_name );
1342- total_len += (strlen (dirp->d_name ) + 1 );
1343- }
1344- }
1345- (void )closedir (dp);
1346- }
1347-
1348- // create new char[] to replace modlist
1349- char *new_modlist = new char [total_len+1 ];
1350- memset ( new_modlist, 0 , total_len + 1 );
1351- SCP_vector<SCP_string>::iterator ii, end = temp_modlist.end ();
1352- for (ii = temp_modlist.begin (); ii != end; ++ii) {
1353- strcat_s (new_modlist, total_len+1 , ii->c_str ());
1354- strcat_s (new_modlist, total_len+1 , " ," ); // replace later with NUL
1355- }
1356-
1357- // make the rest of the function unaware that anything happened here
1358- temp = modlist;
1359- modlist = new_modlist;
1360- delete [] temp;
1361- len = total_len;
1415+ // handle case-insensitive searching
1416+ handle_unix_modlist (&modlist, &len);
13621417#endif
13631418
13641419 // null terminate each individual
0 commit comments