misc.c (c082b52c720814bcffecc3901ef80b0c3b4cfe3c) misc.c (84f33dea627930e57209583fc83ffb3202babc0a)
1/* Copyright 1988,1990,1993,1994 by Paul Vixie
2 * All rights reserved
3 *
4 * Distribute freely, except: don't remove my name from the source or
5 * documentation (don't take credit for my work), mark your changes (don't
6 * get me blamed for your possible bugs), don't alter or remove this
7 * notice. May be sold if buildable source is provided to buyer. No
8 * warrantee of any kind, express or implied, is included with this
9 * software; use at your own risk, responsibility for damages (if any) to
10 * anyone resulting from the use of this software rests entirely with the
11 * user.
12 *
13 * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
14 * I'll try to keep a version up to date. I can be reached as follows:
15 * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul
16 */
17
18#if !defined(lint) && !defined(LINT)
1/* Copyright 1988,1990,1993,1994 by Paul Vixie
2 * All rights reserved
3 *
4 * Distribute freely, except: don't remove my name from the source or
5 * documentation (don't take credit for my work), mark your changes (don't
6 * get me blamed for your possible bugs), don't alter or remove this
7 * notice. May be sold if buildable source is provided to buyer. No
8 * warrantee of any kind, express or implied, is included with this
9 * software; use at your own risk, responsibility for damages (if any) to
10 * anyone resulting from the use of this software rests entirely with the
11 * user.
12 *
13 * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
14 * I'll try to keep a version up to date. I can be reached as follows:
15 * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul
16 */
17
18#if !defined(lint) && !defined(LINT)
19static const char rcsid[] =
20 "$FreeBSD$";
19static char rcsid[] = "$Id: misc.c,v 2.9 1994/01/15 20:43:43 vixie Exp $";
21#endif
22
23/* vix 26jan87 [RCS has the rest of the log]
24 * vix 30dec86 [written]
25 */
26
27
28#include "cron.h"
29#if SYS_TIME_H
30# include <sys/time.h>
31#else
32# include <time.h>
33#endif
34#include <sys/file.h>
35#include <sys/stat.h>
20#endif
21
22/* vix 26jan87 [RCS has the rest of the log]
23 * vix 30dec86 [written]
24 */
25
26
27#include "cron.h"
28#if SYS_TIME_H
29# include <sys/time.h>
30#else
31# include <time.h>
32#endif
33#include <sys/file.h>
34#include <sys/stat.h>
36#include <err.h>
37#include <errno.h>
38#include <string.h>
39#include <fcntl.h>
40#if defined(SYSLOG)
41# include <syslog.h>
42#endif
43
44

--- 126 unchanged lines hidden (view full) ---

171#endif /* DEBUGGING */
172}
173
174
175void
176set_cron_uid()
177{
178#if defined(BSD) || defined(POSIX)
35#include <errno.h>
36#include <string.h>
37#include <fcntl.h>
38#if defined(SYSLOG)
39# include <syslog.h>
40#endif
41
42

--- 126 unchanged lines hidden (view full) ---

169#endif /* DEBUGGING */
170}
171
172
173void
174set_cron_uid()
175{
176#if defined(BSD) || defined(POSIX)
179 if (seteuid(ROOT_UID) < OK)
180 err(ERROR_EXIT, "seteuid");
177 if (seteuid(ROOT_UID) < OK) {
178 perror("seteuid");
179 exit(ERROR_EXIT);
180 }
181#else
181#else
182 if (setuid(ROOT_UID) < OK)
183 err(ERROR_EXIT, "setuid");
182 if (setuid(ROOT_UID) < OK) {
183 perror("setuid");
184 exit(ERROR_EXIT);
185 }
184#endif
185}
186
187
188void
189set_cron_cwd()
190{
191 struct stat sb;
192
193 /* first check for CRONDIR ("/var/cron" or some such)
194 */
195 if (stat(CRONDIR, &sb) < OK && errno == ENOENT) {
186#endif
187}
188
189
190void
191set_cron_cwd()
192{
193 struct stat sb;
194
195 /* first check for CRONDIR ("/var/cron" or some such)
196 */
197 if (stat(CRONDIR, &sb) < OK && errno == ENOENT) {
196 warn("%s", CRONDIR);
198 perror(CRONDIR);
197 if (OK == mkdir(CRONDIR, 0700)) {
199 if (OK == mkdir(CRONDIR, 0700)) {
198 warnx("%s: created", CRONDIR);
200 fprintf(stderr, "%s: created\n", CRONDIR);
199 stat(CRONDIR, &sb);
200 } else {
201 stat(CRONDIR, &sb);
202 } else {
201 err(ERROR_EXIT, "%s: mkdir", CRONDIR);
203 fprintf(stderr, "%s: ", CRONDIR);
204 perror("mkdir");
205 exit(ERROR_EXIT);
202 }
203 }
206 }
207 }
204 if (!(sb.st_mode & S_IFDIR))
205 err(ERROR_EXIT, "'%s' is not a directory, bailing out", CRONDIR);
206 if (chdir(CRONDIR) < OK)
207 err(ERROR_EXIT, "cannot chdir(%s), bailing out", CRONDIR);
208 if (!(sb.st_mode & S_IFDIR)) {
209 fprintf(stderr, "'%s' is not a directory, bailing out.\n",
210 CRONDIR);
211 exit(ERROR_EXIT);
212 }
213 if (chdir(CRONDIR) < OK) {
214 fprintf(stderr, "cannot chdir(%s), bailing out.\n", CRONDIR);
215 perror(CRONDIR);
216 exit(ERROR_EXIT);
217 }
208
209 /* CRONDIR okay (now==CWD), now look at SPOOL_DIR ("tabs" or some such)
210 */
211 if (stat(SPOOL_DIR, &sb) < OK && errno == ENOENT) {
218
219 /* CRONDIR okay (now==CWD), now look at SPOOL_DIR ("tabs" or some such)
220 */
221 if (stat(SPOOL_DIR, &sb) < OK && errno == ENOENT) {
212 warn("%s", SPOOL_DIR);
222 perror(SPOOL_DIR);
213 if (OK == mkdir(SPOOL_DIR, 0700)) {
223 if (OK == mkdir(SPOOL_DIR, 0700)) {
214 warnx("%s: created", SPOOL_DIR);
224 fprintf(stderr, "%s: created\n", SPOOL_DIR);
215 stat(SPOOL_DIR, &sb);
216 } else {
225 stat(SPOOL_DIR, &sb);
226 } else {
217 err(ERROR_EXIT, "%s: mkdir", SPOOL_DIR);
227 fprintf(stderr, "%s: ", SPOOL_DIR);
228 perror("mkdir");
229 exit(ERROR_EXIT);
218 }
219 }
230 }
231 }
220 if (!(sb.st_mode & S_IFDIR))
221 err(ERROR_EXIT, "'%s' is not a directory, bailing out", SPOOL_DIR);
232 if (!(sb.st_mode & S_IFDIR)) {
233 fprintf(stderr, "'%s' is not a directory, bailing out.\n",
234 SPOOL_DIR);
235 exit(ERROR_EXIT);
236 }
222}
223
224
237}
238
239
240/* acquire_daemonlock() - write our PID into /etc/cron.pid, unless
241 * another daemon is already running, which we detect here.
242 *
243 * note: main() calls us twice; once before forking, once after.
244 * we maintain static storage of the file pointer so that we
245 * can rewrite our PID into the PIDFILE after the fork.
246 *
247 * it would be great if fflush() disassociated the file buffer.
248 */
249void
250acquire_daemonlock(closeflag)
251 int closeflag;
252{
253 static FILE *fp = NULL;
254
255 if (closeflag && fp) {
256 fclose(fp);
257 fp = NULL;
258 return;
259 }
260
261 if (!fp) {
262 char pidfile[MAX_FNAME];
263 char buf[MAX_TEMPSTR];
264 int fd, otherpid;
265
266 (void) sprintf(pidfile, PIDFILE, PIDDIR);
267 if ((-1 == (fd = open(pidfile, O_RDWR|O_CREAT, 0644)))
268 || (NULL == (fp = fdopen(fd, "r+")))
269 ) {
270 sprintf(buf, "can't open or create %s: %s",
271 pidfile, strerror(errno));
272 fprintf(stderr, "%s: %s\n", ProgramName, buf);
273 log_it("CRON", getpid(), "DEATH", buf);
274 exit(ERROR_EXIT);
275 }
276
277 if (flock(fd, LOCK_EX|LOCK_NB) < OK) {
278 int save_errno = errno;
279
280 fscanf(fp, "%d", &otherpid);
281 sprintf(buf, "can't lock %s, otherpid may be %d: %s",
282 pidfile, otherpid, strerror(save_errno));
283 fprintf(stderr, "%s: %s\n", ProgramName, buf);
284 log_it("CRON", getpid(), "DEATH", buf);
285 exit(ERROR_EXIT);
286 }
287
288 (void) fcntl(fd, F_SETFD, 1);
289 }
290
291 rewind(fp);
292 fprintf(fp, "%d\n", getpid());
293 fflush(fp);
294 (void) ftruncate(fileno(fp), ftell(fp));
295
296 /* abandon fd and fp even though the file is open. we need to
297 * keep it open and locked, but we don't need the handles elsewhere.
298 */
299}
300
225/* get_char(file) : like getc() but increment LineNumber on newlines
226 */
227int
228get_char(file)
229 FILE *file;
230{
231 int ch;
232

--- 86 unchanged lines hidden (view full) ---

319}
320
321
322/* int in_file(char *string, FILE *file)
323 * return TRUE if one of the lines in file matches string exactly,
324 * FALSE otherwise.
325 */
326static int
301/* get_char(file) : like getc() but increment LineNumber on newlines
302 */
303int
304get_char(file)
305 FILE *file;
306{
307 int ch;
308

--- 86 unchanged lines hidden (view full) ---

395}
396
397
398/* int in_file(char *string, FILE *file)
399 * return TRUE if one of the lines in file matches string exactly,
400 * FALSE otherwise.
401 */
402static int
327in_file(char *string, FILE *file)
403in_file(string, file)
404 char *string;
405 FILE *file;
328{
329 char line[MAX_TEMPSTR];
330
331 rewind(file);
332 while (fgets(line, MAX_TEMPSTR, file)) {
333 if (line[0] != '\0')
406{
407 char line[MAX_TEMPSTR];
408
409 rewind(file);
410 while (fgets(line, MAX_TEMPSTR, file)) {
411 if (line[0] != '\0')
334 if (line[strlen(line)-1] == '\n')
335 line[strlen(line)-1] = '\0';
412 line[strlen(line)-1] = '\0';
336 if (0 == strcmp(line, string))
337 return TRUE;
338 }
339 return FALSE;
340}
341
342
343/* int allowed(char *username)
344 * returns TRUE if (ALLOW_FILE exists and user is listed)
345 * or (DENY_FILE exists and user is NOT listed)
346 * or (neither file exists but user=="root" so it's okay)
347 */
348int
349allowed(username)
350 char *username;
351{
413 if (0 == strcmp(line, string))
414 return TRUE;
415 }
416 return FALSE;
417}
418
419
420/* int allowed(char *username)
421 * returns TRUE if (ALLOW_FILE exists and user is listed)
422 * or (DENY_FILE exists and user is NOT listed)
423 * or (neither file exists but user=="root" so it's okay)
424 */
425int
426allowed(username)
427 char *username;
428{
352 FILE *allow, *deny;
353 int isallowed;
429 static int init = FALSE;
430 static FILE *allow, *deny;
354
431
355 isallowed = FALSE;
356
357 deny = NULL;
432 if (!init) {
433 init = TRUE;
358#if defined(ALLOW_FILE) && defined(DENY_FILE)
434#if defined(ALLOW_FILE) && defined(DENY_FILE)
359 if ((allow = fopen(ALLOW_FILE, "r")) == NULL && errno != ENOENT)
360 goto out;
361 if ((deny = fopen(DENY_FILE, "r")) == NULL && errno != ENOENT)
362 goto out;
363 Debug(DMISC, ("allow/deny enabled, %d/%d\n", !!allow, !!deny))
435 allow = fopen(ALLOW_FILE, "r");
436 deny = fopen(DENY_FILE, "r");
437 Debug(DMISC, ("allow/deny enabled, %d/%d\n", !!allow, !!deny))
364#else
438#else
365 allow = NULL;
439 allow = NULL;
440 deny = NULL;
366#endif
441#endif
442 }
367
368 if (allow)
443
444 if (allow)
369 isallowed = in_file(username, allow);
370 else if (deny)
371 isallowed = !in_file(username, deny);
372 else {
445 return (in_file(username, allow));
446 if (deny)
447 return (!in_file(username, deny));
448
373#if defined(ALLOW_ONLY_ROOT)
449#if defined(ALLOW_ONLY_ROOT)
374 isallowed = (strcmp(username, ROOT_USER) == 0);
450 return (strcmp(username, ROOT_USER) == 0);
375#else
451#else
376 isallowed = TRUE;
452 return TRUE;
377#endif
453#endif
378 }
379out: if (allow)
380 fclose(allow);
381 if (deny)
382 fclose(deny);
383 return (isallowed);
384}
385
386
387void
388log_it(username, xpid, event, detail)
389 char *username;
390 int xpid;
391 char *event;

--- 13 unchanged lines hidden (view full) ---

405#if defined(LOG_FILE)
406 /* we assume that MAX_TEMPSTR will hold the date, time, &punctuation.
407 */
408 msg = malloc(strlen(username)
409 + strlen(event)
410 + strlen(detail)
411 + MAX_TEMPSTR);
412
454}
455
456
457void
458log_it(username, xpid, event, detail)
459 char *username;
460 int xpid;
461 char *event;

--- 13 unchanged lines hidden (view full) ---

475#if defined(LOG_FILE)
476 /* we assume that MAX_TEMPSTR will hold the date, time, &punctuation.
477 */
478 msg = malloc(strlen(username)
479 + strlen(event)
480 + strlen(detail)
481 + MAX_TEMPSTR);
482
413 if (msg == NULL)
414 warnx("failed to allocate memory for log message");
415 else {
483 if (LogFD < OK) {
484 LogFD = open(LOG_FILE, O_WRONLY|O_APPEND|O_CREAT, 0600);
416 if (LogFD < OK) {
485 if (LogFD < OK) {
417 LogFD = open(LOG_FILE, O_WRONLY|O_APPEND|O_CREAT, 0600);
418 if (LogFD < OK) {
419 warn("can't open log file %s", LOG_FILE);
420 } else {
421 (void) fcntl(LogFD, F_SETFD, 1);
422 }
486 fprintf(stderr, "%s: can't open log file\n",
487 ProgramName);
488 perror(LOG_FILE);
489 } else {
490 (void) fcntl(LogFD, F_SETFD, 1);
423 }
491 }
492 }
424
493
425 /* we have to sprintf() it because fprintf() doesn't always
426 * write everything out in one chunk and this has to be
427 * atomically appended to the log file.
428 */
429 sprintf(msg, "%s (%02d/%02d-%02d:%02d:%02d-%d) %s (%s)\n",
430 username,
431 t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min,
432 t->tm_sec, pid, event, detail);
494 /* we have to sprintf() it because fprintf() doesn't always write
495 * everything out in one chunk and this has to be atomically appended
496 * to the log file.
497 */
498 sprintf(msg, "%s (%02d/%02d-%02d:%02d:%02d-%d) %s (%s)\n",
499 username,
500 t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, pid,
501 event, detail);
433
502
434 /* we have to run strlen() because sprintf() returns (char*)
435 * on old BSD.
436 */
437 if (LogFD < OK || write(LogFD, msg, strlen(msg)) < OK) {
438 if (LogFD >= OK)
439 warn("%s", LOG_FILE);
440 warnx("can't write to log file");
441 write(STDERR, msg, strlen(msg));
442 }
443
444 free(msg);
503 /* we have to run strlen() because sprintf() returns (char*) on old BSD
504 */
505 if (LogFD < OK || write(LogFD, msg, strlen(msg)) < OK) {
506 if (LogFD >= OK)
507 perror(LOG_FILE);
508 fprintf(stderr, "%s: can't write to log file\n", ProgramName);
509 write(STDERR, msg, strlen(msg));
445 }
510 }
511
512 free(msg);
446#endif /*LOG_FILE*/
447
448#if defined(SYSLOG)
449 if (!syslog_open) {
450 /* we don't use LOG_PID since the pid passed to us by
451 * our client may not be our own. therefore we want to
452 * print the pid ourselves.
453 */

--- 59 unchanged lines hidden (view full) ---

513 *rp = '\0';
514 return rb;
515}
516
517
518/* warning:
519 * heavily ascii-dependent.
520 */
513#endif /*LOG_FILE*/
514
515#if defined(SYSLOG)
516 if (!syslog_open) {
517 /* we don't use LOG_PID since the pid passed to us by
518 * our client may not be our own. therefore we want to
519 * print the pid ourselves.
520 */

--- 59 unchanged lines hidden (view full) ---

580 *rp = '\0';
581 return rb;
582}
583
584
585/* warning:
586 * heavily ascii-dependent.
587 */
521static void
522mkprint(register char *dst, register unsigned char *src, register int len)
588void
589mkprint(dst, src, len)
590 register char *dst;
591 register unsigned char *src;
592 register int len;
523{
524 while (len-- > 0)
525 {
526 register unsigned char ch = *src++;
527
528 if (ch < ' ') { /* control character */
529 *dst++ = '^';
530 *dst++ = ch + '@';

--- 16 unchanged lines hidden (view full) ---

547 */
548char *
549mkprints(src, len)
550 register unsigned char *src;
551 register unsigned int len;
552{
553 register char *dst = malloc(len*4 + 1);
554
593{
594 while (len-- > 0)
595 {
596 register unsigned char ch = *src++;
597
598 if (ch < ' ') { /* control character */
599 *dst++ = '^';
600 *dst++ = ch + '@';

--- 16 unchanged lines hidden (view full) ---

617 */
618char *
619mkprints(src, len)
620 register unsigned char *src;
621 register unsigned int len;
622{
623 register char *dst = malloc(len*4 + 1);
624
555 if (dst != NULL)
556 mkprint(dst, src, len);
625 mkprint(dst, src, len);
557
558 return dst;
559}
560
561
562#ifdef MAIL_DATE
563/* Sat, 27 Feb 93 11:44:51 CST
564 * 123456789012345678901234567
565 */
566char *
567arpadate(clock)
568 time_t *clock;
569{
570 time_t t = clock ?*clock :time(0L);
571 struct tm *tm = localtime(&t);
626
627 return dst;
628}
629
630
631#ifdef MAIL_DATE
632/* Sat, 27 Feb 93 11:44:51 CST
633 * 123456789012345678901234567
634 */
635char *
636arpadate(clock)
637 time_t *clock;
638{
639 time_t t = clock ?*clock :time(0L);
640 struct tm *tm = localtime(&t);
572 static char ret[32]; /* zone name might be >3 chars */
573
574 if (tm->tm_year >= 100)
575 tm->tm_year += 1900;
576
577 (void) snprintf(ret, sizeof(ret), "%s, %2d %s %d %02d:%02d:%02d %s",
641 static char ret[30]; /* zone name might be >3 chars */
642
643 (void) sprintf(ret, "%s, %2d %s %2d %02d:%02d:%02d %s",
578 DowNames[tm->tm_wday],
579 tm->tm_mday,
580 MonthNames[tm->tm_mon],
581 tm->tm_year,
582 tm->tm_hour,
583 tm->tm_min,
584 tm->tm_sec,
585 TZONE(*tm));
586 return ret;
587}
588#endif /*MAIL_DATE*/
589
590
644 DowNames[tm->tm_wday],
645 tm->tm_mday,
646 MonthNames[tm->tm_mon],
647 tm->tm_year,
648 tm->tm_hour,
649 tm->tm_min,
650 tm->tm_sec,
651 TZONE(*tm));
652 return ret;
653}
654#endif /*MAIL_DATE*/
655
656
591#ifdef HAVE_SAVED_UIDS
657#ifdef HAVE_SAVED_SUIDS
592static int save_euid;
593int swap_uids() { save_euid = geteuid(); return seteuid(getuid()); }
594int swap_uids_back() { return seteuid(save_euid); }
595#else /*HAVE_SAVED_UIDS*/
596int swap_uids() { return setreuid(geteuid(), getuid()); }
597int swap_uids_back() { return swap_uids(); }
598#endif /*HAVE_SAVED_UIDS*/
658static int save_euid;
659int swap_uids() { save_euid = geteuid(); return seteuid(getuid()); }
660int swap_uids_back() { return seteuid(save_euid); }
661#else /*HAVE_SAVED_UIDS*/
662int swap_uids() { return setreuid(geteuid(), getuid()); }
663int swap_uids_back() { return swap_uids(); }
664#endif /*HAVE_SAVED_UIDS*/