Index: trunk/tools/tsutils/watcherd/watcherd.c |
— | — | @@ -44,7 +44,6 @@ |
45 | 45 | static void read_configuration(void); |
46 | 46 | static int run_check(void); |
47 | 47 | static void notify_query(char const *id, char const *user, char const *db, char const *query, int t); |
48 | | -static int seen_query(int64_t); |
49 | 48 | static void clean_seen_queries(void); |
50 | 49 | static void add_seen_query(int64_t); |
51 | 50 | static int has_warned(int64_t); |
— | — | @@ -345,17 +344,6 @@ |
346 | 345 | querylist.q_next = q; |
347 | 346 | } |
348 | 347 | |
349 | | -static int |
350 | | -seen_query(qid) |
351 | | - int64_t qid; |
352 | | -{ |
353 | | -query *q; |
354 | | - for (q = querylist.q_next; q; q = q->q_next) |
355 | | - if (q->q_id == qid) |
356 | | - return 1; |
357 | | - return 0; |
358 | | -} |
359 | | - |
360 | 348 | static void |
361 | 349 | set_warned(qid) |
362 | 350 | int64_t qid; |
Index: trunk/tools/tsutils/pwtool/pwtool.c |
— | — | @@ -0,0 +1,254 @@ |
| 2 | +/* Copyright (c) 2007 River Tarnell <river@attenuate.org>. */ |
| 3 | +/* |
| 4 | + * Permission is granted to anyone to use this software for any purpose, |
| 5 | + * including commercial applications, and to alter it and redistribute it |
| 6 | + * freely. This software is provided 'as-is', without any express or implied |
| 7 | + * warranty. |
| 8 | + */ |
| 9 | + |
| 10 | +/* $Id$ */ |
| 11 | + |
| 12 | +/* |
| 13 | + * pwtool: allow users to edit their shell and realname. |
| 14 | + */ |
| 15 | + |
| 16 | +#define _GNU_SOURCE |
| 17 | + |
| 18 | +#include <sys/types.h> |
| 19 | +#include <sys/stat.h> |
| 20 | +#include <sys/capability.h> |
| 21 | +#include <stdio.h> |
| 22 | +#include <string.h> |
| 23 | +#include <errno.h> |
| 24 | +#include <pwd.h> |
| 25 | +#include <fcntl.h> |
| 26 | +#include <unistd.h> |
| 27 | +#include <ctype.h> |
| 28 | +#include <stdlib.h> |
| 29 | +#include <signal.h> |
| 30 | + |
| 31 | +#define PASSWD "/etc/passwd" |
| 32 | +#define TMPFILE "/etc/passwd.tmp" |
| 33 | + |
| 34 | +static int isvalidshell(char const *); |
| 35 | +static int isvalidgecos(char const *); |
| 36 | +static void cleanup(void); |
| 37 | + |
| 38 | +static int outfd = -1; |
| 39 | + |
| 40 | +cap_t caps; |
| 41 | + |
| 42 | +int |
| 43 | +main(argc, argv) |
| 44 | + int argc; |
| 45 | + char *argv[]; |
| 46 | +{ |
| 47 | +int infd; |
| 48 | +FILE *inf, *outf; |
| 49 | +struct stat st; |
| 50 | +struct passwd *pwd; |
| 51 | +uid_t me; |
| 52 | +int c; |
| 53 | +char *newshell = NULL, *newgecos = NULL; |
| 54 | +cap_value_t wantcaps[] = { CAP_CHOWN }; |
| 55 | + |
| 56 | + (void) umask(022); |
| 57 | + |
| 58 | + if ((caps = cap_init()) == NULL) { |
| 59 | + (void) fprintf(stderr, "cannot initialise capabilities: %s\n", |
| 60 | + strerror(errno)); |
| 61 | + return 1; |
| 62 | + } |
| 63 | + |
| 64 | + /* |
| 65 | + * Drop all capabilities from our effective and inheritable sets. |
| 66 | + * Leave CAP_CHOWN in permitted because we need it for fchown later. |
| 67 | + */ |
| 68 | + cap_clear(caps); |
| 69 | + cap_set_flag(caps, CAP_PERMITTED, sizeof(wantcaps) / sizeof(*wantcaps), wantcaps, CAP_SET); |
| 70 | + |
| 71 | + if (cap_set_proc(caps) == -1) { |
| 72 | + (void) fprintf(stderr, "cannot set capabilities: %s\n", |
| 73 | + strerror(errno)); |
| 74 | + return 1; |
| 75 | + } |
| 76 | + |
| 77 | + while ((c = getopt(argc, argv, "s:g:h")) != -1) { |
| 78 | + switch (c) { |
| 79 | + case 's': |
| 80 | + newshell = optarg; |
| 81 | + break; |
| 82 | + |
| 83 | + case 'g': |
| 84 | + newgecos = optarg; |
| 85 | + break; |
| 86 | + |
| 87 | + case 'h': |
| 88 | + (void) fprintf(stderr, "usage: pwtool [-h] [-s shell] [-g gecos]\n"); |
| 89 | + return 0; |
| 90 | + |
| 91 | + default: |
| 92 | + return 1; |
| 93 | + } |
| 94 | + } |
| 95 | + argc -= optind; |
| 96 | + argv += optind; |
| 97 | + |
| 98 | + if (argc != 0) { |
| 99 | + (void) fprintf(stderr, "usage: pwtool [-s shell] [-g gecos]\n"); |
| 100 | + return 1; |
| 101 | + } |
| 102 | + |
| 103 | + if (!newgecos && !newshell) |
| 104 | + return 0; |
| 105 | + |
| 106 | + |
| 107 | + if (newshell && !isvalidshell(newshell)) { |
| 108 | + (void) fprintf(stderr, "pwtool: \"%s\" is not a valid login shell\n", |
| 109 | + newshell); |
| 110 | + return 1; |
| 111 | + } |
| 112 | + |
| 113 | + if (newgecos && !isvalidgecos(newgecos)) { |
| 114 | + (void) fprintf(stderr, "pwtool: GECOS may only contain ASCII alphanumerics and whitespace\n"); |
| 115 | + return 1; |
| 116 | + } |
| 117 | + |
| 118 | + me = getuid(); |
| 119 | + |
| 120 | + if ((infd = open(PASSWD, O_RDONLY)) == -1) { |
| 121 | + (void) fprintf(stderr, "pwtool: cannot open %s: %s\n", PASSWD, strerror(errno)); |
| 122 | + return 1; |
| 123 | + } |
| 124 | + |
| 125 | + if ((inf = fdopen(infd, "r")) == NULL) { |
| 126 | + (void) fprintf(stderr, "pwtool: cannot open %s: %s\n", PASSWD, strerror(errno)); |
| 127 | + return 1; |
| 128 | + } |
| 129 | + |
| 130 | + if (fstat(infd, &st) == -1) { |
| 131 | + (void) fprintf(stderr, "pwtool: cannot fstat %s: %s\n", PASSWD, strerror(errno)); |
| 132 | + return 1; |
| 133 | + } |
| 134 | + |
| 135 | + atexit(cleanup); |
| 136 | + signal(SIGINT, SIG_IGN); |
| 137 | + signal(SIGTERM, SIG_IGN); |
| 138 | + signal(SIGQUIT, SIG_IGN); |
| 139 | + |
| 140 | + if ((outfd = open(TMPFILE, O_WRONLY | O_EXCL | O_CREAT, st.st_mode)) == -1) { |
| 141 | + (void) fprintf(stderr, "pwtool: cannot open %s: %s\n", TMPFILE, strerror(errno)); |
| 142 | + return 1; |
| 143 | + } |
| 144 | + |
| 145 | + /* |
| 146 | + * CAP_CHOWN is needed to change the owner of the tmp file correctly. |
| 147 | + */ |
| 148 | + cap_set_flag(caps, CAP_EFFECTIVE, sizeof(wantcaps) / sizeof(*wantcaps), wantcaps, CAP_SET); |
| 149 | + |
| 150 | + if (cap_set_proc(caps) == -1) { |
| 151 | + (void) fprintf(stderr, "cannot set capabilities: %s\n", |
| 152 | + strerror(errno)); |
| 153 | + return 1; |
| 154 | + } |
| 155 | + |
| 156 | + if (fchown(outfd, st.st_uid, st.st_gid) == -1) { |
| 157 | + (void) fprintf(stderr, "pwtool: cannot chown %s: %s\n", TMPFILE, strerror(errno)); |
| 158 | + return 1; |
| 159 | + } |
| 160 | + |
| 161 | + /* |
| 162 | + * Now we can drop CAP_CHOWN from both permitted and effective. |
| 163 | + */ |
| 164 | + cap_set_flag(caps, CAP_PERMITTED, sizeof(wantcaps) / sizeof(*wantcaps), wantcaps, CAP_CLEAR); |
| 165 | + cap_set_flag(caps, CAP_EFFECTIVE, sizeof(wantcaps) / sizeof(*wantcaps), wantcaps, CAP_CLEAR); |
| 166 | + |
| 167 | + if (cap_set_proc(caps) == -1) { |
| 168 | + (void) fprintf(stderr, "cannot set capabilities: %s\n", |
| 169 | + strerror(errno)); |
| 170 | + return 1; |
| 171 | + } |
| 172 | + |
| 173 | + if ((outf = fdopen(outfd, "w")) == NULL) { |
| 174 | + (void) fprintf(stderr, "pwtool: cannot open %s: %s\n", TMPFILE, strerror(errno)); |
| 175 | + return 1; |
| 176 | + } |
| 177 | + |
| 178 | + while ((pwd = fgetpwent(inf)) != NULL) { |
| 179 | + if (pwd->pw_uid == me) { |
| 180 | + if (newgecos) |
| 181 | + pwd->pw_gecos = newgecos; |
| 182 | + if (newshell) |
| 183 | + pwd->pw_shell = newshell; |
| 184 | + } |
| 185 | + |
| 186 | + if (putpwent(pwd, outf) == -1) { |
| 187 | + (void) fprintf(stderr, "pwtool: error writing to %s: %s", |
| 188 | + TMPFILE, strerror(errno)); |
| 189 | + return 1; |
| 190 | + } |
| 191 | + } |
| 192 | + |
| 193 | + if (ferror(inf)) { |
| 194 | + (void) fprintf(stderr, "pwtool: error reading %s: %s\n", |
| 195 | + PASSWD, strerror(errno)); |
| 196 | + return 1; |
| 197 | + } |
| 198 | + |
| 199 | + if (fsync(fileno(outf)) == -1) { |
| 200 | + (void) fprintf(stderr, "pwtool: error syncing %s: %s\n", |
| 201 | + TMPFILE, strerror(errno)); |
| 202 | + return 1; |
| 203 | + } |
| 204 | + |
| 205 | + if (fclose(outf) == EOF) { |
| 206 | + (void) fprintf(stderr, "pwtool: error closing %s: %s\n", |
| 207 | + TMPFILE, strerror(errno)); |
| 208 | + outfd = -1; |
| 209 | + return 1; |
| 210 | + } |
| 211 | + |
| 212 | + outfd = -1; |
| 213 | + fclose(inf); |
| 214 | + |
| 215 | + if (rename(TMPFILE, PASSWD) == -1) { |
| 216 | + (void) fprintf(stderr, "pwtool: cannot rename %s to %s: %s\n", |
| 217 | + TMPFILE, PASSWD, strerror(errno)); |
| 218 | + return 1; |
| 219 | + } |
| 220 | + |
| 221 | + return 0; |
| 222 | +} |
| 223 | + |
| 224 | +static int |
| 225 | +isvalidshell(sh) |
| 226 | + char const *sh; |
| 227 | +{ |
| 228 | +char const *s; |
| 229 | + setusershell(); |
| 230 | + while ((s = getusershell()) != NULL) |
| 231 | + if (!strcmp(s, sh)) |
| 232 | + return 1; |
| 233 | + return 0; |
| 234 | +} |
| 235 | + |
| 236 | +static int |
| 237 | +isvalidgecos(ge) |
| 238 | + char const *ge; |
| 239 | +{ |
| 240 | + while (*ge) { |
| 241 | + if (!isascii(*ge) || !(isalnum(*ge) || isblank(*ge))) |
| 242 | + return 0; |
| 243 | + |
| 244 | + ge++; |
| 245 | + } |
| 246 | + |
| 247 | + return 1; |
| 248 | +} |
| 249 | + |
| 250 | +static void |
| 251 | +cleanup() |
| 252 | +{ |
| 253 | + if (outfd != -1) |
| 254 | + (void) unlink(TMPFILE); |
| 255 | +} |
Index: trunk/tools/tsutils/pwtool/Makefile |
— | — | @@ -0,0 +1,8 @@ |
| 2 | +PROG = pwtool |
| 3 | +BINMODE = 4755 |
| 4 | + |
| 5 | +SRCS = pwtool.c |
| 6 | +OBJS = $(SRCS:.c=.o) |
| 7 | +LIBS = -lcap |
| 8 | + |
| 9 | +include ../mk/prog.mk |
Index: trunk/tools/tsutils/config.mk |
— | — | @@ -1,7 +1,7 @@ |
2 | | -LINT = lint |
3 | | -CC = suncc |
4 | | -CFLAGS = -m64 -O -g -errwarn -xc99=none |
5 | | -LINTFLAGS = -axsm -u -errtags=yes -s -Xc99=%none -Xarch=amd64 -errsecurity=core -erroff=E_INCONS_ARG_DECL2 |
| 2 | +#LINT = lint |
| 3 | +#CC = suncc |
| 4 | +#CFLAGS = -m64 -O -g -errwarn -xc99=all |
| 5 | +#LINTFLAGS = -axsm -u -errtags=yes -s -Xc99=%none -Xarch=amd64 -errsecurity=core -erroff=E_INCONS_ARG_DECL2 |
6 | 6 | |
7 | | -# CC = gcc |
8 | | -# CFLAGS = -W -Wall -Werror |
| 7 | +CC = gcc |
| 8 | +CFLAGS = -W -Wall -Werror |
Index: trunk/tools/tsutils/Makefile |
— | — | @@ -1,4 +1,4 @@ |
2 | | -SUBDIRS = libtsutils watcherd acctexp listlogins lsexp whodo |
| 2 | +SUBDIRS = libtsutils watcherd acctexp listlogins lsexp whodo whinequota pwtool |
3 | 3 | MAKEFLAGS = --no-print-directory |
4 | 4 | |
5 | 5 | all clean depend install lint: |