source: trunk/athena/etc/athinfod/athinfod.c @ 13769

Revision 13769, 6.6 KB checked in by danw, 25 years ago (diff)
compile with warnings
Line 
1/* Copyright 1998 by the Massachusetts Institute of Technology.
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose.  It is provided "as is"
13 * without express or implied warranty.
14 */
15
16static const char rcsid[] = "$Id: athinfod.c,v 1.3 1999-10-19 20:22:56 danw Exp $";
17
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <sys/socket.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <ctype.h>
25#include <unistd.h>
26#include <fcntl.h>
27
28#define PATH_ATHINFO_DEFS "/etc/athena/athinfo.defs"
29#define PATH_ATHINFO_ACCESS "/etc/athena/athinfo.access"
30
31static const char *read_query(void);
32static void shutdown_input(void);
33static const char *get_definition(const char *query);
34static void check_enabled(const char *query);
35static int first_field_matches(const char *s, const char *word);
36static const char *skip_spaces(const char *p);
37static const char *skip_nonspaces(const char *p);
38static int read_line(FILE *fp, char **buf, int *bufsize);
39static void *emalloc(size_t size);
40static void *erealloc(void *ptr, size_t size);
41
42int main(int argc, char **argv)
43{
44  const char *query, *cmd;
45
46  query = read_query();
47  shutdown_input();
48  cmd = get_definition(query);
49  check_enabled(query);
50  execl("/bin/sh", "sh", "-c", cmd, (char *) NULL);
51  fprintf(stderr, "athinfod: cannot run shell, aborting.\n");
52  return 1;
53}
54
55/* Read the query from stdin and validate it. */
56static const char *read_query(void)
57{
58  char *line = NULL;
59  int linesize;
60  const char *p;
61
62  if (read_line(stdin, &line, &linesize) != 0)
63    {
64      fprintf(stderr, "athinfod: couldn't read query.\n");
65      exit(0);
66    }
67
68  /* Make sure the query consists of printable nonspace characters. */
69  for (p = line; *p; p++)
70    {
71      if (!isprint((unsigned char)*p) || isspace((unsigned char)*p))
72        {
73          fprintf(stderr, "athinfod: invalid query.\n");
74          exit(0);
75        }
76    }
77  return line;
78}
79
80/* Shut down the input side of the inetd socket and repoint stdin at
81 * /dev/null.  This eliminates the possibility of malicious input
82 * affecting the commands we execute.
83 */
84static void shutdown_input(void)
85{
86  int fd;
87
88  shutdown(STDIN_FILENO, 0);
89  close(STDIN_FILENO);
90  fd = open("/dev/null", O_RDONLY);
91  if (fd == -1)
92    {
93      fprintf(stderr, "athinfod: cannot open /dev/null, aborting.\n");
94      exit(1);
95    }
96  if (fd != STDIN_FILENO)
97    {
98      dup2(fd, STDIN_FILENO);
99      close(fd);
100    }
101}
102
103/* Read the definition of query from the athinfo.defs file. */
104static const char *get_definition(const char *query)
105{
106  char *line = NULL;
107  int linesize;
108  FILE *fp;
109
110  fp = fopen(PATH_ATHINFO_DEFS, "r");
111  if (!fp)
112    {
113      fprintf(stderr,
114              "athinfod: cannot open athinfo definitions file, aborting.\n");
115      exit(1);
116    }
117
118  while (read_line(fp, &line, &linesize) == 0)
119    {
120      /* Ignore comment lines. */
121      if (*line == '#')
122        continue;
123
124      if (first_field_matches(line, query))
125        {
126          fclose(fp);
127          return skip_spaces(skip_nonspaces(line));
128        }
129    }
130
131  fclose(fp);
132  fprintf(stderr, "athinfod: unrecognized query.\n");
133  exit(0);
134}
135
136/* See if this command is enabled. */
137static void check_enabled(const char *query)
138{
139  char *line = NULL;
140  int linesize, enabled = 0, val;
141  FILE *fp;
142  const char *p;
143
144  fp = fopen(PATH_ATHINFO_ACCESS, "r");
145  if (!fp)
146    {
147      fprintf(stderr,
148              "athinfod: cannot open athinfo access file, aborting.\n");
149      exit(1);
150    }
151
152  while (read_line(fp, &line, &linesize) == 0)
153    {
154      /* Only pay attention to lines starting with "enable" or "disable". */
155      if (first_field_matches(line, "enable"))
156        val = 1;
157      else if (first_field_matches(line, "disable"))
158        val = 0;
159      else
160        continue;
161
162      /* If we find an exact match, stop.  If we find a glob match,
163       * accept that value for now but hold out for an exact match.
164       * (This means if there are conflicting lines in the config
165       * file, we take the first exact match but the last glob match.
166       * Oh well.)
167       */
168      p = skip_spaces(skip_nonspaces(line));
169      if (first_field_matches(p, query))
170        {
171          enabled = val;
172          break;
173        }
174      else if (first_field_matches(p, "*"))
175        enabled = val;
176    }
177
178  fclose(fp);
179  free(line);
180  if (!enabled)
181    {
182      fprintf(stderr, "athinfod: query disabled.\n");
183      exit(0);
184    }
185}
186
187static int first_field_matches(const char *s, const char *word)
188{
189  int len = strlen(word);
190
191  return (strncasecmp(s, word, len) == 0 &&
192          (isspace((unsigned char)s[len]) || !s[len]));
193}
194
195static const char *skip_spaces(const char *p)
196{
197  while (isspace((unsigned char)*p))
198    p++;
199  return p;
200}
201
202static const char *skip_nonspaces(const char *p)
203{
204  while (*p && !isspace((unsigned char)*p))
205    p++;
206  return p;
207}
208
209/* Read a line from a file into a dynamically allocated buffer,
210 * zeroing the trailing newline if there is one.  The calling routine
211 * may call read_line multiple times with the same buf and bufsize
212 * pointers; *buf will be reallocated and *bufsize adjusted as
213 * appropriate.  The initial value of *buf should be NULL.  After the
214 * calling routine is done reading lines, it should free *buf.  This
215 * function returns 0 if a line was successfully read, 1 if the file
216 * ended, and -1 if there was an I/O error.
217 */
218static int read_line(FILE *fp, char **buf, int *bufsize)
219{
220  char *newbuf;
221  int offset = 0, len;
222
223  if (*buf == NULL)
224    {
225      *buf = emalloc(128);
226      *bufsize = 128;
227    }
228
229  while (1)
230    {
231      if (!fgets(*buf + offset, *bufsize - offset, fp))
232        return (offset != 0) ? 0 : (ferror(fp)) ? -1 : 1;
233      len = offset + strlen(*buf + offset);
234      if ((*buf)[len - 1] == '\n')
235        {
236          (*buf)[len - 1] = 0;
237          if (len > 1 && (*buf)[len - 2] == '\r')
238            (*buf)[len - 2] = 0;
239          return 0;
240        }
241      offset = len;
242
243      /* Allocate more space. */
244      newbuf = erealloc(*buf, *bufsize * 2);
245      *buf = newbuf;
246      *bufsize *= 2;
247    }
248}
249
250static void *emalloc(size_t size)
251{
252  void *ptr;
253
254  ptr = malloc(size);
255  if (!ptr)
256    {
257      fprintf(stderr, "athinfod: malloc failure, aborting.\n");
258      exit(1);
259    }
260  return ptr;
261}
262
263void *erealloc(void *ptr, size_t size)
264{
265  ptr = realloc(ptr, size);
266  if (!ptr)
267    {
268      fprintf(stderr, "athinfod: realloc failure, aborting.\n");
269      exit(1);
270    }
271  return ptr;
272}
Note: See TracBrowser for help on using the repository browser.