/***********************************************************************
* chshm: A tool to change shared memory ownership and permission
*
* Author: Curu Wong
* Date: 2013-04-18
**********************************************************************
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
void print_usage(char *prog_name){
fprintf(stderr, "Usage: %s [Options] shmid ...\n", prog_name);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -u|--user change owner to \n");
fprintf(stderr, " -g|--group change group to \n");
fprintf(stderr, " -m|--mode change mode to in octal\n");
fprintf(stderr, "\neg:\n");
fprintf(stderr, " %s -u nobody -m 0660 65535 \n", prog_name);
fprintf(stderr, " This will change shm id 65535's owner to nobody, mode to 0660\n");
}
int chshm(int shmid, uid_t uid, gid_t gid, int mode)
{
int ret;
struct shmid_ds buf;
//save current stat
ret = shmctl(shmid, IPC_STAT, &buf);
if(ret == -1 ){
perror("error get shared memory info");
return -1;
}
// if uid or gid is -1, it will not be changed
if( uid != -1 ){
buf.shm_perm.uid = uid;
}
if( gid != -1 ){
buf.shm_perm.gid = gid;
}
if(mode != -1){
buf.shm_perm.mode = mode;
}
ret = shmctl(shmid, IPC_SET, &buf);
if( ret == -1){
perror("error: unable to change owner");
return -1;
}
return 0;
}
int main(int argc, char *argv[])
{
uid_t uid = -1;
gid_t gid = -1;
mode_t mode = -1;
int shmid;
struct group *grent;
struct passwd *pwent;
int c;
static int help_flag = 0;
while (1){
static struct option long_options[] = {
{"help", no_argument, &help_flag, 1},
{"user", required_argument, 0, 'u'},
{"group", required_argument, 0, 'g'},
{"mode", required_argument, 0, 'm'},
{0, 0, 0, 0 }
};
int option_index = 0;
c = getopt_long (argc, argv, "hu:g:m:",
long_options, &option_index);
if (c == -1){
break;
}
switch(c) {
case 'u':
errno = 0;
pwent = getpwnam(optarg);
if(pwent != NULL){
uid= pwent->pw_uid;
}else{
if(errno){
perror("getpwnam");
}else{
fprintf(stderr, "no such user '%s'\n", optarg);
}
exit(EXIT_FAILURE);
}
break;
case 'g':
errno = 0;
grent = getgrnam(optarg);
if(grent != NULL){
gid= grent->gr_gid;
}else{
if(errno){
perror("getgrnam");
}else{
fprintf(stderr, "no such group '%s'\n", optarg);
}
exit(EXIT_FAILURE);
}
break;
case 'm':
mode = strtoul(optarg, NULL, 8);
break;
case 'h':
help_flag = 1;
break;
default:
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
}
if(optind >= argc || help_flag ){
print_usage(argv[0]);
exit(0);
}
while(optind < argc){
shmid = strtoul(argv[optind], NULL, 10);
if (chshm(shmid, uid, gid, mode) == -1 ){
exit(EXIT_FAILURE);
}
optind++;
}
return 0;
}