예제 #1
0
/*
 * See if the entry already exists.  If not,
 * this was an instantiated wild card, and we
 * must add it.
 */
static void
rmtab_read_wildcard(struct rmtabent *rep)
{
	nfs_export *exp, *exp2;
	struct addrinfo *ai;

	ai = host_addrinfo(rep->r_client);
	if (ai == NULL)
		return;

	exp = export_allowed(ai, rep->r_path);
	freeaddrinfo(ai);
	if (exp == NULL)
		return;

	exp2 = export_lookup(rep->r_client, exp->m_export.e_path, 0);
	if (exp2 == NULL) {
		struct exportent ee;

		memset(&ee, 0, sizeof(ee));
		dupexportent(&ee, &exp->m_export);

		ee.e_hostname = rep->r_client;
		exp2 = export_create(&ee, 0);
		exp2->m_changed = exp->m_changed;
	}
	exp2->m_mayexport = 1;
}
예제 #2
0
void *SDL_LoadFunction(void *handle, const char *name)
{
    export_sym_t *sym; 
	
    if((sym = export_lookup(name)) != NULL) {
		return (void*)sym->ptr;
	}
    else return NULL; 
}
예제 #3
0
파일: export.c 프로젝트: kouril/nfs-utils
/**
 * export_read - read entries from /etc/exports
 * @fname: name of file to read from
 *
 */
void
export_read(char *fname)
{
    struct exportent	*eep;
    nfs_export		*exp;

    setexportent(fname, "r");
    while ((eep = getexportent(0,1)) != NULL) {
        exp = export_lookup(eep->e_hostname, eep->e_path, 0);
        if (!exp)
            export_create(eep, 0);
        else
            warn_duplicated_exports(exp, eep);
    }
    endexportent();
}
예제 #4
0
파일: xtab.c 프로젝트: Distrotech/nfs-utils
static int
xtab_read(char *xtab, char *lockfn, int is_export)
{
    /* is_export == 0  => reading /proc/fs/nfs/exports - we know these things are exported to kernel
     * is_export == 1  => reading /var/lib/nfs/etab - these things are allowed to be exported
     * is_export == 2  => reading /var/lib/nfs/xtab - these things might be known to kernel
     */
	struct exportent	*xp;
	nfs_export		*exp;
	int			lockid;

	if ((lockid = xflock(lockfn, "r")) < 0)
		return 0;
	setexportent(xtab, "r");
	if (is_export == 1)
		v4root_needed = 1;
	while ((xp = getexportent(is_export==0, 0)) != NULL) {
		if (!(exp = export_lookup(xp->e_hostname, xp->e_path, is_export != 1)) &&
		    !(exp = export_create(xp, is_export!=1))) {
			continue;
		}
		switch (is_export) {
		case 0:
			exp->m_exported = 1;
			break;
		case 1:
			exp->m_xtabent = 1;
			exp->m_mayexport = 1;
			if ((xp->e_flags & NFSEXP_FSID) && xp->e_fsid == 0)
				v4root_needed = 0;
			break;
		case 2:
			exp->m_exported = -1;/* may be exported */
			break;
		}
	}
	endexportent();
	xfunlock(lockid);

	return 0;
}
예제 #5
0
static void
exportfs_parsed(char *hname, char *path, char *options, int verbose)
{
	struct exportent *eep;
	nfs_export	*exp = NULL;
	struct addrinfo	*ai = NULL;
	int		htype;

	if ((htype = client_gettype(hname)) == MCL_FQDN) {
		ai = host_addrinfo(hname);
		if (ai != NULL) {
			exp = export_find(ai, path);
			hname = ai->ai_canonname;
		}
	} else
		exp = export_lookup(hname, path, 0);

	if (!exp) {
		if (!(eep = mkexportent(hname, path, options)) ||
		    !(exp = export_create(eep, 0)))
			goto out;
	} else if (!updateexportent(&exp->m_export, options))
		goto out;

	if (verbose)
		printf("exporting %s:%s\n", exp->m_client->m_hostname,
			exp->m_export.e_path);
	exp->m_xtabent = 1;
	exp->m_mayexport = 1;
	exp->m_changed = 1;
	exp->m_warned = 0;
	validate_export(exp);

out:
	freeaddrinfo(ai);
}
예제 #6
0
/*@-mustfreefresh -mustfreeonly -branchstate -globstate@*/
int main(int argc, char **argv)
{
    int ch;
    bool daemonize = false;
    unsigned int flags = WATCH_ENABLE;
    struct exportmethod_t *method = NULL;

    progname = argv[0];

    if (export_default() == NULL) {
	(void)fprintf(stderr, "%s: no export methods.\n", progname);
	exit(1);
    }

    logfile = stdout;
    while ((ch = getopt(argc, argv, "dD:e:f:hi:lm:V")) != -1) {
	switch (ch) {
	case 'd':
	    openlog(basename(progname), LOG_PID | LOG_PERROR, LOG_DAEMON);
	    daemonize = true;
	    break;
#ifdef CLIENTDEBUG_ENABLE
	case 'D':
	    debug = atoi(optarg);
	    gps_enable_debug(debug, logfile);
	    break;
#endif /* CLIENTDEBUG_ENABLE */
	case 'e':
	    method = export_lookup(optarg);
	    if (method == NULL) {
		(void)fprintf(stderr,
			      "%s: %s is not a known export method.\n",
			      progname, optarg);
		exit(1);
	    }
	    break;
       case 'f':       /* Output file name. */
            {
                char    fname[PATH_MAX];
                time_t  t;
                size_t  s;

                t = time(NULL);
                s = strftime(fname, sizeof(fname), optarg, localtime(&t));
                if (s == 0) {
                        syslog(LOG_ERR,
                            "Bad template \"%s\", logging to stdout.", optarg);
                        break;
                }
                logfile = fopen(fname, "w");
                if (logfile == NULL)
                        syslog(LOG_ERR,
                            "Failed to open %s: %s, logging to stdout.",
                            fname, strerror(errno));
                break;
            }
	case 'i':		/* set polling interfal */
	    timeout = (time_t) atoi(optarg);
	    if (timeout < 1)
		timeout = 1;
	    if (timeout >= 3600)
		fprintf(stderr,
			"WARNING: track timeout is an hour or more!\n");
	    break;
	case 'l':
	    export_list(stderr);
	    exit(0);
        case 'm':
	    minmove = (double )atoi(optarg);
	    break;
	case 'V':
	    (void)fprintf(stderr, "%s revision " REVISION "\n", progname);
	    exit(0);
	default:
	    usage();
	    /* NOTREACHED */
	}
    }

    if (daemonize && logfile == stdout) {
	syslog(LOG_ERR, "Daemon mode with no valid logfile name - exiting.");
	exit(1);
    }

    if (method != NULL)
	if (method->magic != NULL) {
	    source.server = (char *)method->magic;
	    source.port = NULL;
	}

    if (optind < argc) {
	gpsd_source_spec(argv[optind], &source);
    } else
	gpsd_source_spec(NULL, &source);
#if 0
    (void)fprintf(logfile,"<!-- server: %s port: %s  device: %s -->\n",
		 source.server, source.port, source.device);
#endif

    /* catch all interesting signals */
    (void)signal(SIGTERM, quit_handler);
    (void)signal(SIGQUIT, quit_handler);
    (void)signal(SIGINT, quit_handler);

    /*@-unrecog@*/
    /* might be time to daemonize */
    if (daemonize) {
	/* not SuS/POSIX portable, but we have our own fallback version */
	if (daemon(0, 0) != 0)
	    (void) fprintf(stderr,"demonization failed: %s\n", strerror(errno));
    }
    /*@+unrecog@*/

    //syslog (LOG_INFO, "---------- STARTED ----------");

    if (gps_open(source.server, source.port, &gpsdata) != 0) {
	(void)fprintf(stderr,
		      "%s: no gpsd running or network error: %d, %s\n",
		      progname, errno, gps_errstr(errno));
	exit(1);
    }

    if (source.device != NULL)
	flags |= WATCH_DEVICE;
    (void)gps_stream(&gpsdata, flags, source.device);

    print_gpx_header();
    (int)gps_mainloop(&gpsdata, 5000000, conditionally_log_fix);
    print_gpx_footer();
    (void)gps_close(&gpsdata);

    exit(0);
}
예제 #7
0
/* There's a lot of shit in here that's not documented or very poorly
   documented by Intel.. I hope that this works for future compilers. */
cmd_elf_prog_t *cmd_elf_load(const char * fn) {
	uint8			*img, *imgout;
	int			sz, i, j, sect; 
	struct elf_hdr_t	*hdr;
	struct elf_shdr_t	*shdrs, *symtabhdr;
	struct elf_sym_t	*symtab;
	int			symtabsize;
	struct elf_rel_t	*reltab;
	struct elf_rela_t	*relatab;
	int			reltabsize;
	char			*stringtab;
	uint32			vma;
	file_t			fd;
	cmd_elf_prog_t *out;
	
	out = malloc(sizeof(cmd_elf_prog_t));
	memset(out, 0, sizeof(cmd_elf_prog_t));

	/* Load the file: needs to change to just load headers */
	fd = fs_open(fn, O_RDONLY);
	if (fd == FILEHND_INVALID) {
		ds_printf("DS_ERROR: Can't open input file '%s'\n", fn);
		return NULL;
	}
	sz = fs_total(fd);
	DBG(("Loading ELF file of size %d\n", sz));

	img = memalign(32, sz);
	if (img == NULL) {
		ds_printf("DS_ERROR: Can't allocate %d bytes for ELF load\n", sz);
		fs_close(fd);
		return NULL;
	}
	fs_read(fd, img, sz);
	fs_close(fd);

	/* Header is at the front */
	hdr = (struct elf_hdr_t *)(img+0);
	if (hdr->ident[0] != 0x7f || strncmp((const char*)hdr->ident+1, "ELF", 3)) {
		ds_printf("DS_ERROR: File is not a valid ELF file\n");
		hdr->ident[4] = 0;
		ds_printf("DS_ERROR: hdr->ident is %d/%s\n", hdr->ident[0], hdr->ident+1);
		goto error1;
	}
	if (hdr->ident[4] != 1 || hdr->ident[5] != 1) {
		ds_printf("DS_ERROR: Invalid architecture flags in ELF file\n");
		goto error1;
	}
	if (hdr->machine != ARCH_CODE) {
		ds_printf("DS_ERROR: Invalid architecture %02x in ELF file\n", hdr->machine);
		goto error1;
	}

	/* Print some debug info */
	DBG(("File size is %d bytes\n", sz));
	DBG(("	entry point	%08lx\n", hdr->entry));
	DBG(("	ph offset	%08lx\n", hdr->phoff));
	DBG(("	sh offset	%08lx\n", hdr->shoff));
	DBG(("	flags		%08lx\n", hdr->flags));
	DBG(("	ehsize		%08x\n", hdr->ehsize));
	DBG(("	phentsize	%08x\n", hdr->phentsize));
	DBG(("	phnum		%08x\n", hdr->phnum));
	DBG(("	shentsize	%08x\n", hdr->shentsize));
	DBG(("	shnum		%08x\n", hdr->shnum));
	DBG(("	shstrndx	%08x\n", hdr->shstrndx));

	/* Locate the string table; SH elf files ought to have
	   two string tables, one for section names and one for object
	   string names. We'll look for the latter. */
	shdrs = (struct elf_shdr_t *)(img + hdr->shoff);
	stringtab = NULL;
	for (i=0; i<hdr->shnum; i++) {
		if (shdrs[i].type == SHT_STRTAB && i != hdr->shstrndx) {
			stringtab = (char*)(img + shdrs[i].offset);
		}
	}
	if (!stringtab) {
		ds_printf("DS_ERROR: ELF contains no object string table\n");
		goto error1;
	}

	/* Locate the symbol table */
	symtabhdr = NULL;
	for (i=0; i<hdr->shnum; i++) {
		if (shdrs[i].type == SHT_SYMTAB || shdrs[i].type == SHT_DYNSYM) {
			symtabhdr = shdrs+i;
			break;
		}
	}
	if (!symtabhdr) {
		ds_printf("DS_ERROR: ELF contains no symbol table\n");
		goto error1;
	}
	symtab = (struct elf_sym_t *)(img + symtabhdr->offset);
	symtabsize = symtabhdr->size / sizeof(struct elf_sym_t);

	/* Relocate symtab entries for quick access */
	for (i=0; i<symtabsize; i++)
		symtab[i].name = (uint32)(stringtab + symtab[i].name);

	/* Build the final memory image */
	sz = 0;
	for (i=0; i<hdr->shnum; i++) {
		if (shdrs[i].flags & SHF_ALLOC) {
			shdrs[i].addr = sz;
			sz += shdrs[i].size;
			if (shdrs[i].addralign && (shdrs[i].addr % shdrs[i].addralign)) {
				uint32 orig = shdrs[i].addr;
				shdrs[i].addr = (shdrs[i].addr + shdrs[i].addralign)
					& ~(shdrs[i].addralign-1);
				sz += shdrs[i].addr - orig;
			}
		}
	}
	DBG(("Final image is %d bytes\n", sz));
	out->data = imgout = malloc(sz);
	if (out->data == NULL) {
		ds_printf("DS_ERROR: Can't allocate %d bytes for ELF program data\n", sz);
		goto error1;
	}
	out->size = sz;
	vma = (uint32)imgout;
	for (i=0; i<hdr->shnum; i++) {
		if (shdrs[i].flags & SHF_ALLOC) {
			if (shdrs[i].type == SHT_NOBITS) {
				DBG(("  setting %d bytes of zeros at %08x\n",
					shdrs[i].size, shdrs[i].addr));
				memset(imgout+shdrs[i].addr, 0, shdrs[i].size);
			}
			else {
				DBG(("  copying %d bytes from %08x to %08x\n",
					shdrs[i].size, shdrs[i].offset, shdrs[i].addr));
				memcpy(imgout+shdrs[i].addr,
					img+shdrs[i].offset,
					shdrs[i].size);
			}
		}
	}

	/* Go through and patch in any symbols that are undefined */
	for (i=1; i<symtabsize; i++) {
		export_sym_t * sym;

		/* DBG((" symbol '%s': value %04lx, size %04lx, info %02x, other %02x, shndx %04lx\n",
			(const char *)(symtab[i].name),
			symtab[i].value, symtab[i].size,
			symtab[i].info,
			symtab[i].other,
			symtab[i].shndx)); */
		if (symtab[i].shndx != SHN_UNDEF || ELF32_ST_TYPE(symtab[i].info) == STT_SECTION) {
			// DBG((" symbol '%s': skipping\n", (const char *)(symtab[i].name)));
			continue;
		}

		/* Find the symbol in our exports */
		sym = export_lookup((const char *)(symtab[i].name + ELF_SYM_PREFIX_LEN));
		if (!sym/* && strcmp((symtab[i].name + ELF_SYM_PREFIX_LEN), "start")*/) {
			ds_printf("DS_ERROR: Function '%s' is undefined. Maybe need load module?\n", (const char *)(symtab[i].name + ELF_SYM_PREFIX_LEN));
			goto error3;
		}

		/* Patch it in */
		DBG((" symbol '%s' patched to 0x%lx\n",
			(const char *)(symtab[i].name),
			sym->ptr));
		symtab[i].value = sym->ptr;
	}

	/* Process the relocations */
	reltab = NULL; relatab = NULL;
	for (i=0; i<hdr->shnum; i++) {
		if (shdrs[i].type != SHT_REL && shdrs[i].type != SHT_RELA) continue;

		sect = shdrs[i].info;
		DBG(("Relocating (%s) on section %d\n", shdrs[i].type == SHT_REL ? "SHT_REL" : "SHT_RELA", sect));

		switch (shdrs[i].type) {
		case SHT_RELA:
			relatab = (struct elf_rela_t *)(img + shdrs[i].offset);
			reltabsize = shdrs[i].size / sizeof(struct elf_rela_t);
		
			for (j=0; j<reltabsize; j++) {
				int sym;

				// XXX Does non-sh ever use RELA?
				if (ELF32_R_TYPE(relatab[j].info) != R_SH_DIR32) {
					dbglog(DBG_ERROR, "cmd_elf_load: ELF contains unknown RELA type %02x\n",
						ELF32_R_TYPE(relatab[j].info));
					goto error3;
				}

				sym = ELF32_R_SYM(relatab[j].info);
				if (symtab[sym].shndx == SHN_UNDEF) {
					DBG(("  Writing undefined RELA %08x(%08lx+%08lx) -> %08x\n",
						symtab[sym].value + relatab[j].addend,
						symtab[sym].value,
						relatab[j].addend,
						vma + shdrs[sect].addr + relatab[j].offset));
					*((uint32 *)(imgout
						+ shdrs[sect].addr
						+ relatab[j].offset))
						=	  symtab[sym].value
							+ relatab[j].addend;
				} else {
					DBG(("  Writing RELA %08x(%08x+%08x+%08x+%08x) -> %08x\n",
						vma + shdrs[symtab[sym].shndx].addr + symtab[sym].value + relatab[j].addend,
						vma, shdrs[symtab[sym].shndx].addr, symtab[sym].value, relatab[j].addend,
						vma + shdrs[sect].addr + relatab[j].offset));
					*((uint32*)(imgout
						+ shdrs[sect].addr		/* assuming 1 == .text */
						+ relatab[j].offset))
						+=	  vma
							+ shdrs[symtab[sym].shndx].addr
							+ symtab[sym].value
							+ relatab[j].addend;
				}
			}
			break;

		case SHT_REL:
			reltab = (struct elf_rel_t *)(img + shdrs[i].offset);
			reltabsize = shdrs[i].size / sizeof(struct elf_rel_t);
		
			for (j=0; j<reltabsize; j++) {
				int sym, info, pcrel;

				// XXX Does non-ia32 ever use REL?
				info = ELF32_R_TYPE(reltab[j].info);
				if (info != R_386_32 && info != R_386_PC32) {
					ds_printf("DS_ERROR: ELF contains unknown REL type %02x\n", info);
					goto error3;
				}
				pcrel = (info == R_386_PC32);

				sym = ELF32_R_SYM(reltab[j].info);
				if (symtab[sym].shndx == SHN_UNDEF) {
					uint32 value = symtab[sym].value;
					if (sect == 1 && j < 5) {
						DBG(("  Writing undefined %s %08x -> %08x",
							pcrel ? "PCREL" : "ABSREL",
							value,
							vma + shdrs[sect].addr + reltab[j].offset));
					}
					if (pcrel)
						value -= vma + shdrs[sect].addr + reltab[j].offset;

					*((uint32 *)(imgout
						+ shdrs[sect].addr
						+ reltab[j].offset))
						+= value;

					if (sect == 1 && j < 5) {
						DBG(("(%08x)\n", *((uint32 *)(imgout + shdrs[sect].addr + reltab[j].offset))));
					}
				} else {
					uint32 value = vma + shdrs[symtab[sym].shndx].addr
						+ symtab[sym].value;
					if (sect == 1 && j < 5) {
						DBG(("  Writing %s %08x(%08x+%08x+%08x) -> %08x",
							pcrel ? "PCREL" : "ABSREL",
							value,
							vma, shdrs[symtab[sym].shndx].addr, symtab[sym].value,
							vma + shdrs[sect].addr + reltab[j].offset));
					}
					if (pcrel)
						value -= vma + shdrs[sect].addr + reltab[j].offset;
					
					*((uint32*)(imgout
						+ shdrs[sect].addr
						+ reltab[j].offset))
						+= value;

					if (sect == 1 && j < 5) {
						DBG(("(%08x)\n", *((uint32 *)(imgout + shdrs[sect].addr + reltab[j].offset))));
					}
				}
			}
			break;
		
		}
	}
	if (reltab == NULL && relatab == NULL) {
		ds_printf("DS_WARNING: found no REL(A) sections; did you forget -r?\n");
	}

	/* Look for the program entry points and deal with that */
	{
		int sym;

	#define DO_ONE(symname, outp) \
		sym = find_sym(ELF_SYM_PREFIX symname, symtab, symtabsize); \
		if (sym < 0) { \
			ds_printf("DS_ERROR: ELF contains no %s()\n", symname); \
			goto error3; \
		} \
		\
		out->outp = (vma + shdrs[symtab[sym].shndx].addr \
			+ symtab[sym].value);

		DO_ONE("main", main);
		
	#undef DO_ONE
	}

	free(img);
	DBG(("elf_load final ELF stats: memory image at %p, size %08lx\n\tentry pt %p\n", out->data, out->size, out->start));
	
	/* Flush the icache for that zone */
	icache_flush_range((uint32)out->data, out->size);

	return out;

error3:
	free(out->data);

error1:
	free(img);
	return NULL;
}
예제 #8
0
파일: gpxlogger.c 프로젝트: mcb30/gpsd
int main(int argc, char **argv)
{
    int ch;
    bool daemonize = false;
    unsigned int flags = WATCH_ENABLE;
    struct exportmethod_t *method = NULL;

    progname = argv[0];

    method = export_default();
    if (method == NULL) {
	(void)fprintf(stderr, "%s: no export methods.\n", progname);
	exit(EXIT_FAILURE);
    }

    logfile = stdout;
    while ((ch = getopt(argc, argv, "dD:e:f:hi:lm:V")) != -1) {
	switch (ch) {
	case 'd':
	    openlog(basename(progname), LOG_PID | LOG_PERROR, LOG_DAEMON);
	    daemonize = true;
	    break;
#ifdef CLIENTDEBUG_ENABLE
	case 'D':
	    debug = atoi(optarg);
	    gps_enable_debug(debug, logfile);
	    break;
#endif /* CLIENTDEBUG_ENABLE */
	case 'e':
	    method = export_lookup(optarg);
	    if (method == NULL) {
		(void)fprintf(stderr,
			      "%s: %s is not a known export method.\n",
			      progname, optarg);
		exit(EXIT_FAILURE);
	    }
	    break;
       case 'f':       /* Output file name. */
            {
                char   *fname = NULL;
                time_t  t;
                size_t  s = 0;
                size_t fnamesize = strlen(optarg);

                t = time(NULL);
                while (s == 0) {
		    char *newfname = realloc(fname, fnamesize);
		    if (newfname == NULL) {
			syslog(LOG_ERR, "realloc failed.");
			goto bailout;
		    } else {
			fnamesize += 1024;
			fname = newfname;
		    }
		    s = strftime(fname, fnamesize-1, optarg, localtime(&t));
                }
                fname[s] = '\0';;
                logfile = fopen(fname, "w");
                if (logfile == NULL)
		    syslog(LOG_ERR,
			   "Failed to open %s: %s, logging to stdout.",
			   fname, strerror(errno));
	    bailout:
                free(fname);
                break;
            }
	case 'i':		/* set polling interfal */
	    timeout = (time_t) atoi(optarg);
	    if (timeout < 1)
		timeout = 1;
	    if (timeout >= 3600)
		fprintf(stderr,
			"WARNING: track timeout is an hour or more!\n");
	    break;
	case 'l':
	    export_list(stderr);
	    exit(EXIT_SUCCESS);
        case 'm':
	    minmove = (double )atoi(optarg);
	    break;
	case 'V':
	    (void)fprintf(stderr, "%s: version %s (revision %s)\n",
			  progname, VERSION, REVISION);
	    exit(EXIT_SUCCESS);
	default:
	    usage();
	    /* NOTREACHED */
	}
    }

    if (daemonize && logfile == stdout) {
	syslog(LOG_ERR, "Daemon mode with no valid logfile name - exiting.");
	exit(EXIT_FAILURE);
    }

    if (method->magic != NULL) {
	source.server = (char *)method->magic;
	source.port = NULL;
	source.device = NULL;
    } else {
	source.server = (char *)"localhost";
	source.port = (char *)DEFAULT_GPSD_PORT;
	source.device = NULL;
    }

    if (optind < argc) {
	/* in this case, switch to the method "socket" always */
	gpsd_source_spec(argv[optind], &source);
    }
#if 0
    (void)fprintf(logfile,"<!-- server: %s port: %s  device: %s -->\n",
		 source.server, source.port, source.device);
#endif

    /* catch all interesting signals */
    (void)signal(SIGTERM, quit_handler);
    (void)signal(SIGQUIT, quit_handler);
    (void)signal(SIGINT, quit_handler);

    /* might be time to daemonize */
    if (daemonize) {
	/* not SuS/POSIX portable, but we have our own fallback version */
	if (daemon(0, 0) != 0)
	    (void) fprintf(stderr,"demonization failed: %s\n", strerror(errno));
    }

    //syslog (LOG_INFO, "---------- STARTED ----------");

    if (gps_open(source.server, source.port, &gpsdata) != 0) {
	(void)fprintf(stderr,
		      "%s: no gpsd running or network error: %d, %s\n",
		      progname, errno, gps_errstr(errno));
	exit(EXIT_FAILURE);
    }

    if (source.device != NULL)
	flags |= WATCH_DEVICE;
    (void)gps_stream(&gpsdata, flags, source.device);

    print_gpx_header();
    (void)gps_mainloop(&gpsdata, 5000000, conditionally_log_fix);
    print_gpx_footer();
    (void)gps_close(&gpsdata);

    exit(EXIT_SUCCESS);
}