this repo has no description
at master 261 lines 6.2 kB view raw
1/* 2 * $Id: blueping.c,v 1.8 2005/12/18 03:31:46 jcs Exp $ 3 * 4 * blueping 5 * a bluetooth monitoring utility 6 * 7 * Copyright (c) 2005 joshua stein <jcs@jcs.org> 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_2 34 35#include <CoreFoundation/CoreFoundation.h> 36#include <IOBluetooth/IOBluetoothUserLib.h> 37#include <IOBluetooth/IOBluetoothUtilities.h> 38#include <err.h> 39#include <signal.h> 40#include <time.h> 41 42void bail(int); 43void dolog(char *); 44void launchapp(char *); 45void pingloop(void); 46void sig_handler(int); 47void usage(void); 48 49IOBluetoothDeviceRef device; 50CFRunLoopTimerRef looptimer; 51char enterprog[1024], exitprog[1024]; 52int connected = -1; 53int verbose = 0; 54 55/* default poll interval in seconds */ 56long pollint = 15; 57 58extern char *__progname; 59 60int 61main(int argc, char *argv[]) 62{ 63 BluetoothDeviceAddress device_address; 64 CFStringRef t; 65 char macbuf[255], logstr[255]; 66 char *inval = NULL, *self = NULL, *p = NULL; 67 u_char devname[50]; 68 int ch; 69 70 CFRunLoopTimerContext context = {0, self, NULL, NULL, NULL}; 71 72 bzero(enterprog, sizeof(enterprog)); 73 bzero(exitprog, sizeof(exitprog)); 74 bzero(macbuf, sizeof(macbuf)); 75 76 while ((ch = getopt(argc, argv, "d:e:i:vx:")) != -1) { 77 switch (ch) { 78 case 'd': 79 strncpy(macbuf, optarg, sizeof(macbuf)); 80 break; 81 case 'e': 82 strncpy(enterprog, optarg, sizeof(enterprog)); 83 break; 84 case 'i': 85 if ((!(pollint = strtol((p = optarg), &inval, 10))) || 86 (pollint < 1)) 87 errx(1, "invalid poll interval -- %s", optarg); 88 break; 89 case 'v': 90 verbose++; 91 break; 92 case 'x': 93 strncpy(exitprog, optarg, sizeof(exitprog)); 94 break; 95 default: 96 usage(); 97 } 98 } 99 100 if (!strlen(macbuf)) 101 usage(); 102 103 if (!IOBluetoothLocalDeviceAvailable()) { 104 fprintf(stderr, "%s: no bluetooth available\n", __progname); 105 exit(1); 106 } 107 108 signal(SIGCHLD, sig_handler); 109 signal(SIGINT, sig_handler); 110 111 /* convert the mac address and establish our object */ 112 t = CFStringCreateWithCString(NULL, macbuf, kCFStringEncodingASCII); 113 int status = IOBluetoothNSStringToDeviceAddress(t, &device_address); 114 if (status != kIOReturnSuccess) { 115 fprintf(stderr, "%s: error creating device address: %s\n", 116 __progname, macbuf); 117 exit(1); 118 } 119 CFRelease(t); 120 121 device = IOBluetoothDeviceCreateWithAddress(&device_address); 122 123 if (verbose) { 124 status = IOBluetoothDeviceRemoteNameRequest(device, NULL, NULL, 125 devname); 126 if (status == kIOReturnSuccess) { 127 snprintf(logstr, sizeof(logstr), 128 "found device named \"%s\"", devname); 129 dolog(logstr); 130 } 131 } 132 133 looptimer = CFRunLoopTimerCreate( 134 NULL, 135 CFAbsoluteTimeGetCurrent(), 136 pollint, 137 0, 138 0, 139 (void *)pingloop, 140 &context); 141 142 CFRunLoopAddTimer(CFRunLoopGetCurrent(), looptimer, 143 kCFRunLoopCommonModes); 144 145 CFRunLoopRun(); 146 147 IOBluetoothDeviceCloseConnection(device); 148 IOBluetoothObjectRelease(device); 149 150 return(0); 151} 152 153void 154usage() 155{ 156 fprintf(stderr, "usage: %s -d macaddr [-e enterprog] [-i pollint] [-v]" 157 " [-x exitprog]\n", __progname); 158 exit(1); 159} 160 161void 162dolog(char *entry) 163{ 164 struct timeval tv[2]; 165 time_t now; 166 struct tm *tm; 167 168 gettimeofday(&tv[0], NULL); 169 now = tv[0].tv_sec; 170 tm = localtime(&now); 171 172 printf("[%02d:%02d:%02d] %s\n", tm->tm_hour, tm->tm_min, tm->tm_sec, 173 entry); 174} 175 176void 177pingloop() 178{ 179 int status; 180 char logstr[512]; 181 182 status = IOBluetoothDeviceOpenConnection(device, NULL, NULL); 183 if (status == kIOReturnSuccess) { 184 if (connected == 0 && verbose) { 185 bzero(logstr, sizeof(logstr)); 186 snprintf(logstr, sizeof(logstr), 187 "device entered range"); 188 189 if (strlen(enterprog)) 190 snprintf(logstr, sizeof(logstr), 191 "%s, executing \"%s\"", logstr, 192 enterprog); 193 194 dolog(logstr); 195 } 196 197 if (connected == 0 && strlen(enterprog)) 198 launchapp(enterprog); 199 200 connected = 1; 201 } else { 202 if (connected == 1 && verbose) { 203 bzero(logstr, sizeof(logstr)); 204 snprintf(logstr, sizeof(logstr), "device left range"); 205 206 if (strlen(exitprog)) 207 snprintf(logstr, sizeof(logstr), 208 "%s, executing \"%s\"", logstr, 209 exitprog); 210 211 dolog(logstr); 212 } 213 214 if (connected == 1 && strlen(exitprog)) 215 launchapp(exitprog); 216 217 connected = 0; 218 } 219 220 IOBluetoothDeviceCloseConnection(device); 221 222 if (verbose > 1) { 223 bzero(logstr, sizeof(logstr)); 224 snprintf(logstr, sizeof(logstr), "device is %sin range, " 225 "sleeping for %ld second%s", 226 (connected == 1 ? "" : "not "), pollint, 227 (pollint == 1 ? "" : "s")); 228 dolog(logstr); 229 } 230} 231 232void 233launchapp(char *progname) 234{ 235 char *argp[] = {"sh", "-c", NULL, NULL}; 236 pid_t pid; 237 238 argp[2] = progname; 239 pid = fork(); 240 if (pid == 0) { 241 execv("/bin/sh", argp); 242 _exit(1); 243 } 244} 245 246void 247sig_handler(int sig) 248{ 249 switch (sig) { 250 case SIGCHLD: 251 printf("got sigchld\n"); 252 wait(NULL); 253 break; 254 case SIGINT: 255 printf("\nshutting down\n"); 256 IOBluetoothDeviceCloseConnection(device); 257 IOBluetoothObjectRelease(device); 258 _exit(0); 259 break; 260 } 261}