Just call `seteuid(2)` to do the appropiate unprivileged stuff. `seteuid(2)` allows to switch between the *real*(or saved) user id (the one that launches the suid program or `root` in your case) and *the suid* user id (the one the suid program belongs to) so there should be no problem to regain privileged user id afterwards (as the saved user id is `root`, you don't have any issue to switch to it again and again).
If you change uids with `setuid(2)` you'll change **all** (effective, saved and real uids) and this is only allowed to the root user (or a program setuid root, and there's no way back then).
Look at the next example:
# File pru49015.c:
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
int main(int argc, char **argv)
{
int opt, suid = getuid(), /* this is the saved uid */
uid = 0;
while ((opt = getopt(argc, argv, "i:")) != EOF) {
switch (opt) {
case 'i': uid = atoi(optarg); break;
}
}
/* execute this program with root privileges, like setuid root, for example */
printf("real uid=%d; effective uid=%d\n", getuid(), geteuid());
seteuid(uid); /* change to the non-privileged id configured */
printf("real uid=%d; effective uid=%d\n", getuid(), geteuid());
seteuid(suid); /* return back to saved uid */
printf("real uid=%d; effective uid=%d\n", getuid(), geteuid());
}
You will get an output like this:
$ pru49015 -i 37
real uid=502; effective uid=0
real uid=502; effective uid=37
real uid=502; effective uid=502
when used as a setuid-root program
If you use it as root, you'll get the following output:
$ sudo pru$$ -i 37
real uid=0; effective uid=0
real uid=0; effective uid=37
real uid=0; effective uid=0
The mechanism is that you are allowed on a setuid-<id> program to switch between the user you are (let's call it the *saved user id*) and the user the program runs setuid to (the called *effective user id* or *suid* user) as many times as you want.