gpsd.c

来自「gpsd, a popular GPS daemon.」· C语言 代码 · 共 1,824 行 · 第 1/4 页

C
1,824
字号
		    (void)strlcat(phrase, " ?", BUFSIZ);		if (isnan(sub->fixbuffer.altitude)==0)		    (void)snprintf(phrase+strlen(phrase),				   sizeof(phrase)-strlen(phrase),				   " %.2f",				   sub->fixbuffer.altitude);		else		    (void)strlcat(phrase, " ?", BUFSIZ);		if (isnan(sub->fixbuffer.eph)==0)		    (void)snprintf(phrase+strlen(phrase),				   sizeof(phrase)-strlen(phrase),				  " %.2f",  sub->fixbuffer.eph);		else		    (void)strlcat(phrase, " ?", BUFSIZ);		if (isnan(sub->fixbuffer.epv)==0)		    (void)snprintf(phrase+strlen(phrase),				   sizeof(phrase)-strlen(phrase),				   " %.2f",  sub->fixbuffer.epv);		else		    (void)strlcat(phrase, " ?", BUFSIZ);		if (isnan(sub->fixbuffer.track)==0)		    (void)snprintf(phrase+strlen(phrase),				   sizeof(phrase)-strlen(phrase),				   " %.4f %.3f",				   sub->fixbuffer.track,				   sub->fixbuffer.speed);		else		    (void)strlcat(phrase, " ? ?", BUFSIZ);		if (isnan(sub->fixbuffer.climb)==0)		    (void)snprintf(phrase+strlen(phrase),				   sizeof(phrase)-strlen(phrase),				   " %.3f",				   sub->fixbuffer.climb);		else		    (void)strlcat(phrase, " ?", BUFSIZ);		if (isnan(sub->fixbuffer.epd)==0)		    (void)snprintf(phrase+strlen(phrase),				   sizeof(phrase)-strlen(phrase),				   " %.4f",				   sub->fixbuffer.epd);		else		    (void)strlcat(phrase, " ?", BUFSIZ);		if (isnan(sub->fixbuffer.eps)==0)		    (void)snprintf(phrase+strlen(phrase),			     sizeof(phrase)-strlen(phrase),			     " %.2f", sub->fixbuffer.eps);		else		    (void)strlcat(phrase, " ?", BUFSIZ);		if (isnan(sub->fixbuffer.epc)==0)		    (void)snprintf(phrase+strlen(phrase),			     sizeof(phrase)-strlen(phrase),			     " %.2f", sub->fixbuffer.epc);		else		    (void)strlcat(phrase, " ?", BUFSIZ);		if (sub->fixbuffer.mode > 0)		    (void)snprintf(phrase+strlen(phrase),			     sizeof(phrase)-strlen(phrase),			     " %d", sub->fixbuffer.mode);		else		    (void)strlcat(phrase, " ?", BUFSIZ);	    }	    break;	case 'P':	    if (assign_channel(sub) && have_fix(sub))		(void)snprintf(phrase, sizeof(phrase), ",P=%.6f %.6f",			sub->fixbuffer.latitude,			sub->fixbuffer.longitude);	    else		(void)strlcpy(phrase, ",P=?", BUFSIZ);	    break;	case 'Q':#define ZEROIZE(x)	(isnan(x)!=0 ? 0.0 : x)	    if (assign_channel(sub) &&		(isnan(sub->device->gpsdata.pdop)==0		 || isnan(sub->device->gpsdata.hdop)==0		 || isnan(sub->device->gpsdata.vdop)==0))		(void)snprintf(phrase, sizeof(phrase), ",Q=%d %.2f %.2f %.2f %.2f %.2f",			sub->device->gpsdata.satellites_used,			ZEROIZE(sub->device->gpsdata.pdop),			ZEROIZE(sub->device->gpsdata.hdop),			ZEROIZE(sub->device->gpsdata.vdop),			ZEROIZE(sub->device->gpsdata.tdop),			ZEROIZE(sub->device->gpsdata.gdop));	    else		(void)strlcpy(phrase, ",Q=?", BUFSIZ);#undef ZEROIZE	    break;	case 'R':	    if (*p == '=') ++p;	    if (*p == '2') {		(void)assign_channel(sub);		sub->raw = 2;		gpsd_report(LOG_INF, "client(%d) turned on super-raw mode\n", sub_index(sub));		(void)snprintf(phrase, sizeof(phrase), ",R=2");		p++;	    } else if (*p == '1' || *p == '+') {		(void)assign_channel(sub);		sub->raw = 1;		gpsd_report(LOG_INF, "client(%d) turned on raw mode\n", sub_index(sub));		(void)snprintf(phrase, sizeof(phrase), ",R=1");		p++;	    } else if (*p == '0' || *p == '-') {		sub->raw = 0;		gpsd_report(LOG_INF, "client(%d) turned off raw mode\n", sub_index(sub));		(void)snprintf(phrase, sizeof(phrase), ",R=0");		p++;	    } else if (sub->raw) {		sub->raw = 0;		gpsd_report(LOG_INF, "client(%d) turned off raw mode\n", sub_index(sub));		(void)snprintf(phrase, sizeof(phrase), ",R=0");	    } else {		(void)assign_channel(sub);		sub->raw = 1;		gpsd_report(LOG_INF, "client(%d) turned on raw mode\n", sub_index(sub));		(void)snprintf(phrase, sizeof(phrase), ",R=1");	    }	    break;	case 'S':	    if (assign_channel(sub))		(void)snprintf(phrase, sizeof(phrase), ",S=%d", sub->device->gpsdata.status);	    else		(void)strlcpy(phrase, ",S=?", BUFSIZ);	    break;	case 'T':	    if (assign_channel(sub) && have_fix(sub) && isnan(sub->fixbuffer.track)==0)		(void)snprintf(phrase, sizeof(phrase), ",T=%.4f", sub->fixbuffer.track);	    else		(void)strlcpy(phrase, ",T=?", BUFSIZ);	    break;	case 'U':	    if (assign_channel(sub) && have_fix(sub) && sub->fixbuffer.mode == MODE_3D)		(void)snprintf(phrase, sizeof(phrase), ",U=%.3f", sub->fixbuffer.climb);	    else		(void)strlcpy(phrase, ",U=?", BUFSIZ);	    break;	case 'V':	    if (assign_channel(sub) && have_fix(sub) && isnan(sub->fixbuffer.speed)==0)		(void)snprintf(phrase, sizeof(phrase), ",V=%.3f", sub->fixbuffer.speed * MPS_TO_KNOTS);	    else		(void)strlcpy(phrase, ",V=?", BUFSIZ);	    break;	case 'W':	    if (*p == '=') ++p;	    if (*p == '1' || *p == '+') {		sub->watcher = true;		(void)assign_channel(sub);		(void)snprintf(phrase, sizeof(phrase), ",W=1");		p++;	    } else if (*p == '0' || *p == '-') {		sub->watcher = false;		(void)snprintf(phrase, sizeof(phrase), ",W=0");		p++;	    } else if (sub->watcher!=0) {		sub->watcher = false;		(void)snprintf(phrase, sizeof(phrase), ",W=0");	    } else {		sub->watcher = true;		(void)assign_channel(sub);		gpsd_report(LOG_INF, "client(%d) turned on watching\n", sub_index(sub));		(void)snprintf(phrase, sizeof(phrase), ",W=1");	    }	    break;	case 'X':	    if (assign_channel(sub) && sub->device != NULL)		(void)snprintf(phrase, sizeof(phrase), ",X=%f", sub->device->gpsdata.online);	    else		(void)strlcpy(phrase, ",X=?", BUFSIZ);	    break;	case 'Y':	    if (assign_channel(sub) && sub->device->gpsdata.satellites > 0) {		int used, reported = 0;		(void)strlcpy(phrase, ",Y=", BUFSIZ);		if (sub->device->gpsdata.tag[0] != '\0')		    (void)strlcat(phrase, sub->device->gpsdata.tag, BUFSIZ);		else		    (void)strlcat(phrase, "-", BUFSIZ);		if (isnan(sub->device->gpsdata.sentence_time)==0)		    (void)snprintf(phrase+strlen(phrase),				   sizeof(phrase)-strlen(phrase),				   " %.3f ",				   sub->device->gpsdata.sentence_time);		else		    (void)strlcat(phrase, " ? ", BUFSIZ);		/* insurance against flaky drivers */		for (i = 0; i < sub->device->gpsdata.satellites; i++)		    if (sub->device->gpsdata.PRN[i])			reported++;		(void)snprintf(phrase+strlen(phrase),			       sizeof(phrase)-strlen(phrase),			       "%d:", reported);		for (i = 0; i < sub->device->gpsdata.satellites; i++) {		    used = 0;		    for (j = 0; j < sub->device->gpsdata.satellites_used; j++)			if (sub->device->gpsdata.used[j] == sub->device->gpsdata.PRN[i]) {			    used = 1;			    break;			}		    if (sub->device->gpsdata.PRN[i]) {			(void)snprintf(phrase+strlen(phrase),				      sizeof(phrase)-strlen(phrase),				      "%d %d %d %d %d:",				      sub->device->gpsdata.PRN[i],				      sub->device->gpsdata.elevation[i],sub->device->gpsdata.azimuth[i],				      sub->device->gpsdata.ss[i],				      used);		    }		}		if (sub->device->gpsdata.satellites != reported)		    gpsd_report(LOG_WARN,"Satellite count %d != PRN count %d\n",				sub->device->gpsdata.satellites, reported);	    } else		(void)strlcpy(phrase, ",Y=?", BUFSIZ);	    break;	case 'Z':	    (void)assign_channel(sub);	    if (*p == '=') ++p;	    if (sub->device == NULL) {		(void)snprintf(phrase, sizeof(phrase), ",Z=?");		p++;	    } else if (*p == '1' || *p == '+') {		sub->device->gpsdata.profiling = true;		gpsd_report(LOG_INF, "client(%d) turned on profiling mode\n", sub_index(sub));		(void)snprintf(phrase, sizeof(phrase), ",Z=1");		p++;	    } else if (*p == '0' || *p == '-') {		sub->device->gpsdata.profiling = false;		gpsd_report(LOG_INF, "client(%d) turned off profiling mode\n", sub_index(sub));		(void)snprintf(phrase, sizeof(phrase), ",Z=0");		p++;	    } else {		sub->device->gpsdata.profiling = !sub->device->gpsdata.profiling;		gpsd_report(LOG_INF, "client(%d) toggled profiling mode\n", sub_index(sub));		(void)snprintf(phrase, sizeof(phrase), ",Z=%d",			       (int)sub->device->gpsdata.profiling);	    }	    break;	case '$':	    if (!assign_channel(sub))		(void)strlcpy(phrase, ",$=?", BUFSIZ);	    else if (sub->device->gpsdata.sentence_time!=0)		(void)snprintf(phrase, sizeof(phrase), ",$=%s %d %lf %lf %lf %lf %lf %lf",			sub->device->gpsdata.tag,			(int)sub->device->gpsdata.sentence_length,			sub->device->gpsdata.sentence_time,			sub->device->gpsdata.d_xmit_time - sub->device->gpsdata.sentence_time,			sub->device->gpsdata.d_recv_time - sub->device->gpsdata.sentence_time,			sub->device->gpsdata.d_decode_time - sub->device->gpsdata.sentence_time,			sub->device->poll_times[sub_index(sub)] - sub->device->gpsdata.sentence_time,			timestamp() - sub->device->gpsdata.sentence_time);	    else		(void)snprintf(phrase, sizeof(phrase), ",$=%s %d 0 %lf %lf %lf %lf %lf",			sub->device->gpsdata.tag,			(int)sub->device->gpsdata.sentence_length,			sub->device->gpsdata.d_xmit_time,			sub->device->gpsdata.d_recv_time - sub->device->gpsdata.d_xmit_time,			sub->device->gpsdata.d_decode_time - sub->device->gpsdata.d_xmit_time,			sub->device->poll_times[sub_index(sub)] - sub->device->gpsdata.d_xmit_time,			timestamp() - sub->device->gpsdata.d_xmit_time);	    break;	case '\r': case '\n':	    goto breakout;	}	if (strlen(reply) + strlen(phrase) < sizeof(reply) - 1)	    (void)strlcat(reply, phrase, BUFSIZ);	else	    return -1;	/* Buffer would overflow.  Just return an error */    } breakout:    (void)strlcat(reply, "\r\n", BUFSIZ);    return (int)throttled_write(sub, reply, (ssize_t)strlen(reply));}static void handle_control(int sfd, char *buf)/* handle privileged commands coming through the control socket */{    char	*p, *stash, *eq;    struct gps_device_t	*chp;    int cfd;    if (buf[0] == '-') {	p = snarfline(buf+1, &stash);	gpsd_report(LOG_INF, "<= control(%d): removing %s\n", sfd, stash);	if ((chp = find_device(stash))) {	    if (chp->gpsdata.gps_fd > 0) {		FD_CLR(chp->gpsdata.gps_fd, &all_fds);		adjust_max_fd(chp->gpsdata.gps_fd, false);	    }	    notify_watchers(chp, "X=0\r\n");	    for (cfd = 0; cfd < MAXSUBSCRIBERS; cfd++)		if (subscribers[cfd].device == chp)		    subscribers[cfd].device = NULL;	    gpsd_wrap(chp);	    chp->gpsdata.gps_fd = -1;	/* device is already disconnected */	    /*@i@*/free_channel(chp);	/* modifying observer storage */	    (void)write(sfd, "OK\n", 3);	} else	    (void)write(sfd, "ERROR\n", 6);    } else if (buf[0] == '+') {	p = snarfline(buf+1, &stash);	if (find_device(stash)) {	    gpsd_report(LOG_INF,"<= control(%d): %s already active \n", sfd, stash);		(void)write(sfd, "ERROR\n", 6);	} else {	    gpsd_report(LOG_INF,"<= control(%d): adding %s \n", sfd, stash);	    if (open_device(stash))		(void)write(sfd, "OK\n", 3);	    else		(void)write(sfd, "ERROR\n", 6);	}    } else if (buf[0] == '!') {	p = snarfline(buf+1, &stash);	eq = strchr(stash, '=');	if (eq == NULL) {	    gpsd_report(LOG_WARN,"<= control(%d): ill-formed command \n", sfd);	    (void)write(sfd, "ERROR\n", 3);	} else {	    *eq++ = '\0';	    if ((chp = find_device(stash))) {		gpsd_report(LOG_INF,"<= control(%d): writing to %s \n", sfd, stash);		(void)write(chp->gpsdata.gps_fd, eq, strlen(eq));		(void)write(sfd, "OK\n", 3);	    } else {		gpsd_report(LOG_INF,"<= control(%d): %s not active \n", sfd, stash);		(void)write(sfd, "ERROR\n", 6);	    }	}    }}/*@ -mustfreefresh @*/int main(int argc, char *argv[]){    static char *pid_file = NULL;    static int st, csock = -1;    static gps_mask_t changed;    static char *gpsd_service = NULL;#ifdef RTCM104_SERVICE    static char *rtcm_service = NULL;    static int nsock;#endif /* RTCM104_SERVICE */    static char *control_socket = NULL;    struct gps_device_t *channel;    struct sockaddr_in fsin;    fd_set rfds, control_fds;    int i, option, msock, cfd, dfd;    bool go_background = true;    struct timeval tv;#ifdef RTCM104_SERVICE    struct gps_device_t *gps;#endif /* RTCM104_SERVICE */    struct subscriber_t *sub;#ifdef PPS_ENABLE    pthread_mutex_init(&report_mutex, NULL);#endif /* PPS_ENABLE */#ifdef HAVE_SETLOCALE    (void)setlocale(LC_NUMERIC, "C");#endif    debuglevel = 0;    while ((option = getopt(argc, argv, "F:D:S:bhNnP:V"#ifdef RTCM104_SERVICE			    "R:"#endif /* RTCM104_SERVICE */		)) != -1) {	switch (option) {	case 'D':	    debuglevel = (int) strtol(optarg, 0, 0);	    break;	case 'F':	    control_socket = optarg;	    break;	case 'N':	    go_background = false;	    break;	case 'b':	    context.readonly = true;	    break;#ifdef RTCM104_SERVICE	case 'R':	    rtcm_service = optarg;	    break;#endif /* RTCM104_SERVICE */	case 'S':	    gpsd_service = optarg;	    break;	case 'n':	    nowait = true;	    break;	case 'P':	    pid_file = optarg;	    break;	case 'V':	    (void)printf("gpsd %s\n", VERSION);	    exit(0);	case 'h': case '?':	default:	    usage();	    exit(0);	}    }#ifdef FIXED_PORT_SPEED    /* Asssume that if we're running with FIXED_PORT_SPEED we're some sort     * of embedded configuration where we don't want to wait for connect */    nowait = true;#endif    if (!control_socket && optind >= argc) {	gpsd_report(LOG_ERROR, "can't run with neither control socket nor devices\n");	exit(1);    }    /*     * Control socket has to be created before we go background in order to     * avoid a race condition in which hotplug scripts can try opening     * the socket before it's created.     */    if (control_socket) {	(void)unlink(control_socket);	if ((csock = filesock(control_socket)) < 0) {	    gpsd_report(LOG_ERROR,"control socket create failed, netlib error %d\n",csock);	    exit(2);	}	FD_SET(csock, &all_fds);	adjust_max_fd(csock, true);	gpsd_report(LOG_PROG, "control socket opened at %s\n", control_socket);    }    if (go_background)	(void)daemonize();    if (pid_file) {	FILE *fp;	if ((fp = fopen(pid_file, "w")) != NULL) {	    (void)fprintf(fp, "%u\n", (unsigned int)getpid());	    (void)fclose(fp);	} else {	    gpsd_report(LOG_ERROR, "Cannot create PID file: %s.\n", pid_file);	}    }    openlog("gpsd", LOG_PID, LOG_USER);    gpsd_report(LOG_INF, "launching (Version %s)\n", VERSION);    /*@ -observertrans @*/    if (!gpsd_service)	gpsd_service = getservbyname("gpsd", "tcp") ? "gpsd" : DEFAULT_GPSD_PORT;    /*@ +observertrans @*/    if ((msock = passivesock(gpsd_service, "tcp", QLEN)) < 0) {	gpsd_report(LOG_ERR,"command socket create failed, netlib error %d\n",msock);	exit(2);    }    gpsd_report(LOG_INF, "listening on port %s\n", gpsd_service);#ifdef RTCM104_SERVICE

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?