Coverage Report

Created: 2026-06-13 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpsd/gpsd-3.27.6~dev/libgps/libgps_core.c
Line
Count
Source
1
/* libgps_core.c -- client interface library for the gpsd daemon
2
 *
3
 * Core portion of client library.  Cals helpers to handle different eports.
4
 *
5
 * This file is Copyright by the GPSD project
6
 * SPDX-License-Identifier: BSD-2-clause
7
 */
8
9
#include "../include/gpsd_config.h"   // must be before all includes
10
11
#include <ctype.h>
12
#include <errno.h>
13
#include <fcntl.h>                    // open()
14
#include <stdarg.h>
15
#include <stdbool.h>
16
#include <stdio.h>
17
#include <stdlib.h>
18
#include <string.h>
19
#include <unistd.h>
20
21
#include "../include/gpsd.h"
22
#include "../include/libgps.h"
23
#include "../include/gps_json.h"
24
#include "../include/strfuncs.h"
25
26
int libgps_debuglevel = 0;
27
FILE *debugfp = NULL;
28
29
// control the level and destination of debug trace messages
30
void gps_enable_debug(int level, FILE * fp)
31
0
{
32
0
    libgps_debuglevel = level;
33
0
    debugfp = fp;
34
0
    json_enable_debug(level - DEBUG_JSON, fp);
35
0
}
36
37
/* assemble command in printf(3) style
38
 * do not call directly, us libgps_debug_trace()
39
 */
40
// HOTCODE!  Do not change without profiling.
41
void libgps_trace(const char *fmt, ...)
42
0
{
43
0
    va_list ap;
44
45
0
    va_start(ap, fmt);
46
0
    vfprintf(debugfp, fmt, ap);
47
0
    va_end(ap);
48
0
}
49
50
#define CONDITIONALLY_UNUSED UNUSED
51
52
/* gps_open(host,) -- open a connection for reading from gpsd
53
 *
54
 * host can be:
55
 *     a host name or host ip - to connect to host
56
 *        port is numeric or symbolic port to connect to
57
 *     GPSD_DBUS_EXPORT "DBUS export"     - to connect to local DBUS
58
 *     GPSD_FILE_LOCAL "local file"       - to read to local file
59
 *        port is file name to open
60
 *     GPSD_SHARED_MEMORY "shared memory" - to connect to local chared memory
61
 *
62
 * Return: 0 osnuccess
63
 *         less than zero on failure
64
 */
65
int gps_open(const char *host, const char *port,
66
             struct gps_data_t *gpsdata)
67
0
{
68
0
    int status = -100;
69
70
0
    errno = 0;
71
0
    if (!gpsdata) {
72
0
        return NL_NOHOST;
73
0
    }
74
75
    // save for later
76
0
    gpsdata->source.server = host;
77
0
    gpsdata->source.port = port;
78
79
0
    if (NULL != host &&
80
0
        0 == strcmp(host, GPSD_LOCAL_FILE)) {
81
0
        intptr_t fd;
82
83
0
        libgps_debug_trace(DEBUG_CALLS, "libgps: INFO: gps_open%sILE)\n",
84
0
                            host);
85
0
        if (NULL == port) {
86
0
            libgps_debug_trace(DEBUG_CALLS,
87
0
                               "libgps: ERROR: gps_open(%s) missing port\n",
88
0
                               host);
89
0
            return FILE_FAIL;
90
0
        }
91
0
        fd = open(port, O_RDONLY);
92
0
        if (0 > fd) {
93
0
            libgps_debug_trace(DEBUG_CALLS, "libgps: ERROR: gps_open(%s) %d\n",
94
0
                                port,  errno);
95
0
            return FILE_FAIL;
96
0
        }
97
0
        gpsdata->gps_fd = (gps_fd_t)fd;
98
0
        status = 0;
99
        // set up for line-buffered I/O over the daemon socket
100
0
        gpsdata->privdata =
101
0
            (struct privdata_t *)calloc(1, sizeof(struct privdata_t));
102
0
        if (NULL == gpsdata->privdata) {
103
0
            return -1;
104
0
        }
105
0
    }
106
0
#ifdef SHM_EXPORT_ENABLE
107
0
    else if (NULL != host &&
108
0
        0 == strcmp(host, GPSD_SHARED_MEMORY)) {
109
0
        status = gps_shm_open(gpsdata);
110
0
        if (0 != status) {
111
0
            if (-2 == status ) {
112
0
                return SHM_NOATTACH;
113
0
            }
114
0
            if (-3 == status ) {
115
0
                return SHM_CALLOC;
116
0
            }
117
            // -1, or other error
118
0
            return SHM_NOSHARED;
119
0
        }
120
0
    }
121
0
#define USES_HOST
122
0
#endif  // SHM_EXPORT_ENABLE
123
124
#ifdef DBUS_EXPORT_ENABLE
125
    else if (NULL != host &&
126
        0 == strcmp(host, GPSD_DBUS_EXPORT)) {
127
        status = gps_dbus_open(gpsdata);
128
        if (0 != status ) {
129
            return DBUS_FAILURE;
130
        }
131
    }
132
#define USES_HOST
133
#endif  // DBUS_EXPORT_ENABLE
134
135
0
    else {
136
        // last shot, try host:port
137
0
        status = gps_sock_open(host, port, gpsdata);
138
0
    }
139
0
#define USES_HOST
140
141
#ifndef USES_HOST
142
    if (NULL == host) {
143
        // Should not happen, but this pacifies Codacy
144
        (void)fprintf(stderr,
145
             "No methods available for connecting to NULL == host!\n");
146
    } else {
147
        (void)fprintf(stderr,
148
                      "No methods available for connecting to %s!\n", host);
149
    }
150
#endif  // USES_HOST
151
0
#undef USES_HOST
152
153
0
    gpsdata->set = 0;
154
0
    gpsdata->satellites_used = 0;
155
0
    gps_clear_att(&(gpsdata->attitude));
156
0
    gps_clear_dop(&(gpsdata->dop));
157
0
    gps_clear_fix(&(gpsdata->fix));
158
0
    gps_clear_gst(&(gpsdata->gst));
159
0
    gps_clear_log(&(gpsdata->log));
160
161
0
    return status;
162
0
}
163
164
// close a gpsd connection
165
int gps_close(struct gps_data_t *gpsdata CONDITIONALLY_UNUSED)
166
0
{
167
0
    int status = -1;
168
169
0
    libgps_debug_trace(DEBUG_CALLS, "%s", "libgps: gps_close()\n");
170
171
0
#ifdef SHM_EXPORT_ENABLE
172
0
    if (BAD_SOCKET((intptr_t)(gpsdata->gps_fd))) {
173
0
        gps_shm_close(gpsdata);
174
0
        status = 0;
175
0
    }
176
0
#endif  // SHM_EXPORT_ENABLE
177
178
0
    if (-1 == status ) {
179
0
        status = gps_sock_close(gpsdata);
180
0
    }
181
182
0
    return status;
183
0
}
184
185
/* wait for and read data from the daemon or file
186
 *
187
 * parameters:
188
 *    gps_data_t *gpsdata   -- structure for GPS data
189
 *    char *message         -- NULL, or optional buffer for received JSON
190
 *    int message_len       -- zero, or sizeof(message)
191
 *
192
 * Return:
193
 *    -1 == error
194
 *    -2 == EOF
195
 *    zero OK
196
 */
197
int gps_read(struct gps_data_t *gpsdata, char *message, int message_len)
198
0
{
199
0
    int status = -1;
200
201
0
    libgps_debug_trace(DEBUG_CALLS, "%s",  "libgps: gps_read() begins\n");
202
0
    if ((NULL != message) &&
203
0
        (0 < message_len)) {
204
        // be sure message is zero length
205
        // we do not memset() as this is time critical input path
206
0
        *message = '\0';
207
0
    }
208
0
    if (NULL == PRIVATE(gpsdata)) {
209
0
        char err[] = "gps_read() NULL == privdata";
210
0
        libgps_debug_trace(DEBUG_CALLS, "libgps: %s\n", err);
211
0
        strlcpy(gpsdata->error, err, sizeof(gpsdata->error));
212
0
        gpsdata->set = ERROR_SET;
213
0
        return -1;
214
0
    }
215
216
0
    if (NULL != gpsdata->source.server &&
217
0
        0 == strcmp(gpsdata->source.server, GPSD_LOCAL_FILE)) {
218
        // local file read
219
0
        char *eol, *eptr;
220
0
        ssize_t read_ret, message_len;
221
222
0
        errno = 0;
223
224
        // scan to find end of message (\n), or end of buffer
225
0
        eol = PRIVATE(gpsdata)->buffer;
226
227
        // fill the buffer
228
0
#if !defined(USE_QT)
229
        // Coverity takes the first branch, we want this checked.
230
0
        eptr = eol + PRIVATE(gpsdata)->waiting;
231
0
        read_ret = read(gpsdata->gps_fd, eptr,
232
0
                        sizeof(PRIVATE(gpsdata)->buffer) -
233
0
                        PRIVATE(gpsdata)->waiting - 1);
234
#else
235
        read_ret = -1;  // TBD
236
#endif
237
0
        if (0 >= read_ret) {
238
0
            int ret;
239
240
            // EOL, or error
241
0
            if ( 0 == read_ret) {
242
0
                strlcpy(gpsdata->error, "EOF", sizeof(gpsdata->error));
243
0
                ret = -2;
244
0
            } else {
245
0
                strlcpy(gpsdata->error, "ERROR", sizeof(gpsdata->error));
246
0
                ret = -1;
247
0
            }
248
0
            gpsdata->set = ERROR_SET;
249
0
            libgps_debug_trace(DEBUG_CALLS, "libgps: %s\n", gpsdata->error);
250
0
            return ret;
251
0
        }
252
0
        gpsdata->set &= ~PACKET_SET;
253
0
        PRIVATE(gpsdata)->waiting += read_ret;
254
0
        eptr = eol + PRIVATE(gpsdata)->waiting;
255
256
0
        while ((eptr > eol) &&
257
0
               ('\n' != *eol)) {
258
0
            eol++;
259
0
        }
260
261
0
        if (eol >= eptr) {
262
            /* Buffer is full but still didn't get a message.
263
             * discard and try again. */
264
0
            libgps_debug_trace(DEBUG_CALLS, "%s",
265
0
                                "libgps: gps_read() buffer full, "
266
0
                                "but no message\n");
267
0
            PRIVATE(gpsdata)->buffer[0] = '\0';
268
0
            PRIVATE(gpsdata)->waiting = 0;
269
0
            return -1;
270
0
        }
271
        /* else  have a full message in buffer
272
         * eol now points to trailing \n in a full message */
273
0
        *eol = '\0';
274
        /* why the 1?  We want the NUL.
275
         *          |0|1|2|3|4|5| 6|7|
276
         *          |1|2|3|4|5|6|\n|X|
277
         *     buffer^         eol^
278
         *  buffer = 0
279
         *  eol = 6
280
         *  eol-buffer = 6-0 = 6, size of the line data is 7 bytes with \n
281
         *  eol-buffer+1 = 6-0+1 = 7
282
         */
283
0
        message_len = 1 + eol - PRIVATE(gpsdata)->buffer;
284
285
0
        if (NULL != message) {
286
            // user wants a copy, including NUL
287
0
            memcpy(message, PRIVATE(gpsdata)->buffer, message_len);
288
0
        }
289
0
        (void)clock_gettime(CLOCK_REALTIME, &gpsdata->online);
290
        // unpack the JSON message
291
0
        status = gps_unpack(PRIVATE(gpsdata)->buffer, gpsdata);
292
293
        // calculate length of good data still in buffer
294
0
        PRIVATE(gpsdata)->waiting -= message_len;
295
296
0
        if (0 >= PRIVATE(gpsdata)->waiting) {
297
            // no waiting data, or overflow, clear the buffer, just in case
298
0
            *PRIVATE(gpsdata)->buffer = '\0';
299
0
            PRIVATE(gpsdata)->waiting = 0;
300
0
        } else {
301
            // shift the remaining data to the front.
302
0
            memmove(PRIVATE(gpsdata)->buffer,
303
0
                    PRIVATE(gpsdata)->buffer + message_len,
304
0
                    PRIVATE(gpsdata)->waiting);
305
0
        }
306
0
        gpsdata->set |= PACKET_SET;
307
0
#ifdef SHM_EXPORT_ENABLE
308
0
    } else if (BAD_SOCKET((intptr_t)(gpsdata->gps_fd))) {
309
0
        status = gps_shm_read(gpsdata);
310
0
#endif  // SHM_EXPORT_ENABLE
311
312
0
    } else if (-1 == status &&
313
0
        !BAD_SOCKET((intptr_t)(gpsdata->gps_fd))) {
314
0
        status = gps_sock_read(gpsdata, message, message_len);
315
0
    }
316
317
0
    libgps_debug_trace(DEBUG_CALLS, "libgps: gps_read() -> %d (%s)\n",
318
0
                        status, gps_maskdump(gpsdata->set));
319
320
0
    return status;
321
0
}
322
323
/* send a command to the gpsd instance
324
 *
325
 * Return: 0 -- success
326
 * Return: negative -- fail
327
 */
328
int gps_send(struct gps_data_t *gpsdata CONDITIONALLY_UNUSED,
329
             const char *fmt CONDITIONALLY_UNUSED, ...)
330
0
{
331
0
    int status = -1;
332
0
    char buf[BUFSIZ];
333
0
    va_list ap;
334
335
0
    va_start(ap, fmt);
336
0
    (void)vsnprintf(buf, sizeof(buf) - 2, fmt, ap);
337
0
    va_end(ap);
338
    // codacy deos not like strlen()
339
0
    if ('\n' != buf[strnlen(buf, sizeof(buf)) - 1]) {
340
0
        (void)strlcat(buf, "\n", sizeof(buf));
341
0
    }
342
343
0
    status = gps_sock_send(gpsdata, buf);
344
345
0
    return status;
346
0
}
347
348
/* setup a stream
349
 *
350
 * FIXME: works on socket streams, but not on shared memory stream.
351
 *
352
 * Return: 0 -- success
353
 * Return: negative -- fail
354
 */
355
int gps_stream(struct gps_data_t *gpsdata, watch_t flags,
356
        const char *d CONDITIONALLY_UNUSED)
357
0
{
358
0
    int status = -1;
359
360
0
    if (NULL != gpsdata->source.server &&
361
0
        0 == strcmp(gpsdata->source.server, GPSD_LOCAL_FILE)) {
362
        // lodal cile, read-only
363
0
        flags |= WATCH_READONLY;
364
0
    }
365
0
    gpsdata->watch = flags;
366
0
    if (WATCH_READONLY & flags) {
367
        // read only
368
0
        return 0;
369
0
    }
370
0
    status = gps_sock_stream(gpsdata, flags, d);
371
372
0
    return status;
373
0
}
374
375
// return the contents of the client data buffer
376
const char *gps_data(const struct gps_data_t *gpsdata CONDITIONALLY_UNUSED)
377
0
{
378
0
    const char *bufp = NULL;
379
380
0
    bufp = gps_sock_data(gpsdata);
381
382
0
    return bufp;
383
0
}
384
385
/* is there input waiting from the GPS?
386
 * timeout is in uSec
387
 */
388
bool gps_waiting(const struct gps_data_t *gpsdata,
389
                 int timeout CONDITIONALLY_UNUSED)
390
0
{
391
    // this is bogus, but I can't think of a better solution yet
392
0
    bool waiting = true;
393
394
0
    if (NULL != gpsdata->source.server &&
395
0
        0 == strcmp(gpsdata->source.server, GPSD_LOCAL_FILE)) {
396
        // always ready, until EOF
397
0
        return true;
398
0
    }
399
0
#ifdef SHM_EXPORT_ENABLE
400
0
    if (SHM_PSEUDO_FD == (intptr_t)(gpsdata->gps_fd)) {
401
0
        waiting = gps_shm_waiting(gpsdata, timeout);
402
0
        return waiting;
403
0
    }
404
0
#endif  // SHM_EXPORT_ENABLE
405
406
0
    if (0 <= (intptr_t)(gpsdata->gps_fd)) {
407
0
        waiting = gps_sock_waiting(gpsdata, timeout);
408
0
    }
409
410
0
    return waiting;
411
0
}
412
413
/* run a main loop with a specified handler
414
 *
415
 * Returns: -1 on timeout or read error
416
 *          -2 read error
417
 * FIXME: read error should return different than timeout
418
 */
419
int gps_mainloop(struct gps_data_t *gpsdata CONDITIONALLY_UNUSED,
420
                 int timeout CONDITIONALLY_UNUSED,
421
                 void (*hook)(struct gps_data_t *gpsdata) CONDITIONALLY_UNUSED)
422
0
{
423
0
    int status = -1;
424
425
0
    libgps_debug_trace(DEBUG_CALLS, "%s", "libgps: gps_mainloop() begins\n");
426
427
0
#ifdef SHM_EXPORT_ENABLE
428
0
    if (SHM_PSEUDO_FD == (intptr_t)(gpsdata->gps_fd)) {
429
0
        libgps_debug_trace(DEBUG_CALLS, "%s",
430
0
                           "libgps: gps_shm_mainloop() begins\n");
431
0
        status = gps_shm_mainloop(gpsdata, timeout, hook);
432
0
    }
433
0
#endif  // SHM_EXPORT_ENABLE
434
#ifdef DBUS_EXPORT_ENABLE
435
    if (DBUS_PSEUDO_FD == (intptr_t)(gpsdata->gps_fd)) {
436
        libgps_debug_trace(DEBUG_CALLS, "%s",
437
                           "libgps: gps_dbus_mainloop() begins\n");
438
        status = gps_dbus_mainloop(gpsdata, timeout, hook);
439
    }
440
#endif  // DBUS_EXPORT_ENABLE
441
0
    if (0 <= (intptr_t)(gpsdata->gps_fd)) {
442
0
        libgps_debug_trace(DEBUG_CALLS, "%s",
443
0
                           "libgps: gps_sock_mainloop() begins\n");
444
0
        status = gps_sock_mainloop(gpsdata, timeout, hook);
445
0
    }
446
447
0
    libgps_debug_trace(DEBUG_CALLS, "libgps: gps_mainloop() -> %d (%s)\n",
448
0
                        status, gps_maskdump(gpsdata->set));
449
450
0
    return status;
451
0
}
452
453
extern const char *gps_errstr(const int err)
454
0
{
455
    /*
456
     * We might add our own error codes in the future, e.g for
457
     * protocol compatibility checks
458
     */
459
#ifdef USE_QT
460
    static char buf[32];
461
462
    (void)snprintf(buf, sizeof(buf), "Qt error %d", err);
463
    return buf;
464
#else   // USE_QT
465
0
    switch (err) {
466
0
    case SHM_NOSHARED:
467
0
        return "no shared-memory segment or daemon not running";
468
0
    case SHM_NOATTACH:
469
0
        return "attach failed for unknown reason";
470
0
    case DBUS_FAILURE:
471
0
        return "DBUS initialization failure";
472
0
    case FILE_FAIL:
473
0
        return "failed to open file";
474
0
    case SHM_CALLOC:
475
0
        return "calloc() failed";
476
0
    default:
477
0
        return netlib_errstr(err);
478
0
    }
479
0
#endif  // USE_QT
480
0
}
481
482
void libgps_dump_state(struct gps_data_t *collect)
483
0
{
484
0
    char ts_buf[TIMESPEC_LEN];
485
486
    // no need to dump the entire state, this is a sanity check
487
0
#ifndef USE_QT
488
0
    (void)fprintf(debugfp, "flags: (0x%04x) %s\n",
489
0
                  (unsigned int)collect->set, gps_maskdump(collect->set));
490
0
#endif
491
0
    if (ONLINE_SET & collect->set) {
492
0
        (void)fprintf(debugfp, "ONLINE: %s\n",
493
0
                      timespec_str(&collect->online, ts_buf, sizeof(ts_buf)));
494
0
    }
495
0
    if (TIME_SET & collect->set) {
496
0
        (void)fprintf(debugfp, "TIME: %s\n",
497
0
                     timespec_str(&collect->fix.time, ts_buf, sizeof(ts_buf)));
498
0
    }
499
    // NOTE: %.7f needed for cm level accurate GPS
500
0
    if (LATLON_SET & collect->set) {
501
0
        (void)fprintf(debugfp, "LATLON: lat/lon: %.7lf %.7lf\n",
502
0
                      collect->fix.latitude, collect->fix.longitude);
503
0
    }
504
0
    if (ALTITUDE_SET & collect->set) {
505
0
        (void)fprintf(debugfp, "ALTITUDE: altHAE: %lf  U: climb: %lf\n",
506
0
                      collect->fix.altHAE, collect->fix.climb);
507
0
    }
508
0
    if (SPEED_SET & collect->set) {
509
0
        (void)fprintf(debugfp, "SPEED: %lf\n", collect->fix.speed);
510
0
    }
511
0
    if (TRACK_SET & collect->set) {
512
0
        (void)fprintf(debugfp, "TRACK: track: %lf\n", collect->fix.track);
513
0
    }
514
0
    if (MAGNETIC_TRACK_SET & collect->set) {
515
0
        (void)fprintf(debugfp, "MAGNETIC_TRACK: magtrack: %lf\n",
516
0
                      collect->fix.magnetic_track);
517
0
    }
518
0
    if (CLIMB_SET & collect->set) {
519
0
        (void)fprintf(debugfp, "CLIMB: climb: %lf\n", collect->fix.climb);
520
0
    }
521
0
    if (STATUS_SET & collect->set) {
522
0
        (void)fprintf(debugfp, "STATUS: status: %d (%s)\n",
523
0
                      collect->fix.status,
524
0
                      val2str(collect->fix.status, vstatus_str));
525
0
    }
526
0
    if (MODE_SET & collect->set) {
527
0
        (void)fprintf(debugfp, "MODE: mode: %d (%s)\n",
528
0
                      collect->fix.mode,
529
0
                      val2str(collect->fix.mode, vmode_str));
530
0
    }
531
0
    if (DOP_SET & collect->set) {
532
0
        (void)fprintf(debugfp,
533
0
                      "DOP: satellites %d gdop %f hdop %f pdop %f tdop %f "
534
0
                      "vdop %f xdop %f ydop %f\n",
535
0
                      collect->satellites_used,
536
0
                      collect->dop.gdop,
537
0
                      collect->dop.hdop,
538
0
                      collect->dop.pdop,
539
0
                      collect->dop.tdop,
540
0
                      collect->dop.vdop,
541
0
                      collect->dop.xdop,
542
0
                      collect->dop.ydop);
543
0
    }
544
0
    if (VERSION_SET & collect->set) {
545
0
        (void)fprintf(debugfp, "VERSION: release=%s rev=%s proto=%d.%d\n",
546
0
                      collect->version.release,
547
0
                      collect->version.rev,
548
0
                      collect->version.proto_major,
549
0
                      collect->version.proto_minor);
550
0
    }
551
0
    if (POLICY_SET & collect->set) {
552
0
        (void)fprintf(debugfp,
553
0
                      "POLICY: watcher=%s nmea=%s raw=%d scaled=%s timing=%s, "
554
0
                      "split24=%s pps=%s, devpath=%s\n",
555
0
                      collect->policy.watcher ? "true" : "false",
556
0
                      collect->policy.nmea ? "true" : "false",
557
0
                      collect->policy.raw,
558
0
                      collect->policy.scaled ? "true" : "false",
559
0
                      collect->policy.timing ? "true" : "false",
560
0
                      collect->policy.split24 ? "true" : "false",
561
0
                      collect->policy.pps ? "true" : "false",
562
0
                      collect->policy.devpath);
563
0
    }
564
0
    if (SATELLITE_SET & collect->set) {
565
0
        struct satellite_t *sp;
566
567
0
        if (MAXCHANNELS < collect->satellites_visible) {
568
0
            collect->satellites_visible = MAXCHANNELS;
569
0
        }
570
0
        (void)fprintf(debugfp, "SKY: satellites in view: %d\n",
571
0
                      collect->satellites_visible);
572
0
        for (sp = collect->skyview;
573
0
             sp < collect->skyview + collect->satellites_visible;
574
0
             sp++) {
575
0
            (void)fprintf(debugfp, "  %2.2d: %4.1f %5.1f %3.0f %c\n",
576
0
                          sp->PRN, sp->elevation,
577
0
                          sp->azimuth, sp->ss,
578
0
                          sp->used ? 'Y' : 'N');
579
0
        }
580
0
    }
581
0
    if (RAW_SET & collect->set) {
582
0
        (void)fprintf(debugfp, "RAW: got raw data\n");
583
0
    }
584
0
    if (DEVICE_SET & collect->set) {
585
0
        (void)fprintf(debugfp, "DEVICE: Device is '%s', driver is '%s'\n",
586
0
                      collect->dev.path, collect->dev.driver);
587
0
    }
588
0
    if (DEVICELIST_SET & collect->set) {
589
0
        unsigned  i;
590
0
        (void)fprintf(debugfp, "DEVICELIST:%d devices:\n",
591
0
                      collect->devices.ndevices);
592
0
        for (i = 0; i < collect->devices.ndevices; i++) {
593
0
            (void)fprintf(debugfp, "%d: path='%s' driver='%s'\n",
594
0
                          collect->devices.ndevices,
595
0
                          collect->devices.list[i].path,
596
0
                          collect->devices.list[i].driver);
597
0
        }
598
0
    }
599
0
}
600
601
// vim: set expandtab shiftwidth=4