summaryrefslogtreecommitdiff
path: root/args.c
blob: 55aaab9eee1e4a4e74ad198747a0fdfaf38ed614 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* Gopher filesystem. Argument handling routines.

   Copyright (C) 2001, 2002 James A. Morrison <ja2morri@uwaterloo.ca>
   Copyright (C) 2000 Igor Khavkine <igor@twu.net>

   Gopherfs is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2, or (at
   your option) any later version.

   Gopherfs is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. */

#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <error.h>
#include <stdio.h>
#include <argp.h>
#include <argz.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

#include <hurd/netfs.h>

#include "gopherfs.h"

/* ARGP data */
const char *argp_program_version = GOPHER_SERVER_NAME " " GOPHER_SERVER_VERSION;
const char *argp_program_bug_address = "ja2morri@uwaterloo.ca";
char args_doc[] = "SERVER [REMOTE_FS]";
char doc[] = "Hurd gopher filesystem translator";
static const struct argp_option options[] = {
  {"port", 'P', "NUMBER", 0, "Specify a non-standard port"},
  {"debug", 'D', "FILE", 0, "Print debug output to FILE"},
  {0}
};
/* the function that groks the arguments and fills
 * global options
 */
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
  struct gopherfs_params *params = state->input;
  error_t err = 0;

  FILE *debug_stream = NULL;
  char *tail;
  switch (key)
    {
    case 'D':
      if (arg)
	{
	  debug_stream = fopen (arg, "w+");
	  if (! debug_stream)
	    {
	      err = errno;
	      argp_failure (state, 0, errno, "Cannot open debugging file %s", arg);
	    }
	}
      else
	debug_stream = stderr;

      if (!err)
	debug_init (debug_stream);
	
      break;

    case 'P':
      params->port = (unsigned short) strtol (arg, &tail, 10);
      if (tail == arg || params->port > USHRT_MAX)
        {
          /* XXX bad integer conversion */
          error (1, errno, "bad port number");
        }
      break;

    case ARGP_KEY_ARG:
      if (state->arg_num == 0)
        {
	  params->dir = "";
	  params->server = arg;
        }
      else if (state->arg_num == 1)
	{
	  params->dir = arg;
	}
      else
	return ARGP_ERR_UNKNOWN;
      break;

    case ARGP_KEY_SUCCESS:
      if (state->arg_num == 0)
	argp_error (state, "No remote filesystem specified");
      else
	{
	  /* No port was provided. Get gopher default port. */
	  if (params->port == 0)
	    {
	      struct servent *se = getservbyname ("gopher", "tcp");
	      if (! se)
		argp_error (state, "Couldn't get gopher port");

	      params->port = ntohs(se->s_port);
	    }

	  /* Check if the given address resolves. */
	  error_t err;
	  struct addrinfo *addr;
	  err = lookup_host (params->server, params->port, &addr);
	  if (err)
	    argp_failure (state, 10, 0, "%s: %s", params->server, gai_strerror (err));
	}
    default:
      return ARGP_ERR_UNKNOWN;
    }
  return 0;
}

static struct argp_child argp_children[] = { {&netfs_std_startup_argp}, {0} };
static struct argp parser =
  { options, parse_opt, args_doc, doc, argp_children };

/* Used by netfs_set_options to handle runtime option parsing. */
struct argp *netfs_runtime_argp = &parser;

/* maybe overwrite this some time later */
error_t netfs_append_args (char **argz, size_t * argz_len);

/* handle all initial parameter parsing */
error_t
gopherfs_parse_args (int argc, char **argv, struct gopherfs_params *params)
{
  return argp_parse (&parser, argc, argv, 0, 0, params);
}