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$");
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);
9913840Swosch			break;
10013840Swosch
10113840Swosch		case 'B': /* days before current date */
102181322Sedwin			f_dayBefore = atoi(optarg);
10313840Swosch			break;
10413840Swosch
105227370Sgrog		case 'D': /* debug output of sun and moon info */
106227370Sgrog			DEBUG = optarg;
107227370Sgrog			break;
108227370Sgrog
109227370Sgrog		case 'd': /* debug output of current date */
110227370Sgrog			debug = 1;
111227370Sgrog			break;
112227370Sgrog
113205821Sedwin		case 'F': /* Change the time: When does weekend start? */
11498181Sgrog			Friday = atoi(optarg);
11598181Sgrog			break;
116227370Sgrog
117227370Sgrog		case 'f': /* other calendar file */
118227370Sgrog			calendarFile = optarg;
119227370Sgrog			break;
120227370Sgrog
121205821Sedwin		case 'l': /* Change longitudal position */
122205821Sedwin			EastLongitude = strtol(optarg, NULL, 10);
123205821Sedwin			break;
124227370Sgrog
125227370Sgrog		case 't': /* other date, for tests */
126227370Sgrog			f_time = Mktime(optarg);
127227370Sgrog			break;
128227370Sgrog
129205821Sedwin		case 'U': /* Change UTC offset */
130205821Sedwin			UTCOffset = strtod(optarg, NULL);
131205821Sedwin			break;
13298181Sgrog
1331590Srgrimes		case '?':
1341590Srgrimes		default:
1351590Srgrimes			usage();
1361590Srgrimes		}
137181322Sedwin
1381590Srgrimes	argc -= optind;
1391590Srgrimes	argv += optind;
1401590Srgrimes
1411590Srgrimes	if (argc)
1421590Srgrimes		usage();
1431590Srgrimes
14413840Swosch	/* use current time */
145181322Sedwin	if (f_time <= 0)
146181322Sedwin		(void)time(&f_time);
14713840Swosch
148205821Sedwin	/* if not set, determine where I could be */
149205821Sedwin	{
150205821Sedwin		if (UTCOffset == UTCOFFSET_NOTSET &&
151205821Sedwin		    EastLongitude == LONGITUDE_NOTSET) {
152205821Sedwin			/* Calculate on difference between here and UTC */
153205821Sedwin			time_t t;
154205821Sedwin			struct tm tm;
155205821Sedwin			long utcoffset, hh, mm, ss;
156205821Sedwin			double uo;
157181322Sedwin
158205821Sedwin			time(&t);
159205821Sedwin			localtime_r(&t, &tm);
160205821Sedwin			utcoffset = tm.tm_gmtoff;
161205821Sedwin			/* seconds -> hh:mm:ss */
162205821Sedwin			hh = utcoffset / SECSPERHOUR;
163205821Sedwin			utcoffset %= SECSPERHOUR;
164205821Sedwin			mm = utcoffset / SECSPERMINUTE;
165205821Sedwin			utcoffset %= SECSPERMINUTE;
166205821Sedwin			ss = utcoffset;
167205821Sedwin
168205821Sedwin			/* hh:mm:ss -> hh.mmss */
169205821Sedwin			uo = mm + (100.0 * (ss / 60.0));
170205821Sedwin			uo /=  60.0 / 100.0;
171205821Sedwin			uo = hh + uo / 100;
172205821Sedwin
173205821Sedwin			UTCOffset = uo;
174205821Sedwin			EastLongitude = UTCOffset * 15;
175205821Sedwin		} else if (UTCOffset == UTCOFFSET_NOTSET) {
176205821Sedwin			/* Base on information given */
177205821Sedwin			UTCOffset = EastLongitude / 15;
178205821Sedwin		} else if (EastLongitude == LONGITUDE_NOTSET) {
179205821Sedwin			/* Base on information given */
180205821Sedwin			EastLongitude = UTCOffset * 15;
181205821Sedwin		}
182205821Sedwin	}
183205821Sedwin
184205821Sedwin	settimes(f_time, f_dayBefore, f_dayAfter, Friday, &tp1, &tp2);
185205821Sedwin	generatedates(&tp1, &tp2);
186205821Sedwin
187205821Sedwin	/*
188205821Sedwin	 * FROM now on, we are working in UTC.
189205821Sedwin	 * This will only affect moon and sun related events anyway.
190205821Sedwin	 */
191205821Sedwin	if (setenv("TZ", "UTC", 1) != 0)
192205821Sedwin		errx(1, "setenv: %s", strerror(errno));
193205821Sedwin	tzset();
194205821Sedwin
195205821Sedwin	if (debug)
196205821Sedwin		dumpdates();
197205821Sedwin
198205821Sedwin	if (DEBUG != NULL) {
199205821Sedwin		dodebug(DEBUG);
200205821Sedwin		exit(0);
201205821Sedwin	}
202205821Sedwin
2031590Srgrimes	if (doall)
2041590Srgrimes		while ((pw = getpwent()) != NULL) {
2051590Srgrimes			(void)setegid(pw->pw_gid);
20622323Smpp			(void)initgroups(pw->pw_name, pw->pw_gid);
2071590Srgrimes			(void)seteuid(pw->pw_uid);
2081590Srgrimes			if (!chdir(pw->pw_dir))
2091590Srgrimes				cal();
2101590Srgrimes			(void)seteuid(0);
2111590Srgrimes		}
21211334Sache	else
2131590Srgrimes		cal();
2141590Srgrimes	exit(0);
2151590Srgrimes}
2161590Srgrimes
2171590Srgrimes
218181323Sedwinstatic void __dead2
219169343Sdwmaloneusage(void)
2201590Srgrimes{
221251678Sgrog
222205821Sedwin	fprintf(stderr, "%s\n%s\n%s\n",
223227370Sgrog	    "usage: calendar [-A days] [-a] [-B days] [-D sun|moon] [-d]",
224227370Sgrog	    "		     [-F friday] [-f calendarfile] [-l longitude]",
225227370Sgrog	    "		     [-t dd[.mm[.year]]] [-U utcoffset] [-W days]"
226205821Sedwin	    );
22713840Swosch	exit(1);
2281590Srgrimes}
229