• Frist (unregistered)

    luanch frist comment

  • (nodebb)

    Then we touch a file because we're going to redirect output to it

    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.)

    In a shell script, if a command fails, the script stops

    Only if you have run set -e beforehand.

  • (nodebb)

    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.

  • Early Bird (unregistered)

    That's some lovely bash but you left us all hanging. What happened to Robert? Did he find the problem?

  • (nodebb)

    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.

  • LZ79LRU (unregistered) in reply to dpm

    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.

  • Officer Johnny Holzkopf (unregistered) in reply to LZ79LRU

    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...

  • Foo AKA Fooo (unregistered)

    "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.

  • Sou Eu (unregistered) in reply to toodle

    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.

  • R Samuel Klatchko (unregistered)

    In a shell script, if a command fails, the script stops.

    That's not true for bash. By default bash continues although that can be changed with set -e or set -o errexit.

  • (nodebb)

    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")'

  • SG (unregistered)

    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.

  • LZ79LRU (unregistered) in reply to SG

    In the immortal words of the great M.Bison. "Of course!"

  • (nodebb) in reply to toodle

    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.

  • (nodebb) in reply to Sou Eu

    Do everything in C without any system calls.

    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 avoiding system() is a very good plan.

  • (nodebb)

    We take rc.local an find every line that isn't cd /usr/lib/smm9431, and pipe it to that temp file. Then we copy that file right back over rc.local just so we can… echo that line in again.

    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 into rc.local. The combination of the grep -v and echo ensures that this line only ever occurs once no matter how many times the scrogram is executed.

  • MaxiTB (unregistered)

    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.

  • nz (unregistered) in reply to The Beast in Black

    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

    Only if you mean the choice of "killed with SIGSEGV", " killed with SIGILL", and maybe "killed with SIGBUS". Returning a regular exit code requires a syscall.

  • Graham (unregistered)

    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"

  • (nodebb) in reply to dkf

    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

    Nope. When a process exits, it calls _exit() implicitly or explicitly which is a system call.

Leave a comment on “A Reckless Driver”

Log In or post as a guest

Replying to comment #:

« Return to Article