1205821Sedwin/*-
21590Srgrimes * Copyright (c) 1989, 1993, 1994
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 4. Neither the name of the University nor the names of its contributors
141590Srgrimes *    may be used to endorse or promote products derived from this software
151590Srgrimes *    without specific prior written permission.
161590Srgrimes *
171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271590Srgrimes * SUCH DAMAGE.
281590Srgrimes */
291590Srgrimes
301590Srgrimes#ifndef lint
3115714Sachestatic const char copyright[] =
321590Srgrimes"@(#) Copyright (c) 1989, 1993\n\
331590Srgrimes	The Regents of the University of California.  All rights reserved.\n";
3487235Smarkm#endif
351590Srgrimes
3687628Sdwmalone#if 0
371590Srgrimes#ifndef lint
38227370Sgrogstatic char sccsid[] = "@(#)calendar.c	8.3 (Berkeley) 3/25/94";
3987235Smarkm#endif
4087628Sdwmalone#endif
411590Srgrimes
4287628Sdwmalone#include <sys/cdefs.h>
4387628Sdwmalone__FBSDID("$FreeBSD: stable/11/usr.bin/calendar/calendar.c 368914 2021-01-01 09:06:16Z se $");
4487628Sdwmalone
4515714Sache#include <err.h>
4615714Sache#include <errno.h>
4715714Sache#include <locale.h>
481590Srgrimes#include <pwd.h>
491590Srgrimes#include <stdio.h>
501590Srgrimes#include <stdlib.h>
51205821Sedwin#include <string.h>
5213840Swosch#include <time.h>
5315714Sache#include <unistd.h>
541590Srgrimes
5513840Swosch#include "calendar.h"
561590Srgrimes
57205821Sedwin#define	UTCOFFSET_NOTSET	100	/* Expected between -24 and +24 */
58205821Sedwin#define	LONGITUDE_NOTSET	1000	/* Expected between -360 and +360 */
59205821Sedwin
60181322Sedwinstruct passwd	*pw;
61181322Sedwinint		doall = 0;
62205821Sedwinint		debug = 0;
63241737Sedstatic char	*DEBUG = NULL;
64241737Sedstatic time_t	f_time = 0;
65205821Sedwindouble		UTCOffset = UTCOFFSET_NOTSET;
66205821Sedwinint		EastLongitude = LONGITUDE_NOTSET;
671590Srgrimes
68181323Sedwinstatic void	usage(void) __dead2;
69181323Sedwin
701590Srgrimesint
71169343Sdwmalonemain(int argc, char *argv[])
721590Srgrimes{
73205821Sedwin	int	f_dayAfter = 0;		/* days after current date */
74205821Sedwin	int	f_dayBefore = 0;	/* days before current date */
75205821Sedwin	int	Friday = 5;		/* day before weekend */
76205821Sedwin
771590Srgrimes	int ch;
78205821Sedwin	struct tm tp1, tp2;
791590Srgrimes
80181322Sedwin	(void)setlocale(LC_ALL, "");
8115714Sache
82227370Sgrog	while ((ch = getopt(argc, argv, "-A:aB:D:dF:f:l:t:U:W:?")) != -1)
831590Srgrimes		switch (ch) {
841590Srgrimes		case '-':		/* backward contemptible */
851590Srgrimes		case 'a':
861590Srgrimes			if (getuid()) {
871590Srgrimes				errno = EPERM;
881590Srgrimes				err(1, NULL);
891590Srgrimes			}
901590Srgrimes			doall = 1;
911590Srgrimes			break;
9213840Swosch
9398181Sgrog		case 'W': /* we don't need no steenking Fridays */
9498181Sgrog			Friday = -1;
95205821Sedwin			/* FALLTHROUGH */
9698181Sgrog
9713840Swosch		case 'A': /* days after current date */
9813840Swosch			f_dayAfter = atoi(optarg);
99262011Seadler			if (f_dayAfter < 0)
100262011Seadler				errx(1, "number of days must be positive");
10113840Swosch			break;
10213840Swosch
10313840Swosch		case 'B': /* days before current date */
104181322Sedwin			f_dayBefore = atoi(optarg);
105262011Seadler			if (f_dayBefore < 0)
106262011Seadler				errx(1, "number of days must be positive");
10713840Swosch			break;
10813840Swosch
109227370Sgrog		case 'D': /* debug output of sun and moon info */
110227370Sgrog			DEBUG = optarg;
111227370Sgrog			break;
112227370Sgrog
113227370Sgrog		case 'd': /* debug output of current date */
114227370Sgrog			debug = 1;
115227370Sgrog			break;
116227370Sgrog
117205821Sedwin		case 'F': /* Change the time: When does weekend start? */
11898181Sgrog			Friday = atoi(optarg);
11998181Sgrog			break;
120227370Sgrog
121227370Sgrog		case 'f': /* other calendar file */
122227370Sgrog			calendarFile = optarg;
123227370Sgrog			break;
124227370Sgrog
125205821Sedwin		case 'l': /* Change longitudal position */
126205821Sedwin			EastLongitude = strtol(optarg, NULL, 10);
127205821Sedwin			break;
128227370Sgrog
129227370Sgrog		case 't': /* other date, for tests */
130227370Sgrog			f_time = Mktime(optarg);
131227370Sgrog			break;
132227370Sgrog
133205821Sedwin		case 'U': /* Change UTC offset */
134205821Sedwin			UTCOffset = strtod(optarg, NULL);
135205821Sedwin			break;
13698181Sgrog
1371590Srgrimes		case '?':
1381590Srgrimes		default:
1391590Srgrimes			usage();
1401590Srgrimes		}
141181322Sedwin
1421590Srgrimes	argc -= optind;
1431590Srgrimes	argv += optind;
1441590Srgrimes
1451590Srgrimes	if (argc)
1461590Srgrimes		usage();
1471590Srgrimes
14813840Swosch	/* use current time */
149181322Sedwin	if (f_time <= 0)
150181322Sedwin		(void)time(&f_time);
15113840Swosch
152205821Sedwin	/* if not set, determine where I could be */
153205821Sedwin	{
154205821Sedwin		if (UTCOffset == UTCOFFSET_NOTSET &&
155205821Sedwin		    EastLongitude == LONGITUDE_NOTSET) {
156205821Sedwin			/* Calculate on difference between here and UTC */
157205821Sedwin			time_t t;
158205821Sedwin			struct tm tm;
159205821Sedwin			long utcoffset, hh, mm, ss;
160205821Sedwin			double uo;
161181322Sedwin
162205821Sedwin			time(&t);
163205821Sedwin			localtime_r(&t, &tm);
164205821Sedwin			utcoffset = tm.tm_gmtoff;
165205821Sedwin			/* seconds -> hh:mm:ss */
166205821Sedwin			hh = utcoffset / SECSPERHOUR;
167205821Sedwin			utcoffset %= SECSPERHOUR;
168205821Sedwin			mm = utcoffset / SECSPERMINUTE;
169205821Sedwin			utcoffset %= SECSPERMINUTE;
170205821Sedwin			ss = utcoffset;
171205821Sedwin
172205821Sedwin			/* hh:mm:ss -> hh.mmss */
173205821Sedwin			uo = mm + (100.0 * (ss / 60.0));
174205821Sedwin			uo /=  60.0 / 100.0;
175205821Sedwin			uo = hh + uo / 100;
176205821Sedwin
177205821Sedwin			UTCOffset = uo;
178205821Sedwin			EastLongitude = UTCOffset * 15;
179205821Sedwin		} else if (UTCOffset == UTCOFFSET_NOTSET) {
180205821Sedwin			/* Base on information given */
181205821Sedwin			UTCOffset = EastLongitude / 15;
182205821Sedwin		} else if (EastLongitude == LONGITUDE_NOTSET) {
183205821Sedwin			/* Base on information given */
184205821Sedwin			EastLongitude = UTCOffset * 15;
185205821Sedwin		}
186205821Sedwin	}
187205821Sedwin
188205821Sedwin	settimes(f_time, f_dayBefore, f_dayAfter, Friday, &tp1, &tp2);
189205821Sedwin	generatedates(&tp1, &tp2);
190205821Sedwin
191205821Sedwin	/*
192205821Sedwin	 * FROM now on, we are working in UTC.
193205821Sedwin	 * This will only affect moon and sun related events anyway.
194205821Sedwin	 */
195205821Sedwin	if (setenv("TZ", "UTC", 1) != 0)
196205821Sedwin		errx(1, "setenv: %s", strerror(errno));
197205821Sedwin	tzset();
198205821Sedwin
199205821Sedwin	if (debug)
200205821Sedwin		dumpdates();
201205821Sedwin
202205821Sedwin	if (DEBUG != NULL) {
203205821Sedwin		dodebug(DEBUG);
204205821Sedwin		exit(0);
205205821Sedwin	}
206205821Sedwin
2071590Srgrimes	if (doall)
2081590Srgrimes		while ((pw = getpwent()) != NULL) {
2091590Srgrimes			(void)setegid(pw->pw_gid);
21022323Smpp			(void)initgroups(pw->pw_name, pw->pw_gid);
2111590Srgrimes			(void)seteuid(pw->pw_uid);
212368914Sse			if (!chdir(pw->pw_dir)) {
213368914Sse				setenv("HOME", pw->pw_dir, 1);
2141590Srgrimes				cal();
215368914Sse			}
2161590Srgrimes			(void)seteuid(0);
2171590Srgrimes		}
21811334Sache	else
2191590Srgrimes		cal();
2201590Srgrimes	exit(0);
2211590Srgrimes}
2221590Srgrimes
2231590Srgrimes
224181323Sedwinstatic void __dead2
225169343Sdwmaloneusage(void)
2261590Srgrimes{
227251678Sgrog
228205821Sedwin	fprintf(stderr, "%s\n%s\n%s\n",
229227370Sgrog	    "usage: calendar [-A days] [-a] [-B days] [-D sun|moon] [-d]",
230227370Sgrog	    "		     [-F friday] [-f calendarfile] [-l longitude]",
231227370Sgrog	    "		     [-t dd[.mm[.year]]] [-U utcoffset] [-W days]"
232205821Sedwin	    );
23313840Swosch	exit(1);
2341590Srgrimes}
235