25 RCSID(
"$Id: a34f01ab7d1045baa8c09d7e8d9fb2809ecd1e5b $")
27 #include <freeradius-devel/autoconf.h>
28 #include <freeradius-devel/util/perm.h>
29 #include <freeradius-devel/util/sem.h>
30 #include <freeradius-devel/util/value.h>
31 #include <freeradius-devel/util/syserror.h>
32 #include <freeradius-devel/util/strerror.h>
46 #define INFO(fmt, ...) fprintf(stdout, fmt "\n", ## __VA_ARGS__)
71 fprintf(stderr,
"usage: radlock <file> [lock|trylock|unlock|remove|info|perm]\n");
72 fprintf(stderr,
" -u <uid> Desired user.\n");
73 fprintf(stderr,
" -g <gid> Desired group.\n");
74 fprintf(stderr,
" -m <perm> Octal permissions string.\n");
75 fprintf(stderr,
" -h This help text.\n");
76 fprintf(stderr,
"\n");
77 fprintf(stderr,
"Simple utility to query the locking state of a config file\n");
81 #define EXIT_WITH_FAILURE exit(EXIT_FAILURE)
82 #define EXIT_WITH_SUCCESS exit(EXIT_SUCCESS)
88 int main(
int argc,
char *argv[])
93 uid_t uid = geteuid();
95 gid_t gid = getegid();
97 long mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
98 bool mode_set =
false;
112 talloc_set_log_stderr();
114 while ((c = getopt(argc, argv,
"u:g:m:h")) != -1)
switch (c) {
132 mode = strtol(optarg, NULL, 0);
133 if (errno == EINVAL) {
148 fr_perror(
"radlock - Need file to operate on");
153 fr_perror(
"radlock - Need action, must be one of (lock|trylock|unlock|remove|info|perm)");
160 fr_perror(
"radlock - Action must be one of (lock|trylock|unlock|remove|info|perm), got %s", argv[1]);
165 fr_perror(
"radlock - At least one of -u, -g, -m must be specified");
191 fr_perror(
"radlock - Can't lock \"%s\" already held by PID %u",
file, pid);
238 struct semid_ds info;
240 unsigned int perm = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
245 char const *uid_str, *gid_str, *cuid_str, *cgid_str;
254 if (semctl(sem_id, 0, IPC_STAT, &info) < 0) {
264 ret = kill(sem_id, 0);
265 if ((ret < 0) && (errno == ESRCH)) dead =
true;
268 if (!uid_str) uid_str =
"";
271 if (!gid_str) gid_str =
"";
274 if (!cuid_str) cuid_str =
"";
277 if (!cgid_str) cgid_str =
"";
279 value = semctl(sem_id, 0, GETVAL);
281 INFO(
"Locking information for \"%s\"",
file);
282 INFO(
"\tsemid : %u", sem_id);
284 INFO(
"\tValue : %u (%s)",
value,
value > 0 ?
"locked" :
"unlocked");
285 INFO(
"Last Modified:");
286 INFO(
"\tPID : %u (%s)", pid, dead ?
"dead" :
"alive");
287 INFO(
"\tUser : %s (%u)", uid_str, info.sem_perm.uid);
288 INFO(
"\tGroup : %s (%u)", gid_str, info.sem_perm.gid);
292 INFO(
"\tUser : %s (%u)", cuid_str, info.sem_perm.cuid);
293 INFO(
"\tGroup : %s (%u)", cgid_str, info.sem_perm.cgid);
301 struct semid_ds info;
309 if (semctl(sem_id, 0, IPC_STAT, &info) < 0) {
310 fr_perror(
"radlock - Failed getting lock info for \"%s\": %s",
315 if (uid_set) info.sem_perm.uid = uid;
316 if (gid_set) info.sem_perm.gid = gid;
317 if (mode_set) info.sem_perm.mode = mode;
319 if (semctl(sem_id, 0, IPC_SET, &info) < 0) {
320 fr_perror(
"radlock - Failed setting lock permissions for \"%s\": %s",
#define NEVER_RETURNS
Should be placed before the function return type.
#define L(_str)
Helper for initialising arrays of string literals.
int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
#define fr_exit(_x)
Exit, producing a log message in debug builds.
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
char const * fr_perm_mode_to_str(char out[static 10], mode_t mode)
Convert mode_t into humanly readable permissions flags.
char * fr_perm_gid_to_str(TALLOC_CTX *ctx, uid_t gid)
Print gid to a string.
int fr_perm_uid_from_str(TALLOC_CTX *ctx, uid_t *out, char const *name)
Resolve a user name to a GID.
char * fr_perm_uid_to_str(TALLOC_CTX *ctx, uid_t uid)
Print uid to a string.
char * fr_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Special version of asprintf which implements custom format specifiers.
static TALLOC_CTX * autofree
static NEVER_RETURNS void usage(int ret)
@ RADLOCK_TRYLOCK
Try and lock the semaphore and return if we can't.
@ RADLOCK_UNLOCK
Unlock the semaphore.
@ RADLOCK_PERM
Modify permissions for a given semaphore.
@ RADLOCK_LOCK
Acquire the semaphore if it's at 0.
@ RADLOCK_REMOVE
Remove the semaphore.
@ RADLOCK_INFO
Information about the semaphore.
int main(int argc, char *argv[])
static fr_table_num_sorted_t const radlock_action_table[]
#define EXIT_WITH_SUCCESS
#define EXIT_WITH_FAILURE
static size_t radlock_action_table_len
int fr_sem_post(int sem_id, char const *file, bool undo_on_exit)
Decrement the semaphore by 1.
int fr_sem_wait(int sem_id, char const *file, bool undo_on_exit, bool nonblock)
Wait for a semaphore to reach 0, then increment it by 1.
int fr_sem_close(int sem_id, char const *file)
Remove the semaphore, this helps with permissions issues.
int fr_sem_pid(pid_t *pid, int sem_id)
Return the PID of the process that last operated on the semaphore.
int fr_sem_get(char const *file, int proj_id, uid_t uid, gid_t gid, bool check_perm, bool must_exist)
Returns a semid for the semaphore associated with the file.
static char buff[sizeof("18446744073709551615")+3]
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
An element in a lexicographically sorted array of name to num mappings.
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
static fr_time_t fr_time_from_sec(time_t when)
Convert a time_t (wallclock time) to a fr_time_t (internal time)
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
#define RADIUSD_MAGIC_NUMBER
#define fr_box_time(_val)