Compared to other options like command line options or configuration files or environmental variables or asking the user interactively to set the values , this approach seems very much worse. It is a lot less practical *and* fragile.
How can you know that this specific string will exist at a certain position in the executable ?
// ensure last 3 bytes are digits, else return
for (int i = 0; i < 2; i++) if (!isdigit(bytes[i])) return;
What happens if getpath() returns NULL ?
You keep writing 3 .Best to use a symbolic constant.
I take it ops is a global variable ?
On Unix , if you just want to test for the existence of a file , access()
is a simpler way to do it.
char *path_env = getenv("PATH");
if (!path_env) return NULL;
char path_env_copy[MAX_SIZE];
strncpy(path_env_copy, path_env, sizeof(path_env_copy));
path_env_copy[sizeof(path_env_copy) - 1] = '\0';
char full_path[MAX_SIZE];
char *dir = strtok(path_env_copy, PATH_SEPARATOR);
while (dir) {
snprintf(full_path, sizeof(full_path), "%s%s%s", dir,
(dir[strlen(dir) - 1] == DIR_SEPARATOR[0] ? "" :
DIR_SEPARATOR), fname);
if (stat(full_path, &buffer) == 0) {
char *result = strdup(full_path);
if (!result) return NULL; // memory allocation error <--
This line is redundant.
I wouldn't use strtok() at all for this but rather strchr() and keep track myself of the position in the string and not modify the string at
all. This way
- you can use the string returned by getenv() directly instead of having
to copy it.
- you don't have to call strlen() when you have already traversed the
string to find the separator. Traversing the string for a second time
probably won't have a noticeable effect for performance in this context
but this kind of thing where the code has done a certain somewhat costly
computation (traversing part of the string) and then immediately does
again almost the same computation instead of using the result found by
the first computation , grates me.
If I remeber correctly , the convention is that if :: exists in PATH
then it's the same as :.: i.e. the current working directory. Your
code does not handle this case. Yet another reason to do the searching
in the string yourself instead of using strtok() .
Spiros Bousbouras <[email protected]> wrote:
Compared to other options like command line options or configuration files or
environmental variables or asking the user interactively to set the values , >> this approach seems very much worse. It is a lot less practical *and* fragile.
How can you know that this specific string will exist at a certain position >> in the executable ?
Because it checks that does...
// ensure last 3 bytes are digits, else return
for (int i = 0; i < 2; i++) if (!isdigit(bytes[i])) return;
What happens if getpath() returns NULL ?
Ouch busted...
You keep writing 3 .Best to use a symbolic constant.
Why? 3 is always 3. Maybe I dont undestand what you mean...
I take it ops is a global variable ?
In this example, yes.
On Unix , if you just want to test for the existence of a file , access()
is a simpler way to do it.
char *path_env = getenv("PATH");
if (!path_env) return NULL;
char path_env_copy[MAX_SIZE];
strncpy(path_env_copy, path_env, sizeof(path_env_copy));
path_env_copy[sizeof(path_env_copy) - 1] = '\0';
char full_path[MAX_SIZE];
char *dir = strtok(path_env_copy, PATH_SEPARATOR);
while (dir) {
snprintf(full_path, sizeof(full_path), "%s%s%s", dir,
(dir[strlen(dir) - 1] == DIR_SEPARATOR[0] ? "" :
DIR_SEPARATOR), fname);
if (stat(full_path, &buffer) == 0) {
char *result = strdup(full_path);
if (!result) return NULL; // memory allocation error <--
This line is redundant.
Please explain why you think so.
I wouldn't use strtok() at all for this but rather strchr() and keep
track myself of the position in the string and not modify the string at
all. This way
- you can use the string returned by getenv() directly instead of having >> to copy it.
- you don't have to call strlen() when you have already traversed the
string to find the separator. Traversing the string for a second time
probably won't have a noticeable effect for performance in this context
but this kind of thing where the code has done a certain somewhat costly >> computation (traversing part of the string) and then immediately does
again almost the same computation instead of using the result found by
the first computation , grates me.
I dunno, is it perfect? Nah. Is it a good start? Well, yeah =)
? I don't know, but I think you might have thought twice about that -1.
I could not tell what it was supposed to do so I didn't comment, but
there's definitely a "let's just try" sense to the code. For example,
you examine and use three characters, but you don't test if three
characters were actually read.
It's recommended *not* to include the current directory in $PATH.
On Tue, 20 Feb 2024 06:56:06 -0000 (UTC)
[email protected] (Mike Sanders) wrote:
Just thinking aloud... Imagining here allowing more advanced users of
my app to modify a string of digits residing at the end of my project's
binary/exe. When the app loads, it reads in those digits. So far (knock
on wood), I've not run up against a single case where the code below has
failed to work under multiple OSs. A method mostly for power user's.d
[email protected] (Mike Sanders) writes:
Keith Thompson <[email protected]> wrote:
It's recommended *not* to include the current directory in $PATH.
I've been thinking about that very thing in fact. It renders my
idea of a binary reading a few bytes from its-self all but dead.
I wont subvert a given security model for a configuration flag
or two...
But there you have it, a wonky idea, I've got plenty of them.
Under Linux, a program can find its executable via /proc/$$/exe .
For example , your code has
fseek(bin, -3, SEEK_END); // jump 3 bytes before end of file
unsigned char bytes[3];
fread(bytes, 1, 3, bin);
.Just reading this it is not immediate clear whether all appearances of 3 refer to the same conceptual entity or different ones which all happen to have the value 3. Using a constant would have made it clear that it is the former. Additionally , if you ever want to change the value , it is simpler to only do it in one place.
Talk about reinventing the wheel.
That was a feature in 1960's operating systems. Usually called
a switch register. Which was implemented first in hardware,
and later in the operating system. In several systems, the
OS (or binary loader) would load the value into some part
of the application's memory before it starts (in one case,
at address zero).
Using an environment variable is far preferable, at least on
unix-like or POSIX operating environments.
fseek(bin, -3, SEEK_END); // jump 3 bytes before end of file
On 26 Feb 2024 21:22:33 GMT
[email protected] (Stefan Ram) wrote:
Spiros Bousbouras <[email protected]> writes:The way your are quoting me gives the impression that I wrote the code.
fseek(bin, -3, SEEK_END); // jump 3 bytes before end of fileA binary stream need not meaningfully support fseek calls
with a whence value of SEEK_END.
I didn't , I was quoting Mike Sanders quote.
Lines beginning with ">" are from the post at the end of the References: >>fseek(bin, -3, SEEK_END);
I am now testing a new attribution line added by my post script
(which I have written in Python). - If one still should read
"writes:", above something went wrong.
While I usually do post test posts to test newsgroups, in this case,
I post to "comp.lang.c", so that Spiros can see my new attribution
line and complain again should he still deem it to be misleading.
Lines beginning with ">" are from the post at the end of the References:
fseek(bin, -3, SEEK_END);
I am now testing a new attribution line added by my post script
(which I have written in Python). - If one still should read
"writes:", above something went wrong.
While I usually do post test posts to test newsgroups, in this case,
I post to "comp.lang.c", so that Spiros can see my new attribution
line and complain again should he still deem it to be misleading.
You're overcomplicating things.
Just thinking aloud... Imagining here allowing more advanced users of
my app to modify a string of digits residing at the end of my project's binary/exe. When the app loads, it reads in those digits. So far (knock
on wood), I've not run up against a single case where the code below has failed to work under multiple OSs. A method mostly for power user's.
The user simply opens the compiled project in their favorite hex editor
& modifies the pre-existing string, a pseudo bitmask of sorts. Certainly
the user could unwittingly add/remove bytes rather than only modifying the bytes, still its a nifty idea. But practical? I'm not so sure on that point.
Any other gotchas of note?
If they can only modify bytes, not add or remove, you can just put some
bytes anywhere in your code and the user can find them modify them with
a hex editor. You don't need to do anything special to allow someone to modify a file in their possession.
[email protected] (Mike Sanders) writes:
Keith Thompson <[email protected]> wrote:
It's recommended *not* to include the current directory in $PATH.
I've been thinking about that very thing in fact. It renders my
idea of a binary reading a few bytes from its-self all but dead.
I wont subvert a given security model for a configuration flag
or two...
But there you have it, a wonky idea, I've got plenty of them.
Under Linux, a program can find its executable via /proc/$$/exe .
YM sprintf(buf, "/proc/%d/exe", getpid()) // or if paranoid snprintf
because substituting for $$ is a feature of shell and perl only. But /proc/self/exe works in anything.
[email protected] wrote:
YM sprintf(buf, "/proc/%d/exe", getpid()) // or if paranoid snprintf
because substituting for $$ is a feature of shell and perl only. But
/proc/self/exe works in anything.
For Linux, sure. But the BSDs & Apple & Win...
Reading itsself, its real self, seems to me to be the only
cross platform way.
For Linux, sure. But the BSDs & Apple & Win...
Reading itsself, its real self, seems to me to be the only
cross platform way.
Perhaps, but there seems to be no cross-platform way for a program
to determine the "itself" to read.
Which may be the wrong order. Regardless of the overall merits of your idea , it should mimic as close as possible how the system finds executables. This means not search in the current directory unless the appropriate constructs exist in PATH and search the components in the same order as they appear in PATH .This implies recognising :: in PATH and my point is that using strtok() (apart from its other issues) makes it harder to do this.
| Sysop: | Keyop |
|---|---|
| Location: | Huddersfield, West Yorkshire, UK |
| Users: | 715 |
| Nodes: | 16 (0 / 16) |
| Uptime: | 167:41:32 |
| Calls: | 12,096 |
| Calls today: | 4 |
| Files: | 15,003 |
| Messages: | 6,517,813 |