~ubuntu-branches/ubuntu/natty/ntop/natty

« back to all changes in this revision

Viewing changes to ntop_darwin.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2005-01-30 21:59:13 UTC
  • mfrom: (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20050130215913-xc3ke963bw49b3k4
Tags: 2:3.0-5
* Updated README.Debian file so users will understand what to do at
  install, closes: #291794, #287802.
* Updated ntop init script to give better output.
* Also changed log directory from /var/lib/ntop to /var/log/ntop,
  closes: #252352.
* Quoted the interface list to allow whitespace, closes: #267248.
* Added a couple of logcheck ignores, closes: #269321, #269319.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2001-04  Luca Deri <deri@ntop.org>
 
3
 *
 
4
 *                         http://www.ntop.org/
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
19
 */
 
20
 
 
21
/* 
 
22
   This file contains some compatibility functions that are needed for
 
23
   ntop to run on Darwin/MacOS X
 
24
*/
 
25
 
 
26
#ifdef DARWIN
 
27
 
 
28
/* ***************************************************************** */
 
29
 
 
30
/*
 
31
 * This file was modified by Christoph Pfisterer <cp@chrisp.de>
 
32
 * on Tue, Jan 23 2001. See the file "ChangeLog" for details of what
 
33
 * was changed.
 
34
 *
 
35
 *
 
36
 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
 
37
 *
 
38
 * @APPLE_LICENSE_HEADER_START@
 
39
 * 
 
40
 * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
 
41
 * Reserved.  This file contains Original Code and/or Modifications of
 
42
 * Original Code as defined in and that are subject to the Apple Public
 
43
 * Source License Version 1.1 (the "License").  You may not use this file
 
44
 * except in compliance with the License.  Please obtain a copy of the
 
45
 * License at http://www.apple.com/publicsource and read it before using
 
46
 * this file.
 
47
 * 
 
48
 * The Original Code and all software distributed under the License are
 
49
 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 
50
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 
51
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 
52
 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
 
53
 * License for the specific language governing rights and limitations
 
54
 * under the License.
 
55
 * 
 
56
 * @APPLE_LICENSE_HEADER_END@
 
57
 */
 
58
#include <stdio.h>
 
59
#include <stdlib.h>
 
60
#include <string.h>
 
61
#include <errno.h>
 
62
#include <sys/types.h>
 
63
#include <sys/stat.h>
 
64
#include <limits.h>
 
65
#include "mach-o/dyld.h"
 
66
#include "ntop_darwin.h"
 
67
 
 
68
/*
 
69
 * debugging macros
 
70
 */
 
71
#if DEBUG > 0
 
72
#define DEBUG_PRINT(format) fprintf(stderr,(format));fflush(stderr)
 
73
#define DEBUG_PRINT1(format,arg1) fprintf(stderr,(format),(arg1));\
 
74
  fflush(stderr)
 
75
#define DEBUG_PRINT2(format,arg1,arg2) fprintf(stderr,(format),\
 
76
  (arg1),(arg2));fflush(stderr)
 
77
#define DEBUG_PRINT3(format,arg1,arg2,arg3) fprintf(stderr,(format),\
 
78
  (arg1),(arg2),(arg3));fflush(stderr)
 
79
#else
 
80
#define DEBUG_PRINT(format) /**/
 
81
#define DEBUG_PRINT1(format,arg1) /**/
 
82
#define DEBUG_PRINT2(format,arg1,arg2) /**/
 
83
#define DEBUG_PRINT3(format,arg1,arg2,arg3) /**/
 
84
#undef DEBUG
 
85
#endif
 
86
 
 
87
/*
 
88
 * The structure of a dlopen() handle.
 
89
 */
 
90
struct dlopen_handle {
 
91
    dev_t dev;          /* the path's device and inode number from stat(2) */
 
92
    ino_t ino; 
 
93
    int dlopen_mode;    /* current dlopen mode for this handle */
 
94
    int dlopen_count;   /* number of times dlopen() called on this handle */
 
95
    NSModule module;    /* the NSModule returned by NSLinkModule() */
 
96
    struct dlopen_handle *prev;
 
97
    struct dlopen_handle *next;
 
98
};
 
99
static struct dlopen_handle *dlopen_handles = NULL;
 
100
static const struct dlopen_handle main_program_handle = {NULL};
 
101
static char *dlerror_pointer = NULL;
 
102
 
 
103
/*
 
104
 * NSMakePrivateModulePublic() is not part of the public dyld API so we define
 
105
 * it here.  The internal dyld function pointer for
 
106
 * __dyld_NSMakePrivateModulePublic is returned so thats all that maters to get
 
107
 * the functionality need to implement the dlopen() interfaces.
 
108
 */
 
109
static int NSMakePrivateModulePublic(NSModule module)
 
110
{
 
111
  static NSModule *p;
 
112
 
 
113
  if(p == NULL)
 
114
    _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", (unsigned long *)&p);
 
115
 
 
116
  if(p == NULL) {
 
117
#ifdef DEBUG
 
118
    printf("_dyld_func_lookup of __dyld_NSMakePrivateModulePublic "
 
119
           "failed\n");
 
120
#endif
 
121
    return(FALSE);
 
122
  } else
 
123
    return(TRUE);
 
124
}
 
125
 
 
126
/*
 
127
 * helper routine: search for a named module in various locations
 
128
 */
 
129
static
 
130
int
 
131
_dl_search_paths(
 
132
const char *filename,
 
133
char *pathbuf,
 
134
struct stat *stat_buf)
 
135
{
 
136
    const char *pathspec;
 
137
    const char *element;
 
138
    const char *p;
 
139
    char *q;
 
140
    char *pathbuf_end;
 
141
    const char *envvars[] = {
 
142
        "$DYLD_LIBRARY_PATH",
 
143
        "$LD_LIBRARY_PATH",
 
144
        "/usr/lib:/lib",
 
145
        NULL };
 
146
    int envvar_index;
 
147
 
 
148
        pathbuf_end = pathbuf + PATH_MAX - 8;
 
149
 
 
150
        for(envvar_index = 0; envvars[envvar_index]; envvar_index++) {
 
151
            if(envvars[envvar_index][0] == '$') {
 
152
                pathspec = getenv(envvars[envvar_index]+1);
 
153
            }
 
154
            else {
 
155
                pathspec = envvars[envvar_index];
 
156
            }
 
157
 
 
158
            if(pathspec != NULL) {
 
159
                element = pathspec;
 
160
                while(*element) {
 
161
                    /* extract path list element */
 
162
                    p = element;
 
163
                    q = pathbuf;
 
164
                    while(*p && *p != ':' && q < pathbuf_end) *q++ = *p++;
 
165
                    if(q == pathbuf) {  /* empty element */
 
166
                        if(*p) {
 
167
                            element = p+1;
 
168
                            continue;
 
169
                        }
 
170
                        break;
 
171
                    }
 
172
                    if (*p) {
 
173
                        element = p+1;
 
174
                    }
 
175
                    else{
 
176
                        element = p;  /* this terminates the loop */
 
177
                    }
 
178
 
 
179
                    /* add slash if neccessary */
 
180
                    if(*(q-1) != '/' && q < pathbuf_end) {
 
181
                        *q++ = '/';
 
182
                    }
 
183
 
 
184
                    /* append module name */
 
185
                    p = filename;
 
186
                    while(*p && q < pathbuf_end) *q++ = *p++;
 
187
                    *q++ = 0;
 
188
 
 
189
                    if(q >= pathbuf_end) {
 
190
                        /* maybe add an error message here */
 
191
                        break;
 
192
                    }
 
193
 
 
194
                    if(stat(pathbuf, stat_buf) == 0) {
 
195
                        return 0;
 
196
                    }
 
197
                }
 
198
            }
 
199
        }
 
200
 
 
201
        /* we have searched everywhere, now we give up */
 
202
        return -1;
 
203
}
 
204
 
 
205
/*
 
206
 * dlopen() the MacOS X version of the FreeBSD dlopen() interface.
 
207
 */
 
208
void* dlopen(const char *path, int mode)
 
209
{
 
210
    const char *module_path;
 
211
    void *retval;
 
212
    struct stat stat_buf;
 
213
    NSObjectFileImage objectFileImage;
 
214
    NSObjectFileImageReturnCode ofile_result_code;
 
215
    NSModule module;
 
216
    struct dlopen_handle *p;
 
217
    unsigned long options;
 
218
    NSSymbol NSSymbol;
 
219
    void (*init)(void);
 
220
    char pathbuf[PATH_MAX];
 
221
 
 
222
        DEBUG_PRINT2("libdl: dlopen(%s,0x%x) -> ", path, (unsigned int)mode);
 
223
 
 
224
        dlerror_pointer = NULL;
 
225
        /*
 
226
         * A NULL path is to indicate the caller wants a handle for the
 
227
         * main program.
 
228
         */
 
229
        if(path == NULL) {
 
230
            retval = (void *)&main_program_handle;
 
231
            DEBUG_PRINT1("main / %p\n", retval);
 
232
            return(retval);
 
233
        }
 
234
 
 
235
        /* see if the path exists and if so get the device and inode number */
 
236
        if(stat(path, &stat_buf) == -1) {
 
237
            dlerror_pointer = strerror(errno);
 
238
 
 
239
            if(path[0] == '/') {
 
240
                DEBUG_PRINT1("ERROR (stat): %s\n", dlerror_pointer);
 
241
                return(NULL);
 
242
            }
 
243
 
 
244
            /* search for the module in various places */
 
245
            if(_dl_search_paths(path, pathbuf, &stat_buf)) {
 
246
                /* dlerror_pointer is unmodified */
 
247
                DEBUG_PRINT1("ERROR (stat): %s\n", dlerror_pointer);
 
248
                return(NULL);
 
249
            }
 
250
            DEBUG_PRINT1("found %s -> ", pathbuf);
 
251
            module_path = pathbuf;
 
252
            dlerror_pointer = NULL;
 
253
        }
 
254
        else{
 
255
            module_path = path;
 
256
        }
 
257
 
 
258
        /*
 
259
         * If we don't want an unshared handle see if we already have a handle
 
260
         * for this path.
 
261
         */
 
262
        if((mode & RTLD_UNSHARED) != RTLD_UNSHARED) {
 
263
            p = dlopen_handles;
 
264
            while(p != NULL) {
 
265
                if(p->dev == stat_buf.st_dev && p->ino == stat_buf.st_ino) {
 
266
                    /* skip unshared handles */
 
267
                    if((p->dlopen_mode & RTLD_UNSHARED) == RTLD_UNSHARED)
 
268
                        continue;
 
269
                    /*
 
270
                     * We have already created a handle for this path.  The
 
271
                     * caller might be trying to promote an RTLD_LOCAL handle
 
272
                     * to a RTLD_GLOBAL.  Or just looking it up with
 
273
                     * RTLD_NOLOAD.
 
274
                     */
 
275
                    if((p->dlopen_mode & RTLD_LOCAL) == RTLD_LOCAL &&
 
276
                       (mode & RTLD_GLOBAL) == RTLD_GLOBAL) {
 
277
                        /* promote the handle */
 
278
                        if(NSMakePrivateModulePublic(p->module) == TRUE) {
 
279
                            p->dlopen_mode &= ~RTLD_LOCAL;
 
280
                            p->dlopen_mode |= RTLD_GLOBAL;
 
281
                            p->dlopen_count++;
 
282
                            DEBUG_PRINT1("%p\n", p);
 
283
                            return(p);
 
284
                        }
 
285
                        else{
 
286
                            dlerror_pointer = "can't promote handle from "
 
287
                                              "RTLD_LOCAL to RTLD_GLOBAL";
 
288
                            DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
 
289
                            return(NULL);
 
290
                        }
 
291
                    }
 
292
                    p->dlopen_count++;
 
293
                    DEBUG_PRINT1("%p\n", p);
 
294
                    return(p);
 
295
                }
 
296
                p = p->next;
 
297
            }
 
298
        }
 
299
        
 
300
        /*
 
301
         * We do not have a handle for this path if we were just trying to
 
302
         * look it up return NULL to indicate we don't have it.
 
303
         */
 
304
        if((mode & RTLD_NOLOAD) == RTLD_NOLOAD) {
 
305
            dlerror_pointer = "no existing handle for path RTLD_NOLOAD test";
 
306
            DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
 
307
            return(NULL);
 
308
        }
 
309
 
 
310
        /* try to create an object file image from this path */
 
311
        ofile_result_code = NSCreateObjectFileImageFromFile(module_path,
 
312
                                                            &objectFileImage);
 
313
        if(ofile_result_code != NSObjectFileImageSuccess) {
 
314
            switch(ofile_result_code) {
 
315
            case NSObjectFileImageFailure:
 
316
                dlerror_pointer = "object file setup failure";
 
317
                DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
 
318
                return(NULL);
 
319
            case NSObjectFileImageInappropriateFile:
 
320
                dlerror_pointer = "not a Mach-O MH_BUNDLE file type";
 
321
                DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
 
322
                return(NULL);
 
323
            case NSObjectFileImageArch:
 
324
                dlerror_pointer = "no object for this architecture";
 
325
                DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
 
326
                return(NULL);
 
327
            case NSObjectFileImageFormat:
 
328
                dlerror_pointer = "bad object file format";
 
329
                DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
 
330
                return(NULL);
 
331
            case NSObjectFileImageAccess:
 
332
                dlerror_pointer = "can't read object file";
 
333
                DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
 
334
                return(NULL);
 
335
            default:
 
336
                dlerror_pointer = "unknown error from "
 
337
                                  "NSCreateObjectFileImageFromFile()";
 
338
                DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
 
339
                return(NULL);
 
340
            }
 
341
        }
 
342
 
 
343
        /* try to link in this object file image */
 
344
        options = NSLINKMODULE_OPTION_PRIVATE;
 
345
        if((mode & RTLD_NOW) == RTLD_NOW)
 
346
            options |= NSLINKMODULE_OPTION_BINDNOW;
 
347
        module = NSLinkModule(objectFileImage, module_path, options);
 
348
        NSDestroyObjectFileImage(objectFileImage) ;
 
349
        if(module == NULL) {
 
350
            dlerror_pointer = "NSLinkModule() failed for dlopen()";
 
351
            DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
 
352
            return(NULL);
 
353
        }
 
354
 
 
355
        /*
 
356
         * If the handle is to be global promote the handle.  It is done this
 
357
         * way to avoid multiply defined symbols.
 
358
         */
 
359
        if((mode & RTLD_GLOBAL) == RTLD_GLOBAL) {
 
360
            if(NSMakePrivateModulePublic(module) == FALSE) {
 
361
                dlerror_pointer = "can't promote handle from RTLD_LOCAL to "
 
362
                                  "RTLD_GLOBAL";
 
363
                DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
 
364
                return(NULL);
 
365
            }
 
366
        }
 
367
 
 
368
        p = malloc(sizeof(struct dlopen_handle));
 
369
        if(p == NULL) {
 
370
            dlerror_pointer = "can't allocate memory for the dlopen handle";
 
371
            DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
 
372
            return(NULL);
 
373
        }
 
374
 
 
375
        /* fill in the handle */
 
376
        p->dev = stat_buf.st_dev;
 
377
        p->ino = stat_buf.st_ino;
 
378
        if(mode & RTLD_GLOBAL)
 
379
            p->dlopen_mode = RTLD_GLOBAL;
 
380
        else
 
381
            p->dlopen_mode = RTLD_LOCAL;
 
382
        p->dlopen_mode |= (mode & RTLD_UNSHARED) |
 
383
                          (mode & RTLD_NODELETE) |
 
384
                          (mode & RTLD_LAZY_UNDEF);
 
385
        p->dlopen_count = 1;
 
386
        p->module = module;
 
387
        p->prev = NULL;
 
388
        p->next = dlopen_handles;
 
389
        if(dlopen_handles != NULL)
 
390
            dlopen_handles->prev = p;
 
391
        dlopen_handles = p;
 
392
 
 
393
        /* call the init function if one exists */
 
394
        NSSymbol = NSLookupSymbolInModule(p->module, "__init");
 
395
        if(NSSymbol != NULL) {
 
396
            init = NSAddressOfSymbol(NSSymbol);
 
397
            init();
 
398
        }
 
399
        
 
400
        DEBUG_PRINT1("%p\n", p);
 
401
        return(p);
 
402
}
 
403
 
 
404
/*
 
405
 * dlsym() the MacOS X version of the FreeBSD dlopen() interface.
 
406
 */
 
407
void* dlsym(void * handle, const char *symbol) {
 
408
    struct dlopen_handle *dlopen_handle, *p;
 
409
    NSSymbol nsSymbol;
 
410
    void *address;
 
411
 
 
412
        DEBUG_PRINT2("libdl: dlsym(%p,%s) -> ", handle, symbol);
 
413
 
 
414
        dlopen_handle = (struct dlopen_handle *)handle;
 
415
 
 
416
        /*
 
417
         * If this is the handle for the main program do a global lookup.
 
418
         */
 
419
        if(dlopen_handle == (struct dlopen_handle *)&main_program_handle) {
 
420
            if(NSIsSymbolNameDefined(symbol) == TRUE) {
 
421
                nsSymbol = NSLookupAndBindSymbol(symbol);
 
422
                address = NSAddressOfSymbol(nsSymbol);
 
423
                dlerror_pointer = NULL;
 
424
                DEBUG_PRINT1("%p\n", address);
 
425
                return(address);
 
426
            }
 
427
            else{
 
428
                dlerror_pointer = "symbol not found";
 
429
                DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
 
430
                return(NULL);
 
431
            }
 
432
        }
 
433
 
 
434
        /*
 
435
         * Find this handle and do a lookup in just this module.
 
436
         */
 
437
        p = dlopen_handles;
 
438
        while(p != NULL) {
 
439
            if(dlopen_handle == p) {
 
440
                nsSymbol = NSLookupSymbolInModule(p->module, symbol);
 
441
                if(nsSymbol != NULL) {
 
442
                    address = NSAddressOfSymbol(nsSymbol);
 
443
                    dlerror_pointer = NULL;
 
444
                    DEBUG_PRINT1("%p\n", address);
 
445
                    return(address);
 
446
                }
 
447
                else{
 
448
                    dlerror_pointer = "symbol not found";
 
449
                    DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
 
450
                    return(NULL);
 
451
                }
 
452
            }
 
453
            p = p->next;
 
454
        }
 
455
 
 
456
        dlerror_pointer = "bad handle passed to dlsym()";
 
457
        DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
 
458
        return(NULL);
 
459
}
 
460
 
 
461
/*
 
462
 * dlerror() the MacOS X version of the FreeBSD dlopen() interface.
 
463
 */
 
464
const char *
 
465
dlerror(
 
466
void)
 
467
{
 
468
    const char *p;
 
469
 
 
470
        p = (const char *)dlerror_pointer;
 
471
        dlerror_pointer = NULL;
 
472
        return(p);
 
473
}
 
474
 
 
475
/*
 
476
 * dlclose() the MacOS X version of the FreeBSD dlopen() interface.
 
477
 */
 
478
int
 
479
dlclose(
 
480
void * handle)
 
481
{
 
482
    struct dlopen_handle *p, *q;
 
483
    unsigned long options;
 
484
    NSSymbol nsSymbol;
 
485
    void (*fini)(void);
 
486
 
 
487
        DEBUG_PRINT1("libdl: dlclose(%p) -> ", handle);
 
488
 
 
489
        dlerror_pointer = NULL;
 
490
        q = (struct dlopen_handle *)handle;
 
491
        p = dlopen_handles;
 
492
        while(p != NULL) {
 
493
            if(p == q) {
 
494
                /* if the dlopen() count is not zero we are done */
 
495
                p->dlopen_count--;
 
496
                if(p->dlopen_count != 0) {
 
497
                    DEBUG_PRINT("OK");
 
498
                    return(0);
 
499
                }
 
500
 
 
501
                /* call the fini function if one exists */
 
502
                nsSymbol = NSLookupSymbolInModule(p->module, "__fini");
 
503
                if(nsSymbol != NULL) {
 
504
                    fini = NSAddressOfSymbol(nsSymbol);
 
505
                    fini();
 
506
                }
 
507
 
 
508
                /* unlink the module for this handle */
 
509
                options = 0;
 
510
                if(p->dlopen_mode & RTLD_NODELETE)
 
511
                    options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
 
512
                if(p->dlopen_mode & RTLD_LAZY_UNDEF)
 
513
                    options |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
 
514
                if(NSUnLinkModule(p->module, options) == FALSE) {
 
515
                    dlerror_pointer = "NSUnLinkModule() failed for dlclose()";
 
516
                    DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
 
517
                    return(-1);
 
518
                }
 
519
                if(p->prev != NULL)
 
520
                    p->prev->next = p->next;
 
521
                if(p->next != NULL)
 
522
                    p->next->prev = p->prev;
 
523
                if(dlopen_handles == p)
 
524
                    dlopen_handles = p->next;
 
525
                free(p);
 
526
                DEBUG_PRINT("OK");
 
527
                return(0);
 
528
            }
 
529
            p = p->next;
 
530
        }
 
531
        dlerror_pointer = "invalid handle passed to dlclose()";
 
532
        DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
 
533
        return(-1);
 
534
}
 
535
 
 
536
/* ***************************************************************** */
 
537
 
 
538
#endif