25RCSID(
"$Id: 60be089e8ec8d8d8c18a8d892ca75f6a05d867ee $")
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>
42#define INFO(fmt, ...) fprintf(stdout, fmt "\n", ## __VA_ARGS__)
67 fprintf(stderr,
"usage: radlock <file> [lock|trylock|unlock|remove|info|perm]\n");
68 fprintf(stderr,
" -u <uid> Desired user.\n");
69 fprintf(stderr,
" -g <gid> Desired group.\n");
70 fprintf(stderr,
" -m <perm> Octal permissions string.\n");
71 fprintf(stderr,
" -h This help text.\n");
72 fprintf(stderr,
"\n");
73 fprintf(stderr,
"Simple utility to query the locking state of a config file\n");
77#define EXIT_WITH_FAILURE exit(EXIT_FAILURE)
78#define EXIT_WITH_SUCCESS exit(EXIT_SUCCESS)
84int main(
int argc,
char *argv[])
90 uid_t uid = geteuid();
92 gid_t gid = getegid();
94 long mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
95 bool mode_set =
false;
109 talloc_set_log_stderr();
111 while ((c = getopt(argc, argv,
"u:g:m:h")) != -1)
switch (c) {
129 mode = strtol(optarg, &end, 0);
130 if (*end || (end == optarg)) {
145 fr_perror(
"radlock - Need file to operate on");
150 fr_perror(
"radlock - Need action, must be one of (lock|trylock|unlock|remove|info|perm)");
157 fr_perror(
"radlock - Action must be one of (lock|trylock|unlock|remove|info|perm), got %s", argv[1]);
161 if ((action ==
RADLOCK_PERM) && !uid_set && !gid_set && !mode_set) {
162 fr_perror(
"radlock - At least one of -u, -g, -m must be specified");
188 fr_perror(
"radlock - Can't lock \"%s\" already held by PID %u",
file, pid);
235 struct semid_ds info;
237 unsigned int perm = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
242 char const *uid_str, *gid_str, *cuid_str, *cgid_str;
251 if (semctl(sem_id, 0, IPC_STAT, &info) < 0) {
262 if ((ret < 0) && (errno == ESRCH)) dead =
true;
265 if (!uid_str) uid_str =
"";
268 if (!gid_str) gid_str =
"";
271 if (!cuid_str) cuid_str =
"";
274 if (!cgid_str) cgid_str =
"";
276 value = semctl(sem_id, 0, GETVAL);
278 INFO(
"Locking information for \"%s\"",
file);
279 INFO(
"\tsemid : %u", sem_id);
281 INFO(
"\tValue : %u (%s)",
value,
value > 0 ?
"locked" :
"unlocked");
282 INFO(
"Last Modified:");
283 INFO(
"\tPID : %u (%s)", pid, dead ?
"dead" :
"alive");
284 INFO(
"\tUser : %s (%u)", uid_str, info.sem_perm.uid);
285 INFO(
"\tGroup : %s (%u)", gid_str, info.sem_perm.gid);
289 INFO(
"\tUser : %s (%u)", cuid_str, info.sem_perm.cuid);
290 INFO(
"\tGroup : %s (%u)", cgid_str, info.sem_perm.cgid);
298 struct semid_ds info;
306 if (semctl(sem_id, 0, IPC_STAT, &info) < 0) {
307 fr_perror(
"radlock - Failed getting lock info for \"%s\": %s",
312 if (uid_set) info.sem_perm.uid = uid;
313 if (gid_set) info.sem_perm.gid = gid;
314 if (mode_set) info.sem_perm.mode = mode;
316 if (semctl(sem_id, 0, IPC_SET, &info) < 0) {
317 fr_perror(
"radlock - Failed setting lock permissions for \"%s\": %s",
static TALLOC_CTX * autofree
#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.
static NEVER_RETURNS void usage(void)
char * fr_perm_uid_to_str(TALLOC_CTX *ctx, uid_t uid)
Print uid to a string.
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.
int fr_perm_gid_from_str(TALLOC_CTX *ctx, gid_t *out, char const *name)
Resolve a group name to a GID.
char * fr_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Special version of asprintf which implements custom format specifiers.
@ 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)