Setup a binary that needs SU permissions to run at Startup (Manjaro KDE Plasma)

Does anyone know how to do this reliably in Manjaro?:

Setup a binary that needs SU permissions to run at Startup (Manjaro KDE Plasma).

The binary has to access the RPI’s GPIO pins and works when executed with SUDO.

Hi @DrAV,

I do something similar.

You can allow per-binary execution with sudo with a custom entry in sudoers.

It’s actually not that hard. The way I did it:

  1. Create a custom file in etc/sudoers.d for the configuration. This way it doesn’t mess with the ‘/etc/sudoers’ file.
visudo /etc/sudoers.d/mirdarthos

(I changed my visudo to use the micro editor, so can’t really tell you which steps would exactly be neccessary for the rest.)

  1. In the file, I added a line, with the same syntax as used in your sudoers file to allow the execution of a single file with sudo without requiring a password:
<username> ALL=(ALL) NOPASSWD: <full/path/to/script>

Where:

  • <username>: The name of the user executing the script. For me, it was mirdarthos, as I’d be the one executing the script.
  • <full/path/to/script>: The full path to the executable that should be allowed to run as root.
  1. Save the file and exit. Just for good measure reboot. (I don’t think it’s really neccessary, but it can’t really hurt.)

You should now, at least theoretically, bee able to tun <full/path/to/script> using sudo without entering a password:

sudo <full/path/to/script>

You can then add it to run on startup and it won’t require a password.

At least that’s the theory. If it works, feel free to heap on the praise. However, if it doesn’t, well, then I’m off for the day. :wink:

Hi Midarthos, please tell me the steps involved with that editor of yours and where I can get it from as visudo does not appear on my machine:

visudo: no editor found (editor path = /usr/bin/vi)
[fat@RPI4 sudoers.d]$

Hi @DrAV,

visudo is not an editor. Rather, it’s a command. That makes editing sudoers files safe. You can also use nano. (In fact, that might be easier, so I’ll explain that here.)

nano should be installed by default, but to check run the following in the terminal:

pamac search nano

If it is installed, it should be similar to mine:

[...]
nano                                                                                                                                                                         [Installed] 5.9-1                        core

Notice the [Installed] there.

If it’s not installed, install it with:

pamac install nano

To change the editor to nano, add the following to /etc/environment:

# a Custom editor for visudo
SUDO_EDITOR=/usr/bin/nano

This will require administrative rights, but polkit should prompt you for the password if required. I think.

After this, it might be a good idea to restart and try the steps again, from where you got the error.

Edit:
And I’ve got to run now, so if you still need help, try googling for the problem, or wait, hope and pray someone can help you further. Because, it being me, there might be (a) better way(s) to do it. I don’t know, this is just what I’ve got here.

Further reading: Sudo - ArchWiki

Managed to do it using visudo (had to escalate the terminal to root and used visudo from there).
And it runs without entering the password :ok_hand:

I’m adding it to the Autostart GUI and will let you know if it runs automatically when I reboot.

OK all works now!

The script is below in case anyone else wants to run a fan from a GPIO pin; just need GCC to compile it to a binary, add it to a file in sudoers.d (as explained above), then add it to the autostart using the GUI with sudo in front of the filename to execute with root privileges. I use an IRLU2703 nMOSFET.

Many thanks,
DrAV


#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define IN  0
#define OUT 1
#define LOW  0
#define HIGH 1

static int
GPIOExport(int pin)
{
#define BUFFER_MAX 3
	char buffer[BUFFER_MAX];
	ssize_t bytes_written;
	int fd;

	fd = open("/sys/class/gpio/export", O_WRONLY);
	if (-1 == fd) {
		fprintf(stderr, "Failed to open export for writing!\n");
		return(-1);
	}

	bytes_written = snprintf(buffer, BUFFER_MAX, "%d", pin);
	write(fd, buffer, bytes_written);
	close(fd);
	return(0);
}

static int
GPIOUnexport(int pin)
{
	char buffer[BUFFER_MAX];
	ssize_t bytes_written;
	int fd;

	fd = open("/sys/class/gpio/unexport", O_WRONLY);
	if (-1 == fd) {
		fprintf(stderr, "Failed to open unexport for writing!\n");
		return(-1);
	}

	bytes_written = snprintf(buffer, BUFFER_MAX, "%d", pin);
	write(fd, buffer, bytes_written);
	close(fd);
	return(0);
}

static int
GPIODirection(int pin, int dir)
{
	static const char s_directions_str[]  = "in\0out";

#define DIRECTION_MAX 35
	char path[DIRECTION_MAX];
	int fd;

	snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/direction", pin);
	fd = open(path, O_WRONLY);
	if (-1 == fd) {
		fprintf(stderr, "Failed to open gpio direction for writing!\n");
		return(-1);
	}

	if (-1 == write(fd, &s_directions_str[IN == dir ? 0 : 3], IN == dir ? 2 : 3)) {
		fprintf(stderr, "Failed to set direction!\n");
		return(-1);
	}

	close(fd);
	return(0);
}

static int
GPIORead(int pin)
{
#define VALUE_MAX 30
	char path[VALUE_MAX];
	char value_str[3];
	int fd;

	snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", pin);
	fd = open(path, O_RDONLY);
	if (-1 == fd) {
		fprintf(stderr, "Failed to open gpio value for reading!\n");
		return(-1);
	}

	if (-1 == read(fd, value_str, 3)) {
		fprintf(stderr, "Failed to read value!\n");
		return(-1);
	}

	close(fd);

	return(atoi(value_str));
}

static int
GPIOWrite(int pin, int value)
{
	static const char s_values_str[] = "01";

	char path[VALUE_MAX];
	int fd;


	snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", pin);
	fd = open(path, O_WRONLY);
	if (-1 == fd) {
		fprintf(stderr, "Failed to open gpio value for writing!\n");
		return(-1);
	}

	if (1 != write(fd, &s_values_str[LOW == value ? 0 : 1], 1)) {
		fprintf(stderr, "Failed to write value!\n");
		return(-1);
	}

	close(fd);
	return(0);
}


//Fan MOSFET Gate on GPIO 14 (change POUT to your pin); MOSFET Drain to fan's negative wire; MOSFET Source to GND; Fan positive wire to +5 VDC
#define POUT 14

//Define how often it will check the temperature (in seconds)
#define ttime 5

int main(int argc, char *argv[])
{
   FILE *fp;
   int temp = 0;

	//Enable GPIO pins
	if (-1 == GPIOExport(POUT) ) return(1);
    usleep(10000);
	//Set GPIO direction
	if (-1 == GPIODirection(POUT, OUT)) return(2);
    usleep(10000);

	while(1){

        fp = fopen("/sys/class/thermal/thermal_zone0/temp", "r");
        fscanf(fp, "%d", &temp);
        temp = temp/1000.0;
        //Uncomment next line if you want to see the temperature printed in a terminal window
        //printf(">> CPU Temp: %.2f°C\n", temp);
        fclose(fp);

        if(temp>65){
            //Write GPIO value
            if (-1 == GPIOWrite(POUT, 1)){
                return(3);
                usleep(10000);
                }
        }
 if (temp<56){
            if (-1 == GPIOWrite(POUT, 0)){
                return(3);
                usleep(10000);
            }
        }
		sleep(ttime);
	}


	//Disable GPIO pins
	if (-1 == GPIOUnexport(POUT)) return(4);

	return(0);
}

This is not the proper way to set values in /etc/environment
In the file itself at the top it states:

# Syntax: simple "KEY=VAL" pairs on separate lines

So they should look like this:

EDITOR=/usr/bin/micro
SUDO_EDITOR=/usr/bin/micro
VISUAL=/usr/bin/kate
DIFFPROG=/usr/bin/meld
2 Likes

Thank you! Updated the post as well.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.