Shell confusion

Hello again. I’ve been struggling with the code below. The objective is to replace the existing OpenVPN startup command in /etc/rc.d/rc.local with a new one, based on user input. I’ve been informed that Xojo doesn’t allow access to root files, so I’m using gksu to get around that. The app is given superuser privileges by the user on startup. To make things easier to decipher, I’ve added comments in the code. Can somebody please tell me what I’m missing here?

[code]// create new command based on user input
// \& – backslash required for sed command
// replace all slashes so they are escaped for sed command

dim comstr as string
comstr = “openvpn --config “+confpath.text+” --auth-user-pass “+authpath.text+” \&”
comstr = comstr.ReplaceAll("/", “\/”)

// get previous line added to /ect/rc.d/rc.local (recorded in rclocal.conf)

dim f3 as new FolderItem(app.applocation+“rclocal.conf” )
dim tis3 as TextInputStream = TextInputStream.Open(f3)
dim line2 as string = tis3.ReadLine
line2 = line2.ReplaceAll("/", “\/”) // needed for sed command

dim s as shell
s = new shell
s.execute(“gksu -u root sed -i '\'s:”+line2+":"+comstr+":g\’’ /etc/rc.d/rc.local")

// the above execute works with ordinary text, but not my variables. I have verified that variables are formatted correctly for sed, and if I enter the sed command in terminal using the actual text the variable represent (minus the ’ escaping), the command works.

If s.ErrorCode <> 0 Then
MsgBox("Error code: " + Str(s.ErrorCode))
s.close
else
s.close
end if[/code]

What’s in s.Result after you call Execute?

Thanks for the reply, Greg. s.Result shows:

bash: -c: line 0: unexpected EOF while looking for matching `'' bash: -c: line 1: syntax error: unexpected end of file
I haven’t got the foggiest idea what that means. :frowning:

Do me a favor and put the entire command string into a variable before sending it to the shell with something like:

dim cmd as string = "gksu -u root sed -i '\\'s:"+line2+":"+comstr+":g\\'' /etc/rc.d/rc.local" Break s.Execute(cmd)

Run that in the debugger and show me what cmd has in it (with your passwords removed). My guess is that line2 has single quotes in it.

line2 is a full folder path read from a file containing just the previous openvpn startup command. No single quotes. Looks exatly like this:

openvpn --config /etc/sysconfig/network-scripts/vpn.d/openvpn/Toronto.conf --auth-user-pass /etc/sysconfig/network-scripts/vpn.d/openvpn/auth.txt \\&

I ran what you told me to, but the debugger doesn’t show the full command output.

It should. You may need to click the magnifying glass next to the string to see all of it though.

That’s my point though. What you’re showing me is what you think that string contains, and we really need to know what it actually contains.

For instance… are you sure that:

dim line2 as string = tis3.ReadLine

Is getting you the line you expect?

I have verified line2’s actual output by loading it into a textarea. Did that for comstr as well. All looks good to me. here’s the debugger output:

gksu -u root sed -i '\\'s:openvpn --config \\/etc\\/sysconfig\\/network-scripts\\/vpn.d\\/openvpn\\/Toronto.conf --auth-user-pass \\/etc\\/sysconfig\\/network-scripts\\/vpn.d\\/openvpn\\/auth.txt \\&:openvpn --config \\/etc\\/sysconfig\\/network-scripts\\/vpn.d\\/openvpn\\/Toronto2.conf --auth-user-pass \\/etc\\/sysconfig\\/network-scripts\\/vpn.d\\/openvpn\\/auth.txt \\&:g\\'' /etc/rc.d/rc.local

I’m just guessing at this point, but I wonder if the single quotes are making gksu think only the part within single quotes is the actual command.

And putting that string in a terminal window works?

If I un-escape the single quotes, then yes, it works. However, if I use the unescaped command in my project, it fails.

I’m confused. Why would you escape the quotes when you send it to the shell if you don’t need them on the command line?

Because using the command un-escaped in the shell fails, and crashes the debugger.

I’m thinking this may actually be a gksu problem. If you put anything inside quotes after “gksu -u root”, it thinks that’s the command to be run. Maybe the “sed -i” part is being treated as an incomplete command because the rest is inside single quotes, thus making gksu think only the quoted part is the actual command. Essentially like trying to run 2 incomplete commands. Does that make any sense?
BTW: the gksu docs are completely lacking in respect to this.

EDIT: that reminds me of why I needed to escape the single quotes in the 1st place. Sorry, I’ve just ended up so confused what with all the multitude of approaches I’ve tried.

Just curious… why are you using gksu? It seems to require gtk, which shell definitely does not. You may have better luck using su or sudo

I guess I assumed that su wouldn’t work without user input since I’m not actually running a terminal. Am I an idiot (again)?

Does gksu show the password prompt when using a shell object?

Yes. In fact, to have root access right from the start, I used shell/gksu to echo “”. This gives root access to anything else that requires it in the app without the user being prompted every time, unless they choose not to save the authentication for the duration of the session.

OK, now I’m having trouble using su. Since I can’t find any useage info that doesn’t relate to OSX, I’m flailing wildly in the dark…
Trying this, since using shell to execute su on its own does nothing:

dim cmd as string = "su | sed -i 's:"+line2+":"+comstr+":g' /etc/rc.d/rc.local"

Keep getting this result:

sed: couldn't open temporary file /etc/rc.d/sedhspxle: Permission denied Password: su: Authentication failure

I don’t know if it matters, but why is su failing AFTER the sed command?

Here’s something that you can use like gksu that sets the sudo timer such that sudo doesn’t prompt. It’s an exercise for you to get the user’s password.

theShell.Execute "sudo -K" theShell.Mode = 2 #if TargetLinux theShell.Execute "sudo /bin/true" #Else theShell.Execute "sudo /usr/bin/true" #EndIf Do theShell.Poll App.DoEvents(2) #If TargetMacOS If InStr(theShell.Result, "Password:") <> 0 Then Call theShell.ReadAll theShell.WriteLine passwd End If #Else If InStrB(theShell.Result, "[sudo] password") <> 0 Then Call theShell.ReadAll theShell.WriteLine passwd End If #EndIf Loop Until Not theShell.IsRunning

Thanks very much, Tim. While the users of my distro aren’t going to be very happy about the use of sudo (they’ve been warned against it), I’ll give your suggestion a try. At this point, I’d try sticking pins in my eyes if I thought it might help. LOL
Here’s why

Why on Earth would anyone warn against sudo? It’s much saner than straight up “su” and can be controlled very carefully via the /etc/sudoers and /etc/sudoers.d components down to specific apps/tools for specific users. If you have users who are afraid of sudo, they should either get a good book on Unix system administration or probably contact that South Florida real estate company …

My response to that post is “rm is simply a Unix tool, but can be highly abused if used improperly …” or “mv is simply a Unix tool, but can be highly abused if used improperly…”. Anything on a Unix-based system can be abused. Using sudo is the least probable issue for problems.

Plus, with my code above, how would your user know WHAT you are using? All of that would be compiled into your app and completely hidden from the users. Your app would completely hide the sudo side of things in much the same manner that gksu does. If they are afraid of sudo, they should be just as afraid of gksu and friends. Under the hood, the results are the same - someone gets elevated permissions. What they DO with those permissions is something you control in your app/tool.

Also, that whole post reads more like an “if you break it you can’t blame us” discord instead of providing real information for users (aside from the lite treatment of sudoers). Sorry if that feels like a slight, but it reads more like CYA than useful, usable information.

Tim Jones
(BOFH) Bastard Operator From Hell since 1982 (SunOS, SCO, A/IX, DG/UX, IRIX, PTX, SysV, Ultrix, CTIX, and so many others …)
Linux hacker since 1993 (0.99pl12)
BSD386 hacker since 1995