C - System(""); Execute one at a time - c

I've got a system("sudo apt-get update | sudo apt-get -y install apache2 zip unzip"); etc, but its doing all the same commands at once?, how do i make it so it does one after the other is finished?, also some may ask the user to enter information from apt-get, how do i allow this to show?

That pipe character (|) means that the output from sudo apt-get update is being piped into the input of sudo apt-get -y install apache2 zip unzip. Although this doesn't actually make any sense, it does mean both get launched at the same time, which is not what you want.
Either replace the single call with two individual system() calls:
system("sudo apt-get update");
system("sudo apt-get -y install apache2 zip unzip");
Note that when you call system(), your program doesn't resume until the process you launched has exited, so this means the first call will execute, then the second.
Or replace the pipe with && (isn't necessarily guaranteed to work, though it really should on any Linux system):
system("sudo apt-get update && sudo apt-get -y install apache2 zip unzip");
Which means the right-hand side of the command will execute only if the left-hand side exits without error (technically, has an exit status of 0).
You can also replace the pipe with a semicolon (;) instead, which should execute both commands in sequence regardless of the exit status of the first command.

Related

Change ownership of dir to user when running program in sudo

I have a program that I need to run with sudo. I create a directory using mkdir, but this directory has owner and group set to root. That makes sense since I am using sudo. I would like to change the owner and group to the normal user, but I'm not sure how to do that. I thought running system("chown $USER:$USER /directory/") would work, but I suppose since I am in sudo it will just set to root. I was looking into using chown, but I wasn't sure how I was supposed to get the owner and group id. Also it would be good for it to be portable, so I don't want to just hardcode a user/group id.
You're mostly on the right path already, chown is the command you're looking for here.
You can string the two commands to make and then own the directory together using a semicolon.
sudo mkdir test ; sudo chown $USER:$USER test
I've tested this on ubuntu 18.04 and ubuntu 20.04 as that's your tag. The $USER variable resolves to the user that you originally logged in as, not root, as long as you're using it at the beginning of your command like the above. Note that you need to call sudo again when doing the chown portion, the ; ends the sudo elevation.
The coreutils package includes an useful little command, install, you can use instead of mkdir in a sudo context. For example,
sudo install -o USER -g GROUP -m MODE -d DIRECTORY
where USER is the user to own the directory DIRECTORY, GROUP is the group to own the directory, and MODE is the access mode (like chmod) to the directory.
Because system(COMMAND) and popen(COMMAND,...) actually run /bin/sh with -c and COMMAND as parameters, you can use the form
sudo install -o $(id -u) -g $(id -g) -m u=rwx,g=r-x,o=x DIRECTORY
where the shell replaces the user and group names (or rather, numbers, since I'm not using the -n option) before executing sudo. (The id command is also included in coreutils, so you can definitely expect both install and id to be available on all full-blown Linux machines; and even on most embedded systems. It is what all package managers et cetera use to install files, you see.)
Above, I used the mode u=rwx,g=r-x,o=x (equivalently, 0751) as an example; it sets the mode to rwxr-x--x, i.e. grants access to everybody, with owner user and group being able to list the directory contents, and only the owner user being able to create new files or directories in it.

chmod 0644 :Operation not permitted

i wanted to download java using sudo apt on ubuntu 18.04 but it sent me "E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"
so i tried to run "apt-get update" which sent me lots of error that looks like this " chmod 0644 of file /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_bionic_InRelease failed - 201::URIDone (1: Operation not permitted)" so i tried to change the permission using chmod 0644 /var/lib/apt/lists/"
but it didn't work also tried a couple other methods but still didn't work
so hopefully you can tell me what to try to fix it.
btw i'm using windows 10 and running ubuntu 18.04 from the windows store
Remove those files sudo rm -r /var/lib/apt/lists/* and rerun sudo apt-get update

Chocolatey waits for input

Wrote a simple batch to automatically install some packages:
choco install dotnet4.7.1 -y
choco install netfx-4.7.1-devpack -y
choco install microsoft-build-tools -y
The -y switch was added so it won't interact with the user, but I tried to run this batch and just stops at some places. I had to press Enter a few times for the three installations to complete.
How can I make sure this script won't interact with me?
You can try getting the needed "Enter's" from the NUL device:
<nul choco install dotnet4.7.1 -y
This might or might not work; depends on how the application is programmed.

Macports: what exactly does the -f flag mean?

Let's contrast
sudo port install [port_name]
and
sudo port -f install [port_name]
What exactly does the flag -f do in this case? Why don't we use the -f flag each time we install a new port?
On installation, the force flag is used to force activation in case a file that would be provided by the port you are installing already exists on your system. Without the force flag, MacPorts will abort the installation and warn you; with the flag, MacPorts will rename the existing file (appending .mp_$timestamp).
Forcing may become necessary if you have previously uninstalled a version of MacPorts but not cleaned up all the files it provided, or if a third-party installer built using MacPorts installed files into /opt/local (which is wrong, but still happens sometimes).
Because overwriting is not safe behavior, it isn't the default. This is also the reason why you should not always specify -f.
The flag -f is to force the install/install. If there are dependencies that is preventing macports from installing/uninstalling, you can use the -f flag to force the install/uninstall but that is not a desirable way of installing/uninstalling.
Take a look at explanation from https://guide.macports.org/
sudo port uninstall libcomerr
---> Unable to uninstall libcomerr #1.42.9_0, the following ports depend on it:
---> kerberos5 #1.11.3_0
---> subversion #1.8.9_0
---> subversion-perlbindings-5.16 #1.8.9_0
Error: port uninstall failed: Please uninstall the ports that depend on libcomerr first.
You can recursively uninstall all ports that depend on the given port before uninstalling the port itself to work around this. To do that, use the --follow-dependents flag.
$ sudo port uninstall --follow-dependents libcomerr
You can also override this safety check using the -f (force) flag.
Since this will obviously break the dependents you shouldn't do this
unless you know what you are doing.
$ sudo port -f uninstall libcomerr
Although this is an example of uninstall, you can see how -f flag works.

Executing commands in a series in ubuntu terminal

Suppose I have a set of commands to be executed in ubuntu terminal:
for eg:
sudo apt-get update
sudo install xrdp
sudo install java
.....
and many others.
Is it possible in ubuntu to execute the file containing these commands and execute without human intervention (like yes/no) , by default yes?
I tried installing wine , executing $wine cmd /c Commands.bat , after putting all these commands in .bat file but getting errors "Application tried to create a window, but no driver could be loaded."
So, is there any simple way of executing a series of commands in ubuntu?
What you are talking about - multiple commands in one file - is called a "shellscript".
Let's say you have commands.sh:
sudo apt-get update
sudo install xrdp
sudo install java
Then you could execute the commands using:
bash commands.sh
You can also make a directly executable shellscript out of it using the so called shebang mechanism.
Put this line on the very top (line 1) of commands.sh
#!/bin/bash
.. and make the file executable:
chmod +x commands.sh
Now you can execute it directly:
./commands.sh
If you want to say "yes" to all questions, you can use the yes command:
yes | bash "file_with_commands.sh"
No need to do something convolutied and as insane as trying to make cmd.exe work. You already got a perfectly fine working shell on your system. Also you need to understand what programs like sudo do.
sudo is not some magic chant that enables something. sudo is a helper program that allows to start a program with elevated rights. Instead of having a chain of sudo this sudo that you can as just let sudo start a shell and pass a script with all those commands to the shell.
Turning
sudo apt-get update
sudo install xrdp
sudo install java
Into
sudo sh -c 'apt-get update ; install xrdp ; install java'
However that doesn't look right. I think you originally meant to write
sudo apt-get update
sudo apt-get install xrdp
sudo apt-get install java
You can shorten this to
sudo apt-get update
sudo apt-get install xrdp java
Or in coalesced single liner shell
sudo sh -c 'apt-get update ; apt-get install xrdp java'
Now regarding the Yes/No questions. If a program you want to run unattended doesn't offer an option to give a default answer you can make use of the yes program. Even it being named yes it can also answer NO or anything you like:
narfi /home/dw
1007 ~ % yes Hello
Hello
Hello
Hello
Hello
Hello
…
How does this work? There's a concept called the "Standard Input / Output" from which programs read input from and write output to. Shells allow you to redirect the output from one program into the input of another one. This is called pipe-ing. The special character | designates a pipe in shells.
So say you've got a program that wants to see a large number of Aye inputs you could make the following call to the shell
yes Aye | happypirate
So you can combine this with apt-get to give all default yes answer writing
yes | apt-get install …
However this is barking up the wrong tree. Have a look at the call options for apt-get:
~ % apt-get --help
apt 0.9.7.6 for amd64 compiled on Oct 16 2012 18:23:06
Usage: apt-get [options] command
apt-get [options] install|remove pkg1 [pkg2 ...]
apt-get [options] source pkg1 [pkg2 ...]
apt-get is a simple command line interface for downloading and
installing packages. The most frequently used commands are update
and install.
…
-y Assume Yes to all queries and do not prompt <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
…
apt-get gives you an option to auto-answer all yes to all it questions. Neat, right? Note that other programs may use different option keys so you're well advised to always read their fine manuals (RTFM).
At its most basic level, you want to eecute a script. You do that by creating a file like this:
#!/bin/bash
sudo apt-get update
sudo install xrdp
sudo install java
Save that as a file called go, then in the Terminal, you need to make it executable like this:
chmod +x go
Then you can run it by typing:
./go
If your program expects an answer of "yes" for the first question, then "no" for the next question, you can prepare the answers in advance like this and send them into the program:
( echo yes; echo no ) | sudo apt-get update

Resources