1/* uupick.c
2   Get files stored in the public directory by uucp -t.
3
4   Copyright (C) 1992, 1993, 1994, 1995, 2002 Ian Lance Taylor
5
6   This file is part of the Taylor UUCP package.
7
8   This program is free software; you can redistribute it and/or
9   modify it under the terms of the GNU General Public License as
10   published by the Free Software Foundation; either version 2 of the
11   License, or (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
21
22   The author of the program may be contacted at ian@airs.com.
23   */
24
25#include "uucp.h"
26
27#if USE_RCS_ID
28const char uupick_rcsid[] = "$Id: uupick.c,v 1.19 2002/03/05 19:10:42 ian Rel $";
29#endif
30
31#include <errno.h>
32
33#include "getopt.h"
34
35#include "uudefs.h"
36#include "uuconf.h"
37#include "system.h"
38
39/* Local functions.  */
40
41static void upmovedir P((const char *zfull, const char *zrelative,
42			 pointer pinfo));
43static void upmove P((const char *zfrom, const char *zto));
44
45/* Long getopt options.  */
46static const struct option asPlongopts[] =
47{
48  { "system", required_argument, NULL, 's' },
49  { "config", required_argument, NULL, 'I' },
50  { "debug", required_argument, NULL, 'x' },
51  { "version", no_argument, NULL, 'v' },
52  { "help", no_argument, NULL, 1 },
53  { NULL, 0, NULL, 0 }
54};
55
56/* Local functions.  */
57
58static void upusage P((void));
59static void uphelp P((void));
60
61int
62main (argc, argv)
63     int argc;
64     char **argv;
65{
66  /* -s: system name.  */
67  const char *zsystem = NULL;
68  /* -I: configuration file name.  */
69  const char *zconfig = NULL;
70  int iopt;
71  pointer puuconf;
72  int iuuconf;
73  const char *zpubdir;
74  char *zfile, *zfrom, *zfull;
75  char *zallsys;
76  char ab[1000];
77  boolean fquit;
78
79  zProgram = "uupick";
80
81  if (argc < 1)
82      upusage ();
83
84  while ((iopt = getopt_long (argc, argv, "I:s:vx:", asPlongopts,
85			      (int *) NULL)) != EOF)
86    {
87      switch (iopt)
88	{
89	case 's':
90	  /* System name to get files from.  */
91	  zsystem = optarg;
92	  break;
93
94	case 'I':
95	  /* Name configuration file.  */
96	  if (fsysdep_other_config (optarg))
97	    zconfig = optarg;
98	  break;
99
100	case 'x':
101#if DEBUG > 1
102	  /* Set debugging level.  */
103	  iDebug |= idebug_parse (optarg);
104#endif
105	  break;
106
107	case 'v':
108	  /* Print version and exit.  */
109	  printf ("uupick (Taylor UUCP) %s\n", VERSION);
110	  printf ("Copyright (C) 1991, 92, 93, 94, 1995, 2002 Ian Lance Taylor\n");
111	  printf ("This program is free software; you may redistribute it under the terms of\n");
112	  printf ("the GNU General Public LIcense.  This program has ABSOLUTELY NO WARRANTY.\n");
113	  exit (EXIT_SUCCESS);
114	  /*NOTREACHED*/
115
116	case 1:
117	  /* --help.  */
118	  uphelp ();
119	  exit (EXIT_SUCCESS);
120	  /*NOTREACHED*/
121
122	case 0:
123	  /* Long option found and flag set.  */
124	  break;
125
126	default:
127	  upusage ();
128	  /*NOTREACHED*/
129	}
130    }
131
132  if (argc != optind)
133    upusage ();
134
135  iuuconf = uuconf_init (&puuconf, (const char *) NULL, zconfig);
136  if (iuuconf != UUCONF_SUCCESS)
137    ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
138
139  usysdep_initialize (puuconf, INIT_GETCWD | INIT_NOCHDIR);
140
141  zpubdir = NULL;
142  if (zsystem != NULL)
143    {
144      struct uuconf_system ssys;
145
146      /* Get the public directory for the system.  If we can't find
147         the system information, just use the standard public
148         directory, since uupick is not setuid.  */
149      iuuconf = uuconf_system_info (puuconf, zsystem, &ssys);
150      if (iuuconf == UUCONF_SUCCESS)
151	{
152	  zpubdir = zbufcpy (ssys.uuconf_zpubdir);
153	  (void) uuconf_system_free (puuconf, &ssys);
154	}
155    }
156  if (zpubdir == NULL)
157    {
158      iuuconf = uuconf_pubdir (puuconf, &zpubdir);
159      if (iuuconf != UUCONF_SUCCESS)
160	ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
161    }
162
163  if (! fsysdep_uupick_init (zsystem, zpubdir))
164    usysdep_exit (FALSE);
165
166  zallsys = NULL;
167  fquit = FALSE;
168
169  while (! fquit
170	 && ((zfile = zsysdep_uupick (zsystem, zpubdir, &zfrom, &zfull))
171	     != NULL))
172    {
173      boolean fdir;
174      char *zto, *zlocal;
175      FILE *e;
176      boolean fcontinue;
177
178      fdir = fsysdep_directory (zfull);
179
180      do
181	{
182	  boolean fbadname;
183
184	  fcontinue = FALSE;
185
186	  if (zallsys == NULL
187	      || strcmp (zallsys, zfrom) != 0)
188	    {
189	      if (zallsys != NULL)
190		{
191		  ubuffree (zallsys);
192		  zallsys = NULL;
193		}
194
195	      printf ("from %s: %s %s ?\n", zfrom, fdir ? "dir" : "file",
196		      zfile);
197
198	      if (fgets (ab, sizeof ab, stdin) == NULL)
199		break;
200	    }
201
202	  if (ab[0] == 'q')
203	    {
204	      fquit = TRUE;
205	      break;
206	    }
207
208	  switch (ab[0])
209	    {
210	    case '\n':
211	      break;
212
213	    case 'd':
214	      if (fdir)
215		(void) fsysdep_rmdir (zfull);
216	      else
217		{
218		  if (remove (zfull) != 0)
219		    ulog (LOG_ERROR, "remove (%s): %s", zfull,
220			  strerror(errno));
221		}
222	      break;
223
224	    case 'm':
225	    case 'a':
226	      zto = ab + 1 + strspn (ab + 1, " \t");
227	      zto[strcspn (zto, " \t\n")] = '\0';
228	      zlocal = zsysdep_uupick_local_file (zto, &fbadname);
229	      if (zlocal == NULL)
230		{
231		  if (! fbadname)
232		    usysdep_exit (FALSE);
233		  ulog (LOG_ERROR, "%s: bad local file name", zto);
234		  fcontinue = TRUE;
235		  break;
236		}
237	      zto = zsysdep_in_dir (zlocal, zfile);
238	      ubuffree (zlocal);
239	      if (zto == NULL)
240		usysdep_exit (FALSE);
241	      if (! fdir)
242		upmove (zfull, zto);
243	      else
244		{
245		  usysdep_walk_tree (zfull, upmovedir, (pointer) zto);
246		  (void) fsysdep_rmdir (zfull);
247		}
248	      ubuffree (zto);
249
250	      if (ab[0] == 'a')
251		{
252		  zallsys = zbufcpy (zfrom);
253		  ab[0] = 'm';
254		}
255
256	      break;
257
258	    case 'p':
259	      if (fdir)
260		ulog (LOG_ERROR, "Can't print directory");
261	      else
262		{
263		  e = fopen (zfull, "r");
264		  if (e == NULL)
265		    ulog (LOG_ERROR, "fopen (%s): %s", zfull,
266			  strerror (errno));
267		  else
268		    {
269		      while (fgets (ab, sizeof ab, e) != NULL)
270			(void) fputs (ab, stdout);
271		      (void) fclose (e);
272		    }
273		}
274	      fcontinue = TRUE;
275	      break;
276
277	    case '!':
278	      (void) system (ab + 1);
279	      fcontinue = TRUE;
280	      break;
281
282	    default:
283	      printf ("uupick commands:\n");
284	      printf ("q: quit\n");
285	      printf ("<return>: skip file\n");
286	      printf ("m [dir]: move file to directory\n");
287	      printf ("a [dir]: move all files from this system to directory\n");
288	      printf ("p: list file to stdout\n");
289	      printf ("d: delete file\n");
290	      printf ("! command: shell escape\n");
291	      fcontinue = TRUE;
292	      break;
293	    }
294	}
295      while (fcontinue);
296
297      ubuffree (zfull);
298      ubuffree (zfrom);
299      ubuffree (zfile);
300    }
301
302  (void) fsysdep_uupick_free (zsystem, zpubdir);
303
304  usysdep_exit (TRUE);
305
306  /* Avoid error about not returning.  */
307  return 0;
308}
309
310/* Print usage message and die.  */
311
312static void
313upusage ()
314{
315  fprintf (stderr,
316	   "Usage: %s [-s system] [-I config] [-x debug]\n", zProgram);
317  fprintf (stderr, "Use %s --help for help\n", zProgram);
318  exit (EXIT_FAILURE);
319}
320
321/* Print help message.  */
322
323static void
324uphelp ()
325{
326  printf ("Taylor UUCP %s, copyright (C) 1991, 92, 93, 94, 1995, 2002 Ian Lance Taylor\n",
327	  VERSION);
328  printf (" -s,--system system: Only consider files from named system\n");
329  printf (" -x,--debug debug: Set debugging level\n");
330#if HAVE_TAYLOR_CONFIG
331  printf (" -I,--config file: Set configuration file to use\n");
332#endif /* HAVE_TAYLOR_CONFIG */
333  printf (" -v,--version: Print version and exit\n");
334  printf (" --help: Print help and exit\n");
335  printf ("Report bugs to taylor-uucp@gnu.org\n");
336}
337
338/* This routine is called by usysdep_walk_tree when moving the
339   contents of an entire directory.  */
340
341static void
342upmovedir (zfull, zrelative, pinfo)
343     const char *zfull;
344     const char *zrelative;
345     pointer pinfo;
346{
347  const char *ztodir = (const char *) pinfo;
348  char *zto;
349
350  zto = zsysdep_in_dir (ztodir, zrelative);
351  if (zto == NULL)
352    usysdep_exit (FALSE);
353  upmove (zfull, zto);
354  ubuffree (zto);
355}
356
357/* Move a file.  */
358
359static void
360upmove (zfrom, zto)
361     const char *zfrom;
362     const char *zto;
363{
364  (void) fsysdep_move_file (zfrom, zto, TRUE, TRUE, FALSE,
365			    (const char *) NULL);
366}
367