- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
luanch frist comment
Admin
Regardless of the small point that
some_command > x.x
will create the file x.x automatically. (Pendantry: it's a create-or-truncate operation, unlike>>
which is a create-or-append operation.)Only if you have run
set -e
beforehand.Admin
Linux does not honour the setuid bit on shell scripts. This program looks like an ill-concieved workaround; if the binary is setuid root, then this would effectively run a script as root.
Admin
That's some lovely bash but you left us all hanging. What happened to Robert? Did he find the problem?
Admin
Everything else aside, I cannot imagine why they didn't simply write all of the commands to a temporary text file and issue a single system() call to invoke it. But then, I wouldn't have written that to begin with.
Admin
If I had to take a guess I'd say that It's for the same reason as why they did not just write a C program.
The person doing this obviously felt confident with shell scripts and nothing else. But when they ran into the issue explained by toodle they had to find an alternative. And my guess is that (and since this is said to be old this is plausible) the only alternative they had on hand was a C compiler that they had no idea what to do with.
So the one working on this just googled "how to run shell script in C", found a response on stackoverflow showing how to run a line of script and just copy pasted without thought.
Admin
It is also possible that the installer started as a regular shell script, but some PHB said "We cannot do that, we need a program, not a script, so the users cannot see our intelectial proberty and copy our product!" So someone got the "clever" idea to wrap the script's lines into system() calls in C. A few years later, the whole thing was made open-source...
Admin
"The call to system is just a call to the shell to launch new processes to execute each step." That's the implementation-TRWTF here. Each step launches a shell which launches the actual command, so 2 processes per step. A simple shell script would only launch 1 process per step. (I know, who cares about 17 redundant processes these days ...)
Merging/removing some redundant steps and using "sed -i" might actually make the whole thing slightly readable.
"In a shell script, if a command fails, the script stops." Unfortunately not by default. Only with "set -e" which basically any shell script should set.
And you're right, rc.local was for the admin. No install script should mess with it. Actually that's TWRTF. If they did it properly, they could have just run the newly installed rcN.d script (thereby proving that the script works) instead of loading the module manually which is a good indicator of the whole mess they've created.
Admin
Depending on how you configured your Linux, the setuid or the setgid bit might be ignored on scripts. Based on the commands being executed, I'm assuming this is an install program.
There are two sane approaches. In both, the installer should place an executable in the /etc/rc.d directory and symlink to it in each runtime level which needs the driver. Uninstalling is much easier if we don't manipulate rc.local.
Approach 1: Do everything in C without any system calls. C has methods for creating directories (mkdir), moving files (rename), and creating softlinks (symlink). It is trivial to create functions to copy files.
Approach 2: Since the author is more comfortable in shell script than in C, the C program should make a single system call to a shell script with all the commands. The return value of system should be captured and passed to exit.
Admin
That's not true for bash. By default bash continues although that can be changed with
set -e
orset -o errexit
.Admin
You would not believe how many times I've seen that anti pattern - take a shell script, make it into c/c++/perl/python by wrapping each lines with the system call method in the language.
And yes I have seen python with lines like 'os.system("echo some message >> logfile")'
Admin
And just for good measure, all the output is redirected to /dev/null, so good luck figuring out what went wrong when something inevitably does.
Admin
In the immortal words of the great M.Bison. "Of course!"
Admin
It might be a great workaround for the no suid "problem" -- but as I'm seeing it, rc.local runs at boot time.
As root.
Admin
There's a big difference between a system call and a call to
system()
. About the only thing you can do without using system calls (possibly hidden within a library) is to exit with the status code of your choice; no files, no sockets, nothing that persists, reads input or produces output at all. Whereas avoidingsystem()
is a very good plan.Admin
There is a scenario where this is actually a valid non-WTF operation: if the scrogram (script + program) is run multiple times on the same system without any other changes. In this scenario, without the
grep -v
before the echo, the scrogram would just keep appending multiple lines intorc.local
. The combination of thegrep -v
andecho
ensures that this line only ever occurs once no matter how many times the scrogram is executed.Admin
The weirdest part of all of this is zhat it wouldnt be that hard to implement everything straight in C; no idea why the bothered with the shell script in the first place. That feels a bit to me like your old school senior/junior developer relationship as in the senior throwing a shell script down to the junior with the task to implement it in C and that's pretty much what was the result and when finally the senior saw it, he couldnt give a fuss about it.
Admin
I normally wouldn't comment on it, but there are several typos in this story:
"linux" => "Linux" "luanch" => "launch" "tirectory" => "directory" "an insmod it" => "and insmod it" "an find every line" => "and find every line" "end- ensuring" => end &emdash; ensuring" "Which, there's a huge difference between this and a shell script." => No idea what "which" is doing here "command- an exit status" => "command &emdash; an exit status"
Admin
Nope. When a process exits, it calls
_exit()
implicitly or explicitly which is a system call.