static char* dinput_err_str(long err) { static char err_str[64]; switch (err) { case DIERR_NOTACQUIRED: _al_sane_strncpy(err_str, "the device is not acquired", sizeof(err_str)); break; case DIERR_INPUTLOST: _al_sane_strncpy(err_str, "access to the device was not granted", sizeof(err_str)); break; case DIERR_INVALIDPARAM: _al_sane_strncpy(err_str, "the device does not have a selected data format", sizeof(err_str)); break; case DIERR_OTHERAPPHASPRIO: _al_sane_strncpy(err_str, "can't acquire the device in background", sizeof(err_str)); break; default: _al_sane_strncpy(err_str, "unknown error", sizeof(err_str)); } return err_str; }
/* alsa_rawmidi_init: * Inits the ALSA RawMIDI interface. */ static int alsa_rawmidi_init(int input, int voices) { int ret = -1, err; char tmp1[128], tmp2[128], temp[256]; #if ALLEGRO_ALSA_VERSION == 9 snd_rawmidi_info_t *info; const char *device = NULL; #else /* ALLEGRO_ALSA_VERSION == 5 */ snd_rawmidi_info_t info; int card = -1; int device = -1; #endif if (input) { ret = -1; } else { #if ALLEGRO_ALSA_VERSION == 9 device = get_config_string(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_rawmidi_device", tmp2), "default"); err = snd_rawmidi_open(NULL, &rawmidi_handle, device, 0); #else /* ALLEGRO_ALSA_VERSION == 5 */ card = get_config_int(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_rawmidi_card", tmp2), snd_defaults_rawmidi_card()); device = get_config_int(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_rawmidi_device", tmp2), snd_defaults_rawmidi_device()); err = snd_rawmidi_open(&rawmidi_handle, card, device, SND_RAWMIDI_OPEN_OUTPUT_APPEND); #endif if (err) { snprintf(temp, sizeof(temp), "Could not open card/rawmidi device: %s", snd_strerror(err)); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(temp)); ret = -1; } ret = 0; } if (rawmidi_handle) { #if ALLEGRO_ALSA_VERSION == 9 snd_rawmidi_nonblock(rawmidi_handle, 0); snd_rawmidi_info_malloc(&info); snd_rawmidi_info(rawmidi_handle, info); _al_sane_strncpy(alsa_rawmidi_desc, snd_rawmidi_info_get_name(info), sizeof(alsa_rawmidi_desc)); #else /* ALLEGRO_ALSA_VERSION == 5 */ snd_rawmidi_block_mode(rawmidi_handle, 1); snd_rawmidi_info(rawmidi_handle, &info); _al_sane_strncpy(alsa_rawmidi_desc, info.name, sizeof(alsa_rawmidi_desc)); #endif midi_alsa.desc = alsa_rawmidi_desc; alsa_rawmidi_errors = 0; } return ret; }
/* Function: al_set_app_name */ void al_set_app_name(const char *app_name) { if (app_name) { _al_sane_strncpy(_al_app_name, app_name, sizeof(_al_app_name)); } else { ALLEGRO_PATH *path; path = al_get_standard_path(ALLEGRO_EXENAME_PATH); _al_sane_strncpy(_al_app_name, al_get_path_filename(path), sizeof(_al_app_name)); al_destroy_path(path); } }
/* object_enum_callback: [primary thread] * Helper function to find out what objects we have on the device. */ static BOOL CALLBACK object_enum_callback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) { #define GUIDTYPE_EQ(x) GUID_EQUAL(lpddoi->guidType, x) CAPS_AND_NAMES *can = pvRef; if (GUIDTYPE_EQ(__al_GUID_XAxis)) { can->have_x = true; _al_sane_strncpy(can->name_x, lpddoi->tszName, NAME_LEN); } else if (GUIDTYPE_EQ(__al_GUID_YAxis)) { can->have_y = true; _al_sane_strncpy(can->name_y, lpddoi->tszName, NAME_LEN); } else if (GUIDTYPE_EQ(__al_GUID_ZAxis)) { can->have_z = true; _al_sane_strncpy(can->name_z, lpddoi->tszName, NAME_LEN); } else if (GUIDTYPE_EQ(__al_GUID_RxAxis)) { can->have_rx = true; _al_sane_strncpy(can->name_rx, lpddoi->tszName, NAME_LEN); } else if (GUIDTYPE_EQ(__al_GUID_RyAxis)) { can->have_ry = true; _al_sane_strncpy(can->name_ry, lpddoi->tszName, NAME_LEN); } else if (GUIDTYPE_EQ(__al_GUID_RzAxis)) { can->have_rz = true; _al_sane_strncpy(can->name_rz, lpddoi->tszName, NAME_LEN); } else if (GUIDTYPE_EQ(__al_GUID_Slider)) { if (can->num_sliders < MAX_SLIDERS) { _al_sane_strncpy(can->name_slider[can->num_sliders], lpddoi->tszName, NAME_LEN); can->num_sliders++; } } else if (GUIDTYPE_EQ(__al_GUID_POV)) { if (can->num_povs < MAX_POVS) { _al_sane_strncpy(can->name_pov[can->num_povs], lpddoi->tszName, NAME_LEN); can->num_povs++; } } else if (GUIDTYPE_EQ(__al_GUID_Button)) { if (can->num_buttons < MAX_BUTTONS) { _al_sane_strncpy(can->name_button[can->num_buttons], lpddoi->tszName, NAME_LEN); can->num_buttons++; } } return DIENUM_CONTINUE; #undef GUIDTYPE_EQ }
/* _be_sys_get_executable_name: */ extern "C" void _be_sys_get_executable_name(char *output, int size) { image_info info; int32 cookie; cookie = 0; if (get_next_image_info(0, &cookie, &info) == B_NO_ERROR) { _al_sane_strncpy(output, info.name, size); } else { _al_sane_strncpy(output, EXE_NAME_UNKNOWN, size); } output[size-1] = '\0'; }
/* Function: al_set_org_name */ void al_set_org_name(const char *org_name) { if (!org_name) org_name = ""; _al_sane_strncpy(_al_org_name, org_name, sizeof(_al_org_name)); }
/* al_findnext: * Retrieves the next file from a directory search. */ int al_findnext(struct al_ffblk *info) { char tempname[FF_MAXPATHLEN]; char filename[FF_MAXPATHLEN]; int attrib; struct dirent *entry; struct stat s; struct FF_DATA *ff_data = (struct FF_DATA *) info->ff_data; ASSERT(ff_data); /* if the pattern contained no wildcard */ if (!ff_data->dir) return -1; while (TRUE) { /* read directory entry */ entry = readdir(ff_data->dir); if (!entry) { *allegro_errno = (errno ? errno : ENOENT); return -1; } /* try to match file name with pattern */ tempname[0] = 0; if (NAMLEN(entry) >= sizeof(tempname)) strncat(tempname, entry->d_name, sizeof(tempname) - 1); else strncat(tempname, entry->d_name, NAMLEN(entry)); if (ff_match(tempname, ff_data->pattern)) { _al_sane_strncpy(filename, ff_data->dirname, FF_MAXPATHLEN); ff_put_backslash(filename, sizeof(filename)); strncat(filename, tempname, sizeof(filename) - strlen(filename) - 1); /* get file attributes */ if (stat(filename, &s) == 0) { attrib = ff_get_attrib(tempname, &s); /* does it match ? */ if ((attrib & ~ff_data->attrib) == 0) break; } else { /* evil! but no other way to avoid exiting for_each_file() */ *allegro_errno = 0; } } } info->attrib = attrib; info->time = s.st_mtime; info->size = s.st_size; /* overflows at 2GB */ ff_data->size = s.st_size; do_uconvert(tempname, U_UTF8, info->name, U_CURRENT, sizeof(info->name)); return 0; }
/* Function: al_ustr_to_buffer */ void al_ustr_to_buffer(const ALLEGRO_USTR *us, char *buffer, int size) { int need; if (size <= 0) return; /* add 1 for terminating 0 byte */ need = _al_blength(us) + 1; if (size > need) size = need; _al_sane_strncpy(buffer, _al_bdata(us), size); }
/* * Calling LoadLibrary with a relative file name is a security risk: * see e.g. Microsoft Security Advisory (2269637) * "Insecure Library Loading Could Allow Remote Code Execution" */ HMODULE _al_win_safe_load_library(const char *filename) { ALLEGRO_PATH *path1 = NULL; ALLEGRO_PATH *path2 = NULL; char buf[MAX_PATH]; const char *other_dirs[3]; HMODULE lib = NULL; bool msvc_only = false; /* MSVC only: if the executable is in the build configuration directory, * which is also just under the current directory, then also try to load the * library from the current directory. This leads to less surprises when * running example programs. */ #if defined(ALLEGRO_MSVC) msvc_only = true; #endif /* Try to load the library from the directory containing the running * executable, the Windows system directories, or directories on the PATH. * Do NOT try to load the library from the current directory. */ if (al_is_system_installed()) { path1 = al_get_standard_path(ALLEGRO_RESOURCES_PATH); } else if (GetModuleFileName(NULL, buf, sizeof(buf)) < sizeof(buf)) { path1 = al_create_path(buf); } if (msvc_only) { path2 = maybe_parent_dir(path1); } other_dirs[0] = path1 ? al_path_cstr(path1, '\\') : NULL; other_dirs[1] = path2 ? al_path_cstr(path2, '\\') : NULL; other_dirs[2] = NULL; /* sentinel */ _al_sane_strncpy(buf, filename, sizeof(buf)); if (PathFindOnPath(buf, other_dirs)) { ALLEGRO_DEBUG("PathFindOnPath found: %s\n", buf); lib = load_library_at_path(buf); } else { ALLEGRO_WARN("PathFindOnPath failed to find %s\n", filename); } al_destroy_path(path1); al_destroy_path(path2); return lib; }
static char *android_get_clipboard_text(ALLEGRO_DISPLAY *display) { JNIEnv * env = (JNIEnv *)_al_android_get_jnienv(); jobject jtext = _jni_callObjectMethod(env, _al_android_activity_object(), "getClipboardText", "()Ljava/lang/String;"); jsize len = _jni_call(env, jsize, GetStringUTFLength, jtext); const char *str = _jni_call(env, const char *, GetStringUTFChars, jtext, NULL); char * text = al_malloc(len+1); (void) display; text = _al_sane_strncpy(text, str, len); _jni_callv(env, ReleaseStringUTFChars, jtext, str); _jni_callv(env, DeleteLocalRef, jtext); return text; }
/* print_extensions: * Given a string containing extensions (i.e. a NULL terminated string where * each extension are separated by a space and which names do not contain any * space) */ static void print_extensions(char const *extension) { char buf[80]; char *start; ASSERT(extension); while (*extension != '\0') { start = buf; _al_sane_strncpy(buf, extension, 80); while ((*start != ' ') && (*start != '\0')) { extension++; start++; } *start = '\0'; if (*extension != '\0') extension++; ALLEGRO_DEBUG("%s\n", buf); } }
/* system_thread: */ static int32 system_thread(void *data) { (void)data; if (_be_allegro_app == NULL) { char sig[MAXPATHLEN] = "application/x-vnd.Allegro-"; char exe[MAXPATHLEN]; char *term, *p; _be_sys_get_executable_name(exe, sizeof(exe)); strncat(sig, get_filename(exe), sizeof(sig)-1); sig[sizeof(sig)-1] = '\0'; _be_allegro_app = new BeAllegroApp(sig); using_custom_allegro_app = false; term = getenv("TERM"); if (!strcmp(term, "dumb")) { /* The TERM environmental variable is set to "dumb" if the app was * not started from a terminal. */ p = &exe[strlen(exe) - 1]; while (*p != '/') p--; *(p + 1) = '\0'; _al_sane_strncpy(app_path, exe, MAXPATHLEN); } } else { using_custom_allegro_app = true; } _be_allegro_app->Run(); /* XXX commented out due to conflicting TRACE in Haiku TRACE(PREFIX_I "system thread exited\n"); */ return 0; }
static char *add_string(char *buf, const char *src, int *pos, int bufsize) { char *dest = buf + *pos; if (*pos >= bufsize - 1) { /* Out of space. */ ASSERT(dest[0] == '\0'); return dest; } if (*pos > 0) { /* Skip over NUL separator. */ dest++; (*pos)++; } _al_sane_strncpy(dest, src, bufsize - *pos); (*pos) += strlen(dest); ASSERT(*pos < bufsize); return dest; }
static char *dd_err(long err) { static char err_str[64]; switch (err) { case DD_OK: _al_sane_strncpy(err_str, "DD_OK", sizeof(err_str)); break; case DDERR_GENERIC: _al_sane_strncpy(err_str, "DDERR_GENERIC", sizeof(err_str)); break; case DDERR_INCOMPATIBLEPRIMARY: _al_sane_strncpy(err_str, "DDERR_INCOMPATIBLEPRIMARY", sizeof(err_str)); break; case DDERR_INVALIDCAPS: _al_sane_strncpy(err_str, "DDERR_INVALIDCAPS", sizeof(err_str)); break; case DDERR_INVALIDOBJECT: _al_sane_strncpy(err_str, "DDERR_INVALIDOBJECT", sizeof(err_str)); break; case DDERR_INVALIDPARAMS: _al_sane_strncpy(err_str, "DDERR_INVALIDPARAMS", sizeof(err_str)); break; case DDERR_INVALIDPIXELFORMAT: _al_sane_strncpy(err_str, "DDERR_INVALIDPIXELFORMAT", sizeof(err_str)); break; case DDERR_NOFLIPHW: _al_sane_strncpy(err_str, "DDERR_NOFLIPHW", sizeof(err_str)); break; case DDERR_NOTFLIPPABLE: _al_sane_strncpy(err_str, "DDERR_NOTFLIPPABLE", sizeof(err_str)); break; case DDERR_OUTOFMEMORY: _al_sane_strncpy(err_str, "DDERR_OUTOFMEMORY", sizeof(err_str)); break; case DDERR_OUTOFVIDEOMEMORY: _al_sane_strncpy(err_str, "DDERR_OUTOFVIDEOMEMORY", sizeof(err_str)); break; case DDERR_PRIMARYSURFACEALREADYEXISTS: _al_sane_strncpy(err_str, "DDERR_PRIMARYSURFACEALREADYEXISTS", sizeof(err_str)); break; case DDERR_SURFACEBUSY: _al_sane_strncpy(err_str, "DDERR_SURFACEBUSY", sizeof(err_str)); break; case DDERR_SURFACELOST: _al_sane_strncpy(err_str, "DDERR_SURFACELOST", sizeof(err_str)); break; case DDERR_UNSUPPORTED: _al_sane_strncpy(err_str, "DDERR_UNSUPPORTED", sizeof(err_str)); break; case DDERR_UNSUPPORTEDMODE: _al_sane_strncpy(err_str, "DDERR_UNSUPPORTEDMODE", sizeof(err_str)); break; case DDERR_WASSTILLDRAWING: _al_sane_strncpy(err_str, "DDERR_WASSTILLDRAWING", sizeof(err_str)); break; default: _al_sane_strncpy(err_str, "DDERR_UNKNOWN", sizeof(err_str)); break; } return err_str; }
/* al_findfirst: * Initiates a directory search. */ int al_findfirst(AL_CONST char *pattern, struct al_ffblk *info, int attrib) { struct FF_DATA *ff_data; struct stat s; int actual_attrib; char tmp[1024]; char *p; /* allocate ff_data structure */ ff_data = _AL_MALLOC(sizeof(struct FF_DATA)); if (!ff_data) { *allegro_errno = ENOMEM; return -1; } memset(ff_data, 0, sizeof *ff_data); info->ff_data = (void *) ff_data; /* if the pattern contains no wildcard, we use stat() */ if (!ustrpbrk(pattern, uconvert("?*", U_ASCII, tmp, U_CURRENT, sizeof(tmp)))) { /* start the search */ errno = *allegro_errno = 0; if (stat(uconvert(pattern, U_CURRENT, tmp, U_UTF8, sizeof(tmp)), &s) == 0) { /* get file attributes */ actual_attrib = ff_get_attrib(ff_get_filename(uconvert(pattern, U_CURRENT, tmp, U_UTF8, sizeof(tmp))), &s); /* does it match ? */ if ((actual_attrib & ~attrib) == 0) { info->attrib = actual_attrib; info->time = s.st_mtime; info->size = s.st_size; /* overflows at 2GB */ ff_data->size = s.st_size; ustrzcpy(info->name, sizeof(info->name), get_filename(pattern)); return 0; } } _AL_FREE(ff_data); info->ff_data = NULL; *allegro_errno = (errno ? errno : ENOENT); return -1; } ff_data->attrib = attrib; do_uconvert(pattern, U_CURRENT, ff_data->dirname, U_UTF8, sizeof(ff_data->dirname)); p = ff_get_filename(ff_data->dirname); _al_sane_strncpy(ff_data->pattern, p, sizeof(ff_data->pattern)); if (p == ff_data->dirname) _al_sane_strncpy(ff_data->dirname, "./", FF_MAXPATHLEN); else *p = 0; /* nasty bodge, but gives better compatibility with DOS programs */ if (strcmp(ff_data->pattern, "*.*") == 0) _al_sane_strncpy(ff_data->pattern, "*", FF_MAXPATHLEN); /* start the search */ errno = *allegro_errno = 0; ff_data->dir = opendir(ff_data->dirname); if (!ff_data->dir) { *allegro_errno = (errno ? errno : ENOENT); _AL_FREE(ff_data); info->ff_data = NULL; return -1; } if (al_findnext(info) != 0) { al_findclose(info); return -1; } return 0; }
/* be_joy_init: * Initializes BeOS joystick driver. */ extern "C" int be_joy_init(void) { const char *device_config; char device_name[B_OS_NAME_LENGTH + 1]; static char desc[30]; static char name_x[10]; static char name_y[10]; static char name_stick[] = "stick"; static char name_hat[] = "hat"; static char name_throttle[] = "throttle"; static char name_hat_lr[] = "left/right"; static char name_hat_ud[] = "up/down"; static char *name_b[] = {"B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8"}; int32 i, j, stick; BString *temp; char *name; temp = new BString; be_joy = new BJoystick; num_devices = be_joy->CountDevices(); /* no joysticks available */ if (num_devices == 0) { goto cleanup; } /* Scans if the joystick_device config variable is set */ device_config = get_config_string("joystick", "joystick_device", ""); /* Let's try to open selected device */ if ((device_config[0] == '\0') || (be_joy->Open(device_config) < 0)) { /* ok, let's try to open first available device */ if (be_joy->GetDeviceName(0, device_name) != B_OK) { goto cleanup; } if (be_joy->Open(device_name) == B_ERROR) { goto cleanup; } } be_joy->GetControllerName(temp); name = temp->LockBuffer(0); _al_sane_strncpy(desc, name, sizeof(desc)); temp->UnlockBuffer(); joystick_beos.desc = desc; num_axes = be_joy->CountAxes(); num_hats = be_joy->CountHats(); num_buttons = be_joy->CountButtons(); if (num_axes) { axis_value = (int16 *)malloc(sizeof(int16) * num_axes); hat_value = (int8 *)malloc(sizeof(int8) * num_axes); } num_joysticks = be_joy->CountSticks(); for (i = 0; i < num_joysticks; i++) { joy[i].flags = JOYFLAG_DIGITAL | JOYFLAG_ANALOGUE; stick = 0; if (num_axes >= 2) { joy[i].stick[0].flags = JOYFLAG_DIGITAL | JOYFLAG_ANALOGUE | JOYFLAG_SIGNED; joy[i].stick[0].num_axis = 2; joy[i].stick[0].name = name_stick; be_joy->GetAxisNameAt(0, temp); name = temp->LockBuffer(0); _al_sane_strncpy(name_x, name, sizeof(name_x)); temp->UnlockBuffer(); joy[i].stick[0].axis[0].name = name_x; be_joy->GetAxisNameAt(1, temp); name = temp->LockBuffer(0); _al_sane_strncpy(name_y, name, sizeof(name_y)); temp->UnlockBuffer(); joy[i].stick[0].axis[1].name = name_y; stick++; for (j = 2; j < num_axes; j++) { joy[i].stick[stick].flags = JOYFLAG_DIGITAL | JOYFLAG_ANALOGUE | JOYFLAG_UNSIGNED; joy[i].stick[stick].num_axis = 1; joy[i].stick[stick].axis[0].name = ""; joy[i].stick[stick].name = name_throttle; stick++; } for (j = 0; j < num_hats; j++) { joy[i].stick[stick].flags = JOYFLAG_DIGITAL | JOYFLAG_SIGNED; joy[i].stick[stick].num_axis = 2; joy[i].stick[stick].axis[0].name = name_hat_lr; joy[i].stick[stick].axis[1].name = name_hat_ud; joy[i].stick[stick].name = name_hat; stick++; } } joy[i].num_sticks = stick; joy[i].num_buttons = num_buttons; for (j = 0; j < num_buttons; j++) joy[i].button[j].name = name_b[j]; } delete temp; be_joy_poll(); return 0; cleanup: { delete temp; delete be_joy; return -1; } }
/* joystick_enum_callback: [primary thread] * Helper function to find out how many joysticks we have and set them up. * At the end joydx_num_joysticks and joydx_joystick[] will be initialised. */ static BOOL CALLBACK joystick_enum_callback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) { DIPROPRANGE property_range = { /* the header */ { sizeof(DIPROPRANGE), // diph.dwSize sizeof(DIPROPHEADER), // diph.dwHeaderSize 0, // diph.dwObj DIPH_DEVICE, // diph.dwHow }, /* the data */ -32767, // lMin +32767 // lMax }; DIPROPDWORD property_deadzone = { /* the header */ { sizeof(DIPROPDWORD), // diph.dwSize sizeof(DIPROPHEADER), // diph.dwHeaderSize 0, // diph.dwObj DIPH_DEVICE, // diph.dwHow }, /* the data */ 2000, // dwData }; DIPROPDWORD property_buffersize = { /* the header */ { sizeof(DIPROPDWORD), // diph.dwSize sizeof(DIPROPHEADER), // diph.dwHeaderSize 0, // diph.dwObj DIPH_DEVICE, // diph.dwHow }, /* the data */ DEVICE_BUFFER_SIZE // number of data items }; LPDIRECTINPUTDEVICE _dinput_device1; LPDIRECTINPUTDEVICE2 dinput_device = NULL; HRESULT hr; LPVOID temp; CAPS_AND_NAMES caps_and_names; ALLEGRO_JOYSTICK_DIRECTX *joy; int num; (void)pvRef; /* check if the joystick already existed before */ joy = joydx_by_guid(lpddi->guidInstance); if (joy) { ALLEGRO_DEBUG("Device %s still exists\n", joydx_guid_string(joy)); joy->marked = true; return DIENUM_CONTINUE; } /* create the DirectInput joystick device */ hr = IDirectInput8_CreateDevice(joystick_dinput, &lpddi->guidInstance, &_dinput_device1, NULL); if (FAILED(hr)) goto Error; /* query the DirectInputDevice2 interface needed for the poll() method */ hr = IDirectInputDevice8_QueryInterface(_dinput_device1, &__al_IID_IDirectInputDevice8A, &temp); IDirectInputDevice8_Release(_dinput_device1); if (FAILED(hr)) goto Error; dinput_device = temp; /* enumerate objects available on the device */ memset(&caps_and_names, 0, sizeof(caps_and_names)); hr = IDirectInputDevice8_EnumObjects(dinput_device, object_enum_callback, &caps_and_names, DIDFT_PSHBUTTON | DIDFT_AXIS | DIDFT_POV); if (FAILED(hr)) goto Error; /* set data format */ hr = IDirectInputDevice8_SetDataFormat(dinput_device, &__al_c_dfDIJoystick); if (FAILED(hr)) goto Error; /* set the range of axes */ hr = IDirectInputDevice8_SetProperty(dinput_device, DIPROP_RANGE, &property_range.diph); if (FAILED(hr)) goto Error; /* set the dead zone of axes */ hr = IDirectInputDevice8_SetProperty(dinput_device, DIPROP_DEADZONE, &property_deadzone.diph); if (FAILED(hr)) goto Error; /* set the buffer size */ hr = IDirectInputDevice8_SetProperty(dinput_device, DIPROP_BUFFERSIZE, &property_buffersize.diph); if (FAILED(hr)) goto Error; /* set up the joystick structure */ joy = joydx_allocate_structure(&num); if (!joy) { ALLEGRO_ERROR("Joystick array full\n"); goto Error; } joy->config_state = STATE_BORN; joy->marked = true; joy->device = dinput_device; memcpy(&joy->guid, &lpddi->guidInstance, sizeof(GUID)); _al_sane_strncpy(joy->name, lpddi->tszInstanceName, sizeof(joy->name)); /* fill in the joystick structure */ fill_joystick_info_using_caps_and_names(joy, &caps_and_names); /* create a thread event for this joystick, unless it was already created */ joy->waker_event = CreateEvent(NULL, false, false, NULL); /* tell the joystick background thread to wake up when this joystick * device's state changes */ hr = IDirectInputDevice8_SetEventNotification(joy->device, joy->waker_event); if (FAILED(hr)) { ALLEGRO_ERROR("SetEventNotification failed for joystick %d: %s\n", num, dinput_err_str(hr)); goto Error; } if (hr == DI_POLLEDDEVICE) { /* This joystick device must be polled -- replace the Event with * a Waitable Timer object. * * Theoretically all polled devices could share a single * waitable timer object. But, really, how many such devices * are there going to be on a system? */ CloseHandle(joy->waker_event); joy->waker_event = CreateWaitableTimer(NULL, false, NULL); if (joy->waker_event == NULL) { ALLEGRO_ERROR("CreateWaitableTimer failed for polled device.\n"); goto Error; } { LARGE_INTEGER due_time; due_time.HighPart = 0; due_time.LowPart = 150; /* 15 ms (arbitrary) */ SetWaitableTimer(joy->waker_event, &due_time, true, /* periodic */ NULL, NULL, false); } } ALLEGRO_INFO("Joystick %d initialized, GUID: %s\n", num, joydx_guid_string(joy)); config_needs_merging = true; return DIENUM_CONTINUE; Error: if (dinput_device) IDirectInputDevice8_Release(dinput_device); if (joy) { joy->device = NULL; joydx_inactivate_joy(joy); } return DIENUM_CONTINUE; }
/* _unix_read_os_type: * Set the os_type variable to something sensible. */ void _unix_read_os_type(void) { #ifdef ALLEGRO_HAVE_SYS_UTSNAME_H struct utsname utsn; char *tmpstr, *tmpstr2; size_t pos; uname(&utsn); /* fetch OS version and revision */ tmpstr = _AL_MALLOC_ATOMIC(strlen(utsn.release)+1); _al_sane_strncpy(tmpstr, utsn.release, strlen(utsn.release)+1); tmpstr2 = NULL; for (pos = 0; pos <= strlen(utsn.release); pos++) { if (tmpstr[pos] == '.') { tmpstr[pos] = '\0'; if (!tmpstr2) tmpstr2 = tmpstr + pos + 1; } } os_version = atoi(tmpstr); os_revision = atoi(tmpstr2); _AL_FREE(tmpstr); /* try to detect Unix systems we know of */ if (!strcmp(utsn.sysname, "Linux")) { os_type = OSTYPE_LINUX; } else if (!strcmp(utsn.sysname, "SunOS")) { os_type = OSTYPE_SUNOS; } else if (!strcmp(utsn.sysname, "FreeBSD")) { os_type = OSTYPE_FREEBSD; } else if (!strcmp(utsn.sysname, "NetBSD")) { os_type = OSTYPE_NETBSD; } else if (!strcmp(utsn.sysname, "OpenBSD")) { os_type = OSTYPE_OPENBSD; } else if ((!strcmp(utsn.sysname, "IRIX")) || (!strcmp(utsn.sysname, "IRIX64"))) { os_type = OSTYPE_IRIX; } else if (!strcmp(utsn.sysname, "Darwin")) { os_type = OSTYPE_DARWIN; } else if (!strcmp(utsn.sysname, "QNX")) { os_type = OSTYPE_QNX; } else { os_type = OSTYPE_UNIX; /* that's all we can say for now */ } #else os_type = OSTYPE_UNIX; #endif os_multitasking = TRUE; }
/* _find_executable_file: * Helper function: searches path and current directory for executable. * Returns 1 on succes, 0 on failure. */ static int _find_executable_file(const char *filename, char *output, int size) { char *path; /* If filename has an explicit path, search current directory */ if (strchr (filename, '/')) { if (filename[0] == '/') { /* Full path; done */ do_uconvert (filename, U_ASCII, output, U_CURRENT, size); return 1; } else { struct stat finfo; char pathname[1024]; int len; /* Prepend current directory */ getcwd(pathname, sizeof(pathname)); len = strlen(pathname); pathname[len] = '/'; _al_sane_strncpy (pathname+len+1, filename, strlen(filename)); if ((stat(pathname, &finfo)==0) && (!S_ISDIR (finfo.st_mode))) { do_uconvert (pathname, U_ASCII, output, U_CURRENT, size); return 1; } } } /* If filename has no explicit path, but we do have $PATH, search there */ else if ((path = getenv("PATH"))) { char *start = path, *end = path, *buffer = NULL, *temp; struct stat finfo; while (*end) { end = strchr (start, ':'); if (!end) end = strchr (start, '\0'); /* Resize `buffer' for path component, slash, filename and a '\0' */ temp = _AL_REALLOC (buffer, end - start + 1 + strlen (filename) + 1); if (temp) { buffer = temp; _al_sane_strncpy (buffer, start, end - start); *(buffer + (end - start)) = '/'; _al_sane_strncpy (buffer + (end - start) + 1, filename, end - start + 1 + strlen (filename) + 1); if ((stat(buffer, &finfo)==0) && (!S_ISDIR (finfo.st_mode))) { do_uconvert (buffer, U_ASCII, output, U_CURRENT, size); _AL_FREE (buffer); return 1; } } /* else... ignore the failure; `buffer' is still valid anyway. */ start = end + 1; } /* Path search failed */ _AL_FREE (buffer); } return 0; }
/* _unix_get_executable_name: * Return full path to the current executable, use proc fs if available. */ void _unix_get_executable_name(char *output, int size) { #ifdef ALLEGRO_HAVE_SV_PROCFS_H struct prpsinfo psinfo; int fd; #endif char linkname[1024]; char filename[1024]; struct stat finfo; FILE *pipe; pid_t pid; int len; #ifdef ALLEGRO_HAVE_GETEXECNAME { const char *s = getexecname(); if (s) { if (s[0] == '/') { /* Absolute path */ do_uconvert (s, U_ASCII, output, U_CURRENT, size); return; } else { /* Not an absolute path */ if (_find_executable_file(s, output, size)) return; } } } #endif /* We need the PID in order to query procfs */ pid = getpid(); /* Try a Linux-like procfs */ /* get symolic link to executable from proc fs */ sprintf (linkname, "/proc/%d/exe", (int)pid); if (stat (linkname, &finfo) == 0) { len = readlink (linkname, filename, sizeof(filename)-1); if (len>-1) { filename[len] = '\0'; do_uconvert (filename, U_ASCII, output, U_CURRENT, size); return; } } /* Use System V procfs calls if available */ #ifdef ALLEGRO_HAVE_SV_PROCFS_H sprintf (linkname, "/proc/%d/exe", (int)pid); fd = open(linkname, O_RDONLY); if (!fd == -1) { ioctl(fd, PIOCPSINFO, &psinfo); close(fd); /* Use argv[0] directly if we can */ #ifdef ALLEGRO_HAVE_PROCFS_ARGCV if (psinfo.pr_argv && psinfo.pr_argc) { if (_find_executable_file(psinfo.pr_argv[0], output, size)) return; } else #endif { /* Emulate it */ /* We use the pr_psargs field to find argv[0] * This is better than using the pr_fname field because we need * the additional path information that may be present in argv[0] */ /* Skip other args */ char *s = strchr(psinfo.pr_psargs, ' '); if (s) s[0] = '\0'; if (_find_executable_file(psinfo.pr_psargs, output, size)) return; } /* Try the pr_fname just for completeness' sake if argv[0] fails */ if (_find_executable_file(psinfo.pr_fname, output, size)) return; } #endif /* Last resort: try using the output of the ps command to at least find */ /* the name of the file if not the full path */ uszprintf (linkname, sizeof(linkname), "ps -p %d", (int)pid); do_uconvert (linkname, U_CURRENT, filename, U_ASCII, size); pipe = popen(filename, "r"); if (pipe) { /* The first line of output is a header */ fgets(linkname, sizeof(linkname), pipe); /* The information we want is in the last column; find it */ len = strlen(linkname); while (linkname[len] != ' ' && linkname[len] != '\t') len--; /* The second line contains the info we want */ fgets(linkname, sizeof(linkname), pipe); pclose(pipe); /* Treat special cases: filename between [] and - for login shell */ if (linkname[len] == '-') len++; if (linkname[len] == '[' && linkname[strlen(linkname)] == ']') { len++; linkname[strlen(linkname)] = '\0'; } /* Now, the filename should be in the last column */ _al_sane_strncpy (filename, linkname+len+1, strlen(linkname)-len+1); if (_find_executable_file(filename, output, size)) return; /* Just return the output from ps... */ do_uconvert (filename, U_ASCII, output, U_CURRENT, size); return; } #ifdef ALLEGRO_WITH_MAGIC_MAIN /* Try the captured argv[0] */ if (_find_executable_file(__crt0_argv[0], output, size)) return; #endif /* Give up; return empty string */ do_uconvert ("", U_ASCII, output, U_CURRENT, size); }