How do I give write permission to file in Linux? - c

How can I (programmatically) give write permission on a file to a particular user in Linux? Like, for example, its owner? Everyone has read access to this file.

In a shell or shell script simply use:
chmod u+w <filename>
This only modifies the write bit for the user, all other flags remain untouched.
If you want to do it in a C program, you need to use:
int chmod(const char *path, mode_t mode);
First query the existing mode via
int stat(const char *path, struct stat *buf);
... and just set the write bit by doing newMode = oldMode | S_IWUSR. See man 2 chmod and man 2 stat for details.

The octal mode 644 will give the owner read and write permissions, and just read permissions for the rest of the group, as well as other users.
read = 4
write = 2
execute = 1
owner = read | write = 6
group = read = 4
other = read = 4
The basic syntax of the command to set the mode is
chmod 644 [file name]
In C, that would be
#include <sys/stat.h>
chmod("[file name]", 0644);

chmod 644 FILENAME
6 is read and write, 4 is read only. Assuming the owner of the file is the user you wish to grant write access to.

You can do that using chmod, on ubuntu you can try out
$sudo chmod 666
This would give read/write permissions to all...check this out for more details:
http://catcode.com/teachmod/

You can use chmod 777 <filename>

Related

how to execute a command as root

I develop a C code on Linux (Debian). Time to time, I need to execute some commands through system()
I wonder if it is possible to execute a command via system()as root. If it is not the case, is there any function to execute a command (or run a binary) as root that I can use on the C code?
We met the situation before that we want to execute a root command by a normal user, here is our solution (using setuid/SUID):
assume that:
username: Tom
group: gTom
C program file: my_pro.c
Step 1: Write a C code tool: my_sudo.c
...
int main(int args, char *argv[]) {
if (args < 2)
printf("Usage: my_sudo [cmd] [arg1 arg2 ...]");
// cmd here is the shell cmd that you want execute in "my_pro"
// you can check the shell cmd privilege here
// example: if (argv[1] != "yum") return; we just allow yum execute here
char cmd[MAX_CMD];
int i;
for ( i = 2; i < args; i ++) {
// concatenate the cmd, example: "yum install xxxxx"
strcat(cmd, " ");
strcat(cmd, argv[i]);
}
system(cmd);
}
Step 2: Compile my_sudo.c to get a my_sudo executable file
sudo chown root:gTom my_sudo // user root && gTom group
sudo chmod 4550 my_sudo // use SUID to get root privilege
#you will see my_sudo like this(ls -l)
#-r-sr-x--- 1 root my_sudo 9028 Jul 19 10:09 my_sudo*
#assume we put my_sudo to /usr/sbin/my_sudo
Step 3: In your C code
...
int main() {
...
system("/usr/bin/mysudo yum install xxxxx");
...
}
#gcc && ls -l
#-rwxr--r-- 1 Tom gTom 1895797 Jul 23 13:55 my_pro
Step 4: Execute./my_pro
You can execute the yum install without sudo.
If you are a user on your system that has sudo privileges to run commands as root, just pre-pend sudo to the command.
system("sudo yum install some-package");
If you want anybody to be able to do it, then you have to be administrator on your system, change the owner of the file to be root, and modify the permissions of your executable to run as root. By doing so, you do not need to modify your system() command string with sudo.
chmod +s my_program
chown root my_program
Realize that doing this may open you up to security problems, unless you have proven that your program has no security issues.
The file-system may be such to disallow you from setting the setuid bit on your program. If you need more information along these lines, you should consult SuperUser.
This is one of those bag-o-tricks things to keep in mind. There are security risks, so just be aware of who will use it. In the "system" command you can even execute external scripts...although that opens major security risks because while this binary has to have the permissions re-set every time it's compiled, a script can be changed endlessly and this binary will keep calling it.
#include <stdio.h>
#include <stdlib.h>
//Create as root
//gcc fixmusic.c -o fixmusic
//chmod u+s fixmusic
//now run as non-root user and it should work despite limitations of user
int main(int argc, char *argv[] )
{
setuid(0);
char command[100];
sprintf(command,"/usr/bin/chmod -R a+w /mnt/Local/Music");
system(command);
//This is just optional info if someone cat's the binary
volatile const char comment [] = "INFO: Fixes music permissions";
return 0;
}

Process name from its pid in linux

How to get a process name from his pid ?
For example I execute cat file1.txt, but I want to figure out that cat command and its arguments since its pid in the system. Is there a struct to determine it or something similar? Any idea?
There is not any general way to do this unix. Each OS has different ways to handle it and some are very hard. You mention Linux though. With Linux, the info is in the /proc filesystem. To get the command line for process id 9999, read the file /proc/9999/cmdline.
On linux, you can look in /proc/. Try typing man proc for more information. The contents of /proc/$PID/cmdline will give you the command line that process $PID was run with. There is also /proc/self for examining yourself :)
An alternative (e.g. on Mac OS X) is to use libproc. See libproc.h.
POSIX C does NOT support give a standard API for getting the process name by PID.
In linux, you can get the name by LINUX Proc API: /proc/$PID/cmdline. And the code looks like these:
const char* get_process_name_by_pid(const int pid)
{
char* name = (char*)calloc(1024,sizeof(char));
if(name){
sprintf(name, "/proc/%d/cmdline",pid);
FILE* f = fopen(name,"r");
if(f){
size_t size;
size = fread(name, sizeof(char), 1024, f);
if(size>0){
if('\n'==name[size-1])
name[size-1]='\0';
}
fclose(f);
}
}
return name;
}
To get the process name of a process id say 9000 use this command:
ps -p 9000 -o comm=
While this question has been answered, I'd like to add my 2 cents.
In my case, when process 1111 creates process 22222 via pipe (at least this is what I heard), /proc/2222/cmdline does not give correct process name, but instead gives something like 1111_1. I have to use /proc/2222/comm to get the correct process name.
Use the below command in Linux
ls -l /proc/[pid]/exe
It will give the name of the process/application name
ps --pid <pid> -o comm h :
This command gives executable file name. For example if you run a script name.sh, then the above command gives output as bash
ps --ppid <pid> -o comm h:
This command gives the output as name

How to detect a user logged in through GUI in Linux

I would like to capture the user name logged in through GUI in my program. My program is running as a daemon from root login. If a non root user logs in through GUI my program should be notified.
I am pasting my current program which calls a perl script making use of system call to check who is the current user logged in. I am pasting my perl script too for reference.
#include <X11/Xlib.h>
#include <X11/Xos.h>
#include <X11/Xfuncs.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
int main()
{
char *user;
char buf[1024];
int fd, ret;
fd = open("/tmp/log", O_TRUNC|O_RDWR|O_CREAT);
if (!fd) {
printf("Error opening file\n");
exit(1);
}
chmod("/tmp/log", S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP
| S_IROTH | S_IWOTH | S_IXOTH);
daemon(0, 0);
while (1) {
system("perl /home/curr-usr.pl");
sleep(5);
}
return 0;
}
The perl script which is used to get the current user logged in.
#!/usr/bin/perl
my $result;
$result = `whoami`;
open FH, "+>>", "/tmp/log" or die $!;
print FH "$result ";
close (FH);
In the c program above I am calling the perl script in a while loop every 5 seconds. The perl script makes use of the command "whoami" to get the current user logged in & dumps it into the /tmp/log file.
What I want to achieve is if user1 logs in the perl script should give me the current user to be user1. Instead the perl script gives me root as the current user irrespective of the user I am logged in through GUI as I am running the C program & perl script with root user.
Could anyone please advise me with a mechanism by which the C program could get to know the current user logged in through GUI ?
Any help is greatly appreciated.
You can detect the user using the main display like this:
#!/bin/bash
#Detect the name of the display in use
display=":$(ls /tmp/.X11-unix/* | sed 's#/tmp/.X11-unix/X##' | head -n 1)"
#Detect the user using such display
user=$(who | grep '('$display')' | awk '{print $1}')
#Detect the id of the user
uid=$(id -u $user)
I am using XFCE4 and LXDM. "who" and "users" report only users that are logged on a terminal. GUI logon is not reported as Nominal Animal pointed out (Thanks!). I use "pgrep xfce" to check if XFCE4 is running. Following prints out current xfce-user:
#!/usr/bin/perl
# Get all processes
my #xfce_processes = `pgrep xfce`;
# If processes exist, get user of first process in list.
if(scalar #xfce_processes) {
print `ps -o user h $xfce_processes[0]`;
}
else
{
# No xfce processes.
;
}
As you mentioned your program runs as a daemon. Consequently any process it spawns would be run as the same user as one that started that daemon. The user that logs in via UI (or any other method) would never be the user you can get by calling whoami from your daemon.
Instead what you should do is explicitly notify your daemon of a login event or, if that is not an option, keep a list of all the logged-in sessions currently running on the box and see if new sessions appear - that would be a session of a newly logged-in user.
The programms who and users get their information from the file /var/run/utmp.
The file contains N entries of the size of "struct utmp", defined in <utmp.h>
You are interested in the USER_PROCESS type entries. The host field contains the display.
Note that there are multiple entries for the same display if the user opened some terminal emulations (xterm, konsole...).
You could monitor this file or /var/log/wtmp for a history
struct utmp ut_entry;
FILE *fp = fopen(UTMP_FILE, "r");
if( !fp )
{
printf("Could not open utmp file!");
return;
}
while(fread(&ut_entry, sizeof(struct utmp), 1, fp) == 1)
{
if(ut_entry.ut_type != USER_PROCESS)
continue;
// string entries are not 0 terminated if too long...
// copy user name to make sure it is 0 terminated
char tmpUser[UT_NAMESIZE+1] = {0};
strncpy(tmpUser, ut_entry.ut_user, UT_NAMESIZE);
// do more stuff... read the display from ut_entry.host
}
For more information see the utmp manual page
You probably want to investigate either ConsoleKit or its newer incarnation loginctl.
These tools are specifically designed for managing seats and sessions, while maintaining distinction between local text console, GUI and remote sessions. They are not guaranteed to be present on every X11 machine, but if yours is relatively recent, chances are it uses either one or the other tool.
For anyone else coming here for xfce4, what I had to do was run ps -aux | grep xfce4 then there was a line:
root 2497 0.0 0.3 323052 13408 ? Sl 01:24 0:00 xfce4-session
I run kill -9 2497 and that got rid of it. For me this was a hung instance I wanted to kill from SSH.

linux mkdir function can't authorize full permission

I am testing the mkdir function to create a new directory:
folder = mkdir("./linux", 511);
or
folder = mkdir("./linux", 0777);
or
folder = mkdir("./linux", S_IRWXU | S_IRWXG | S_IRWXO);
As you can see, I try to authorize the full permission to the directory but here's what comes up with ls -l | grep linux:
drwxr-xr-x 2 manuzhang manuzhang 4096 2012-01-04 06:53 linux
why can't I authorize write permission for group and others?
Updates:
weird thing, as you guys told me I tried umask. It works with either umask(S_IWGRP) or umask(S_IWOTH) but fails with umask(S_IWGRP | S_IWOTH), any ideas?
From man 2 mkdir:
The argument mode specifies the permissions to use. It is modified by the process's umask in the usual way: the permissions of the created directory are (mode & ~umask & 0777).
I suggest you look at your umask - it is probably set to 0022. Try a chmod post-mkdir.
Permissions set by system calls like mkdir and open are always masked against the current process's umask. You can change the current umask using the umask() function; make sure to set it back when you're done.
Check the umask function: man 2 umask

How to get input file name from Unix terminal in C?

My program gets executed like:
$./sort 1 < test.txt
sort is the program name
1 is the argument (argv[1])
and test.txt is the file I am inputting from
Is it possible to extract the name file from this? if so how?
The problem is I already wrote my whole program as if I could extract the name from the input line, so I need to be able to pass it into arguments.
Any help is appreciated,
Thanks!
You can't. The shell opens (open(2)) that file and sets up the redirect (most likely using dup2).
The only possible way would be for the shell to explicitly export the information in an environment variable that you could read via getenv.
But it doesn't always make sense. For example, what file name would you expect from
$ echo "This is the end" | ./sort 1
Though this can't be done portably, it's possible on Linux by calling readlink on /proc/self/fd/0 (or /proc/some_pid/fd/0).
eg, running:
echo $(readlink /proc/self/fd/0 < /dev/null)
outputs:
/dev/null
No you can't: the shell sends the content of test.txt to the standard input of your program.
Look at this:
sort << _EOF
3
1
2
_EOF
The < > | operators are processed by the shell, they alter standard input,output,error of the programs in the cmd line.
If you happen to run Solaris, you could parse pfiles output to get the file associated, if any, with stdin.
$ /usr/bin/sleep 3600 < /tmp/foo &
[1] 8430
$ pfiles 8430
8430: /usr/bin/sleep 3600
Current rlimit: 65536 file descriptors
0: S_IFREG mode:0600 dev:299,2 ino:36867886 uid:12345 gid:67890 size=123
O_RDONLY|O_LARGEFILE
/tmp/foo
1: S_IFCHR mode:0600 dev:295,0 ino:12569206 uid:12345 gid:67890 rdev:24,2
...
On most Unix platforms, you will also get the same information from lsof -p if this freeware is installed.

Resources