1 /* location-manual.c -- Manual location provider source
2    This file is part of Redshift.
3 
4    Redshift is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8 
9    Redshift is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with Redshift.  If not, see <http://www.gnu.org/licenses/>.
16 
17    Copyright (c) 2010-2017  Jon Lund Steffensen <jonlst@gmail.com>
18 */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <math.h>
23 #include <string.h>
24 #include <errno.h>
25 
26 #include "location-manual.h"
27 
28 #ifdef ENABLE_NLS
29 # include <libintl.h>
30 # define _(s) gettext(s)
31 #else
32 # define _(s) s
33 #endif
34 
35 
36 typedef struct {
37 	location_t loc;
38 } location_manual_state_t;
39 
40 
41 static int
location_manual_init(location_manual_state_t ** state)42 location_manual_init(location_manual_state_t **state)
43 {
44 	*state = malloc(sizeof(location_manual_state_t));
45 	if (*state == NULL) return -1;
46 
47 	location_manual_state_t *s = *state;
48 	s->loc.lat = NAN;
49 	s->loc.lon = NAN;
50 
51 	return 0;
52 }
53 
54 static int
location_manual_start(location_manual_state_t * state)55 location_manual_start(location_manual_state_t *state)
56 {
57 	/* Latitude and longitude must be set */
58 	if (isnan(state->loc.lat) || isnan(state->loc.lon)) {
59 		fputs(_("Latitude and longitude must be set.\n"), stderr);
60 		exit(EXIT_FAILURE);
61 	}
62 
63 	return 0;
64 }
65 
66 static void
location_manual_free(location_manual_state_t * state)67 location_manual_free(location_manual_state_t *state)
68 {
69 	free(state);
70 }
71 
72 static void
location_manual_print_help(FILE * f)73 location_manual_print_help(FILE *f)
74 {
75 	fputs(_("Specify location manually.\n"), f);
76 	fputs("\n", f);
77 
78 	/* TRANSLATORS: Manual location help output
79 	   left column must not be translated */
80 	fputs(_("  lat=N\t\tLatitude\n"
81 		"  lon=N\t\tLongitude\n"), f);
82 	fputs("\n", f);
83 	fputs(_("Both values are expected to be floating point numbers,\n"
84 		"negative values representing west / south, respectively.\n"), f);
85 	fputs("\n", f);
86 }
87 
88 static int
location_manual_set_option(location_manual_state_t * state,const char * key,const char * value)89 location_manual_set_option(location_manual_state_t *state, const char *key,
90 			   const char *value)
91 {
92 	/* Parse float value */
93 	char *end;
94 	errno = 0;
95 	float v = strtof(value, &end);
96 	if (errno != 0 || *end != '\0') {
97 		fputs(_("Malformed argument.\n"), stderr);
98 		return -1;
99 	}
100 
101 	if (strcasecmp(key, "lat") == 0) {
102 		state->loc.lat = v;
103 	} else if (strcasecmp(key, "lon") == 0) {
104 		state->loc.lon = v;
105 	} else {
106 		fprintf(stderr, _("Unknown method parameter: `%s'.\n"), key);
107 		return -1;
108 	}
109 
110 	return 0;
111 }
112 
113 static int
location_manual_get_fd(location_manual_state_t * state)114 location_manual_get_fd(location_manual_state_t *state)
115 {
116 	return -1;
117 }
118 
119 static int
location_manual_handle(location_manual_state_t * state,location_t * location,int * available)120 location_manual_handle(
121 	location_manual_state_t *state, location_t *location, int *available)
122 {
123 	*location = state->loc;
124 	*available = 1;
125 
126 	return 0;
127 }
128 
129 
130 const location_provider_t manual_location_provider = {
131 	"manual",
132 	(location_provider_init_func *)location_manual_init,
133 	(location_provider_start_func *)location_manual_start,
134 	(location_provider_free_func *)location_manual_free,
135 	(location_provider_print_help_func *)location_manual_print_help,
136 	(location_provider_set_option_func *)location_manual_set_option,
137 	(location_provider_get_fd_func *)location_manual_get_fd,
138 	(location_provider_handle_func *)location_manual_handle
139 };
140