1/***
2  This file is part of avahi.
3
4  avahi is free software; you can redistribute it and/or modify it
5  under the terms of the GNU Lesser General Public License as
6  published by the Free Software Foundation; either version 2.1 of the
7  License, or (at your option) any later version.
8
9  avahi is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12  Public License for more details.
13
14  You should have received a copy of the GNU Lesser General Public
15  License along with avahi; if not, write to the Free Software
16  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17  USA.
18***/
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24#include <pthread.h>
25#include <unistd.h>
26#include <limits.h>
27#include <stdio.h>
28#include <string.h>
29#include <stdlib.h>
30#include <assert.h>
31#include <stdarg.h>
32#include <syslog.h>
33
34#include "warn.h"
35
36#ifndef COMPAT_LAYER
37#define COMPAT_LAYER "Apple Bonjour"
38#endif
39
40#ifndef CGI_SUBSYSTEM
41#define CGI_SUBSYSTEM "libdns_sd"
42#endif
43
44static pthread_mutex_t linkage_mutex = PTHREAD_MUTEX_INITIALIZER;
45static int linkage_warning = 0;
46
47const char *avahi_exe_name(void) {
48#ifdef HAVE_GETPROGNAME
49    return getprogname();
50#elif defined(__linux__)
51    static char exe_name[1024] = "";
52    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
53
54    /* Yes, I know, this is not portable. But who cares? It's for
55     * cosmetics only, anyway. */
56
57    pthread_mutex_lock(&mutex);
58
59    if (exe_name[0] == 0) {
60        int k;
61
62        if ((k = readlink("/proc/self/exe", exe_name, sizeof(exe_name)-1)) < 0)
63            snprintf(exe_name, sizeof(exe_name), "(unknown)");
64        else {
65            char *slash;
66
67            assert((size_t) k <= sizeof(exe_name)-1);
68            exe_name[k] = 0;
69
70            if ((slash = strrchr(exe_name, '/')))
71                memmove(exe_name, slash+1, strlen(slash)+1);
72        }
73    }
74
75    pthread_mutex_unlock(&mutex);
76
77    return exe_name;
78#else
79#ifdef __GNUC__
80#warning "avahi_exe_name() needs to be implemented for your operating system"
81#endif
82    return "(unknown)";
83#endif
84}
85
86void avahi_warn(const char *fmt, ...) {
87    char msg[512]  = "*** WARNING *** ";
88    va_list ap;
89    size_t n;
90
91    assert(fmt);
92
93    va_start(ap, fmt);
94    n = strlen(msg);
95    vsnprintf(msg + n, sizeof(msg) - n, fmt, ap);
96    va_end(ap);
97
98    fprintf(stderr, "%s\n", msg);
99
100    openlog(avahi_exe_name(), LOG_PID, LOG_USER);
101    syslog(LOG_WARNING, "%s", msg);
102    closelog();
103}
104
105void avahi_warn_linkage(void) {
106    int w;
107
108    pthread_mutex_lock(&linkage_mutex);
109    w = linkage_warning;
110    linkage_warning = 1;
111    pthread_mutex_unlock(&linkage_mutex);
112
113    if (!w && !getenv("AVAHI_COMPAT_NOWARN")) {
114        avahi_warn("The program '%s' uses the "COMPAT_LAYER" compatibility layer of Avahi.", avahi_exe_name());
115        avahi_warn("Please fix your application to use the native API of Avahi!");
116        avahi_warn("For more information see <http://0pointer.de/avahi-compat?s="CGI_SUBSYSTEM"&e=%s>", avahi_exe_name());
117    }
118}
119
120void avahi_warn_unsupported(const char *function) {
121    avahi_warn("The program '%s' called '%s()' which is not supported (or only supported partially) in the "COMPAT_LAYER" compatibility layer of Avahi.", avahi_exe_name(), function);
122    avahi_warn("Please fix your application to use the native API of Avahi!");
123    avahi_warn("For more information see <http://0pointer.de/avahi-compat?s="CGI_SUBSYSTEM"&e=%s&f=%s>", avahi_exe_name(), function);
124}
125