inline string xml_attribute::parse() const { string data; unsigned offset = 0; const char *source = content; while(*source) { if(*source == '&') { if(strbegin(source, "<")) { data[offset++] = '<'; source += 4; continue; } if(strbegin(source, ">")) { data[offset++] = '>'; source += 4; continue; } if(strbegin(source, "&")) { data[offset++] = '&'; source += 5; continue; } if(strbegin(source, "'")) { data[offset++] = '\''; source += 6; continue; } if(strbegin(source, """)) { data[offset++] = '"'; source += 6; continue; } } //reject illegal characters if(*source == '&') return ""; if(*source == '<') return ""; if(*source == '>') return ""; data[offset++] = *source++; } data[offset] = 0; return data; }
inline bool xml_element::parse_head(string data) { data.qreplace("\t", " "); data.qreplace("\r", " "); data.qreplace("\n", " "); while(qstrpos(data, " ")) data.qreplace(" ", " "); data.qreplace(" =", "="); data.qreplace("= ", "="); data.rtrim(); lstring part; part.qsplit(" ", data); name = part[0]; if(name == "") throw "..."; for(unsigned i = 1; i < part.size(); i++) { lstring side; side.qsplit("=", part[i]); if(side.size() != 2) throw "..."; xml_attribute attr; attr.name = side[0]; attr.content = side[1]; if(strbegin(attr.content, "\"") && strend(attr.content, "\"")) attr.content.trim_once("\""); else if(strbegin(attr.content, "'") && strend(attr.content, "'")) attr.content.trim_once("'"); else throw "..."; attribute.append(attr); } return true; }
// insert a new line just after the current one and switch to it. // // keep it on the same tab level by having it start off with as many // tabs as the current line has. // // if cursor is before the leading tabs when we push ENTER, then the cursor // goes to X position 0 instead of following the end of the copied tabs. // // if we push ENTER in the middle of a line, we split the line and add // the rest of the line at the old cursor position to the new one. void DoEnter(EditView *ev) { int ntabs; int y = ev->cursor.y; bool extra_indent = false; // record current indentation level. // if cursor is at or after this level, we will auto-indent the resultant line. ntabs = ev->curline->GetIndentationLevel(); if (ev->cursor.x < ntabs) ntabs = 0; if (editor.settings.smart_indent_on_open) { // test if current line ends in a "{" if (ev->curline->GetCharAtIndex(ev->curline->GetLength() - 1) == '{') { if (ntabs > 0 || !editor.settings.no_smart_open_at_baselevel) { ntabs++; extra_indent = true; } } } // language-aware auto-indenting if (editor.settings.language_aware_indent && !extra_indent) { BString *bstr = ev->curline->GetLineAsString(); const char *str = bstr->String(); if (*str==TAB || *str==' ') { do { str++; } while(*str == TAB || *str == ' '); if (strbegin(str, "case ") || strbegin(str, "default:")) { ntabs++; extra_indent = true; } } delete bstr; } ev->action_insert_cr(ev->cursor.x, y); if (ntabs) { char *tabs = (char *)smal(ntabs + 1); memset(tabs, TAB, ntabs); tabs[ntabs] = 0; ev->action_insert_string(0, y + 1, tabs, NULL, NULL); frees(tabs); } ev->cursor.move(ntabs, y + 1); }
//ensure there is only one root element inline bool xml_validate(xml_element &document) { unsigned root_counter = 0; for(unsigned i = 0; i < document.element.size(); i++) { string &name = document.element[i].name; if(strbegin(name, "?")) continue; if(strbegin(name, "!")) continue; if(++root_counter > 1) return false; } return true; }
char* ltrim(char *str, const char *key) { if(!key || !*key) return str; while(strbegin(str, key)) { char *dest = str, *src = str + strlen(key); while(true) { *dest = *src++; if(!*dest) break; dest++; } } return str; }
void FileBrowser::onAcceptCartridge(const string &path) { string filename; if(QDir(path).exists()) { filename = resolveFilename(path); } else { filename = path; } if(file::exists(filename)) { close(); config().path.current.cartridge = fileSystemModel->rootPath().toUtf8().constData(); if(cartridgeMode == LoadDirect) { config().path.current.filter = filterBox->currentIndex(); string filter = filterBox->currentText().toUtf8().constData(); if(0); //file extension detection else if(striend(filename, ".sfc")) acceptNormal(filename); else if(striend(filename, ".bs")) acceptBsx(filename); else if(striend(filename, ".st")) acceptSufamiTurbo(filename); else if(striend(filename, ".gb")) acceptSuperGameBoy(filename); else if(striend(filename, ".sgb")) acceptSuperGameBoy(filename); else if(striend(filename, ".gbc")) acceptSuperGameBoy(filename); //filter detection else if(strbegin(filter, "SNES cartridges")) acceptNormal(filename); else if(strbegin(filter, "BS-X cartridges")) acceptBsx(filename); else if(strbegin(filter, "Sufami Turbo cartridges")) acceptSufamiTurbo(filename); else if(strbegin(filter, "Game Boy cartridges")) acceptSuperGameBoy(filename); //fallback behavior else acceptNormal(filename); } else if(cartridgeMode == LoadBase) { loaderWindow->selectBaseCartridge(filename); } else if(cartridgeMode == LoadSlot1) { loaderWindow->selectSlot1Cartridge(filename); } else if(cartridgeMode == LoadSlot2) { loaderWindow->selectSlot2Cartridge(filename); } } }
static uint16_t decode(const char *name) { string s(name); if(!strbegin(name, "KB")) return 0; ltrim(s, "KB"); unsigned id = strunsigned(s); auto pos = strpos(s, "::"); if(!pos) return 0; s = substr(s, pos() + 2); for(unsigned i = 0; i < Limit; i++) { if(s == KeyboardScancodeName[i]) return Base + Size * id + i; } return 0; }
static uint16_t decode(const char *name) { string s(name); if(!strbegin(name, "JP")) return 0; ltrim(s, "JP"); unsigned id = strunsigned(s); int pos = strpos(s, "::"); if(pos < 0) return 0; s = substr(s, pos + 2); for(unsigned i = 0; i < Limit; i++) { if(s == JoypadScancodeName[i]) return Base + Size * id + i; } return 0; }
//limit defaults to zero, which will underflow on first compare; equivalent to no limit template<unsigned Limit> char* ltrim(char *str, const char *key) { unsigned limit = Limit; if(!key || !*key) return str; while(strbegin(str, key)) { char *dest = str, *src = str + strlen(key); while(true) { *dest = *src++; if(!*dest) break; dest++; } if(--limit == 0) break; } return str; }
string operator[](const char *input) { for(unsigned i = 0; i < index_input.size(); i++) { if(index_input[i] == input) return index_output[i]; } //no match, use input; remove input identifier, if one exists if(strbegin(input, "{{")) { if(optional<unsigned> pos = strpos(input, "}}")) { string temp = substr(input, pos() + 2); return temp; } } return input; }
int main(int argc, char **argv) { xkas::Format format = xkas::format_bin; string outputFilename, exportFilename; lstring inputFilename; for(unsigned i = 1; i < argc; i++) { if(!strcmp(argv[i], "-o") && argc >= i + 1) { outputFilename = argv[++i]; } else if(!strcmp(argv[i], "-e") && argc >= i + 1) { exportFilename = argv[++i]; } else if (!strcmp(argv[i], "-ips")) { format = xkas::format_IPS; } else if(!strbegin(argv[i], "-")) { inputFilename.append(argv[i]); } else { print("unrecognized option: ", argv[i], "\n"); return 1; } } if(outputFilename == "" || inputFilename.size() == 0) { print("xkas-plus v14+1\n"); print("usage: xkas -o output.bin input.asm\n"); return 0; } xkas as; unsigned err = 0; as.open(outputFilename, format); foreach(filename, inputFilename) { if(as.assemble(filename) == false) { err = 1; break; } } if (!err && exportFilename != "") { as.exportFile(exportFilename); } as.close(); return err; }
inline string xml_element::parse() const { string data; unsigned offset = 0; const char *source = content; while(*source) { if(*source == '&') { if(strbegin(source, "<")) { data[offset++] = '<'; source += 4; continue; } if(strbegin(source, ">")) { data[offset++] = '>'; source += 4; continue; } if(strbegin(source, "&")) { data[offset++] = '&'; source += 5; continue; } if(strbegin(source, "'")) { data[offset++] = '\''; source += 6; continue; } if(strbegin(source, """)) { data[offset++] = '"'; source += 6; continue; } } if(strbegin(source, "<!--")) { if(optional<unsigned> pos = strpos(source, "-->")) { source += pos() + 3; continue; } else { return ""; } } if(strbegin(source, "<![CDATA[")) { if(optional<unsigned> pos = strpos(source, "]]>")) { string cdata = substr(source, 9, pos() - 9); data << cdata; offset += strlen(cdata); source += offset + 3; continue; } else { return ""; } } //reject illegal characters if(*source == '&') return ""; if(*source == '<') return ""; if(*source == '>') return ""; data[offset++] = *source++; } data[offset] = 0; return data; }
/** * setstr: * @buf: The non tabbed prefixed, null terminated string * @str: The strings to compare with e.g. "Vendor:" * @prop: The HAL property to set * * Return TRUE is found, FALSE otherwise. * * Finds the start of a null terminated string and sets HAL property if valid. */ static int setstr (char *buf, char *str, char *prop) { DBusError error; char *value; if (strbegin (buf, str)) { dbus_error_init (&error); value = buf + strlen (str) + 1; if (strcmp (value, "Not Specified") == 0) goto out; libhal_device_set_property_string (hfp_ctx, hfp_udi, prop, value, &hfp_error); LIBHAL_FREE_DBUS_ERROR (&hfp_error); hfp_info ("Setting %s='%s'", prop, value); return TRUE; } out: return FALSE; }
//ensure file path is absolute (eg resolve relative paths) string Cartridge::filepath(const char *filename, const char *pathname) { //if no pathname, return filename as-is string file(filename); file.replace("\\", "/"); string path = (!pathname || !*pathname) ? (const char*)snes.config.path.current : pathname; //ensure path ends with trailing '/' path.replace("\\", "/"); if(!strend(path, "/")) path.append("/"); //replace relative path with absolute path if(strbegin(path, "./")) { ltrim(path, "./"); path = string() << snes.config.path.base << path; } //remove folder part of filename lstring part; part.split("/", file); return path << part[part.size() - 1]; }
FILE* sec_fopen(char *path, char *mode) { char *rpath=realpath(path,NULL); char *spath=sec_path(NULL); FILE *ret=NULL; log_write(LOG_DBG, "Trying to access %s -> %s", path, rpath); if(rpath!=NULL && spath!=NULL && strbegin(rpath, spath)==0) { ret=fopen(rpath, mode); nfree(rpath); } else { log_write(LOG_INFO, "Prevented access to %s", path); nfree(rpath); } return ret; }
/** * setstr: * @buf: The non tabbed prefixed, null terminated string * @str: The strings to compare with e.g. "Vendor:" * @prop: The HAL property to set * * Returns: TRUE is found, FALSE otherwise. * * Finds the start of a null terminated string and sets HAL * property if valid. */ static int setstr (char *buf, char *str, char *prop) { DBusError error; char *value; if (str == NULL) goto out; if (strbegin (buf, str)) { dbus_error_init (&error); value = buf + strlen (str) + 1; if (strcmp (value, "Not Specified") == 0) goto out; if (!libhal_device_set_property_string (ctx, udi, prop, value, &error)) dbus_error_init (&error); HAL_DEBUG (("Setting %s='%s'", prop, value)); return TRUE; } out: return FALSE; }
/** * main: * @argc: Number of arguments given to program * @argv: Arguments given to program * Returns: Return code * * Main entry point */ int main (int argc, char *argv[]) { int ret; char buf[512]; char *nbuf; int dmipipe[2]; int nullfd; int tmp_ret; FILE *f; int dmiparser_state = DMIPARSER_STATE_IGNORE; /* on some system chassis pops up several times, * so only take the first entry for each */ int dmiparser_done_bios = FALSE; int dmiparser_done_system = FALSE; int dmiparser_done_chassis = FALSE; /* assume failure */ ret = 1; if (! hfp_init (argc, argv)) goto out; tmp_ret = pipe (dmipipe); f = fdopen (dmipipe[0], "r"); nullfd = open ("/dev/null", O_RDONLY); /* fork the child process */ switch (fork ()) { case 0: /* child */ dup2 (nullfd, STDIN_FILENO); dup2 (dmipipe[1], STDOUT_FILENO); close (dmipipe[0]); close (dmipipe[1]); /* execute the child */ execl (DMIDECODE, DMIDECODE, NULL); /* throw an error if we ever reach this point */ hfp_warning("failed to execute " DMIDECODE); exit (1); break; case -1: hfp_warning("cannot fork"); break; } /* parent continues from here */ /* close unused descriptor */ close (dmipipe[1]); /* read the output of the child */ while(fgets (buf, sizeof(buf), f) != NULL) { unsigned int i; unsigned int len; unsigned int tabs = 0; /* trim whitespace */ len = strlen (buf); /* check that will fit in buffer */ if (len >= sizeof (buf)) continue; /* not big enough for data, and protects us from underflow */ if (len < 3) { dmiparser_state = DMIPARSER_STATE_IGNORE; continue; } /* find out number of leading tabs */ if (buf[0] == '\t' && buf[1] == '\t') tabs = 2; /* this is list data */ else if (buf[0] == '\t') tabs = 1; /* this is data, 0 is section type */ if (tabs == 2) /* we do not proccess data at depth 2 */ continue; /* set the section type */ if (tabs == 0) { if (!dmiparser_done_bios && strbegin (buf, "BIOS Information")) dmiparser_state = DMIPARSER_STATE_BIOS; else if (!dmiparser_done_system && strbegin (buf, "System Information")) dmiparser_state = DMIPARSER_STATE_SYSTEM; else if (!dmiparser_done_chassis && strbegin (buf, "Chassis Information")) dmiparser_state = DMIPARSER_STATE_CHASSIS; else /* * We do not match the other sections, * or sections we have processed before */ dmiparser_state = DMIPARSER_STATE_IGNORE; continue; /* next line */ } /* we are not in a section we know, no point continueing */ if (dmiparser_state == DMIPARSER_STATE_IGNORE) continue; /* removes the leading tab */ nbuf = &buf[1]; /* removes the trailing spaces */ for (i = len - 2; isspace (nbuf[i]) && i >= 0; --i) nbuf[i] = '\0'; if (dmiparser_state == DMIPARSER_STATE_BIOS) { setstr (nbuf, "Vendor:", "system.firmware.vendor"); setstr (nbuf, "Version:", "system.firmware.version"); setstr (nbuf, "Release Date:", "system.firmware.release_date"); dmiparser_done_bios = TRUE; } else if (dmiparser_state == DMIPARSER_STATE_SYSTEM) { setstr (nbuf, "Manufacturer:", "system.hardware.vendor"); setstr (nbuf, "Product Name:", "system.hardware.product"); setstr (nbuf, "Version:", "system.hardware.version"); setstr (nbuf, "Serial Number:", "system.hardware.serial"); setstr (nbuf, "UUID:", "system.hardware.uuid"); dmiparser_done_system = TRUE; } else if (dmiparser_state == DMIPARSER_STATE_CHASSIS) { setstr (nbuf, "Manufacturer:", "system.chassis.manufacturer"); setstr (nbuf, "Type:", "system.chassis.type"); dmiparser_done_chassis = TRUE; } } /* as read to EOF, close */ fclose (f); /* return success */ ret = 0; out: return ret; }
bool string::beginswith(const char *str) const { return strbegin(data, str); }
bool gen_table(void) { FILE *fp, *fpo; char line[1024]; int nobjects = -1; int count = 0; printf("regenerating object-names table...\n"); fp = fopen(infile, "rb"); if (!fp) { fprintf(stderr, "<Cannot open object.h>\n"); return 1; } fpo = fopen(outfile, "wb"); if (!fpo) { fprintf(stderr, "<Cannot open objnames.cpp>\n"); fclose(fp); return 1; } memset(nametable, 0, sizeof(nametable)); while(!feof(fp)) { fgetline(fp, line, sizeof(line)); if (strbegin(line, "#define OBJ_")) { char *ptr = strstr(line, "//"); if (ptr) *ptr = 0; strtok(line, " \t"); const char *obj_name = strtok(NULL, " \t"); const char *obj_number_str = strtok(NULL, " \t"); int obj_number; if (obj_name && obj_number_str && (obj_number = atoi(obj_number_str))) { if (!strcmp(obj_name, "OBJ_LAST")) { nobjects = obj_number; } else { //printf("obj_name: %s obj_number: %d\n", obj_name, obj_number); nametable[obj_number] = strdup(&obj_name[4]); count++; } } } } if (nobjects == -1) { fprintf(stderr, "Couldn't find OBJ_LAST\n"); fclose(fp); fclose(fpo); return 1; } fprintf(fpo, "\n// auto-generated by genobjnametable.cpp\n"); fprintf(fpo, "#include <stdio.h>\n"); fprintf(fpo, "\nconst char *object_names[] = {\n"); for(int i=0;i<nobjects;i++) { if (nametable[i]) { fprintf(fpo, "\t\"%s\"", nametable[i]); free(nametable[i]); } else { fprintf(fpo, "\tNULL"); } if (i+1 != nobjects) fprintf(fpo, ",\n"); else fprintf(fpo, "\n"); } fprintf(fpo, "};\n"); printf("wrote %d objects in a space of %d\n", count, nobjects); fclose(fp); fclose(fpo); return 0; }
inline bool xml_element::parse_body(const char *&data) { while(true) { if(!*data) return false; if(*data++ != '<') continue; if(*data == '/') return false; if(strbegin(data, "!DOCTYPE") == true) { parse_doctype(data); return true; } if(strbegin(data, "!--")) { if(optional<unsigned> offset = strpos(data, "-->")) { data += offset() + 3; continue; } else { throw "..."; } } if(strbegin(data, "![CDATA[")) { if(optional<unsigned> offset = strpos(data, "]]>")) { data += offset() + 3; continue; } else { throw "..."; } } optional<unsigned> offset = strpos(data, ">"); if(!offset) throw "..."; string tag = substr(data, 0, offset()); data += offset() + 1; const char *content_begin = data; bool self_terminating = false; if(strend(tag, "?") == true) { self_terminating = true; tag.rtrim_once("?"); } else if(strend(tag, "/") == true) { self_terminating = true; tag.rtrim_once("/"); } parse_head(tag); if(self_terminating) return true; while(*data) { unsigned index = element.size(); xml_element node; if(node.parse_body(data) == false) { if(*data == '/') { signed length = data - content_begin - 1; if(length > 0) content = substr(content_begin, 0, length); data++; optional<unsigned> offset = strpos(data, ">"); if(!offset) throw "..."; tag = substr(data, 0, offset()); data += offset() + 1; tag.replace("\t", " "); tag.replace("\r", " "); tag.replace("\n", " "); while(strpos(tag, " ")) tag.replace(" ", " "); tag.rtrim(); if(name != tag) throw "..."; return true; } } else { element.append(node); } } } }
char* ltrim(char *str, const char *key) { if(!key || !*key) return str; while(strbegin(str, key)) strcpy(str, str + strlen(key)); return str; }
/** * main: * @argc: Number of arguments given to program * @argv: Arguments given to program * * Returns: Return code * * Main entry point */ int main (int argc, char *argv[]) { int ret; DBusError error; char buf[512]; char *nbuf; int dmipipe[2]; int nullfd; FILE *f; int dmiparser_state = DMIPARSER_STATE_IGNORE; /* on some system chassis pops up several times, * so only take the first entry for each */ int dmiparser_done_bios = FALSE; int dmiparser_done_system = FALSE; int dmiparser_done_chassis = FALSE; uint i; struct stat s; const char *path = NULL; const char *possible_paths[] = { "/usr/sbin/dmidecode", "/bin/dmidecode", "/sbin/dmidecode", "/usr/local/sbin/dmidecode", }; /* assume failure */ ret = 1; setup_logger (); dbus_error_init (&error); udi = getenv ("UDI"); if (udi == NULL) { HAL_ERROR (("UDI not set")); goto out; } if ((ctx = libhal_ctx_init_direct (&error)) == NULL) { HAL_ERROR (("ctx init failed")); goto out; } /* find the path to dmidecode */ for (i = 0; i < sizeof (possible_paths) / sizeof (char *); i++) { if (stat (possible_paths[i], &s) == 0 && S_ISREG (s.st_mode)) { path = possible_paths[i]; break; } } if (path == NULL) { HAL_ERROR(("Could not find dmidecode, exit!")); exit(1); } if(pipe (dmipipe) == -1) { HAL_ERROR(("Could not create pipe (error: '%s'), exit!", strerror(errno))); exit(1); } if ((f = fdopen (dmipipe[0], "r")) == NULL) { HAL_ERROR(("Could not open file (error: '%s'), exit!", strerror(errno))); exit(1); } if ((nullfd = open ("/dev/null", O_RDONLY)) == -1){ HAL_ERROR(("Could not open /dev/null (error: '%s'), exit!", strerror(errno))); exit(1); } /* fork the child process */ switch (fork ()) { case 0: /* child */ dup2 (nullfd, STDIN_FILENO); dup2 (dmipipe[1], STDOUT_FILENO); close (dmipipe[0]); close (dmipipe[1]); /* execute the child */ execl (path, path, NULL); /* throw an error if we ever reach this point */ HAL_ERROR (("Failed to execute dmidecode!")); exit (1); break; case -1: HAL_ERROR (("Cannot fork!")); goto out; } /* parent continues from here */ /* close unused descriptor */ close (dmipipe[1]); /* read the output of the child */ while(fgets (buf, sizeof(buf), f) != NULL) { int j; unsigned int len; unsigned int tabs = 0; /* trim whitespace */ len = strlen (buf); /* check that will fit in buffer */ if (len >= sizeof (buf)) continue; /* not big enough for data, and protects us from underflow */ if (len < 3) { dmiparser_state = DMIPARSER_STATE_IGNORE; continue; } /* find out number of leading tabs */ if (buf[0] == '\t' && buf[1] == '\t') tabs = 2; /* this is list data */ else if (buf[0] == '\t') tabs = 1; /* this is data, 0 is section type */ if (tabs == 2) /* we do not proccess data at depth 2 */ continue; /* set the section type */ if (tabs == 0) { if (!dmiparser_done_bios && strbegin (buf, "BIOS Information")) dmiparser_state = DMIPARSER_STATE_BIOS; else if (!dmiparser_done_system && strbegin (buf, "System Information")) dmiparser_state = DMIPARSER_STATE_SYSTEM; else if (!dmiparser_done_chassis && strbegin (buf, "Chassis Information")) dmiparser_state = DMIPARSER_STATE_CHASSIS; else if (!dmiparser_done_chassis && strbegin (buf, "Base Board Information")) dmiparser_state = DMIPARSER_STATE_BOARD; else /* * We do not match the other sections, * or sections we have processed before */ dmiparser_state = DMIPARSER_STATE_IGNORE; continue; /* next line */ } /* we are not in a section we know, no point continueing */ if (dmiparser_state == DMIPARSER_STATE_IGNORE) continue; /* return success only if there was something usefull to parse */ ret = 0; /* removes the leading tab */ nbuf = &buf[1]; /* removes the trailing spaces */ for (j = len - 2; isspace (nbuf[j]) && j >= 0; --j) nbuf[j] = '\0'; if (dmiparser_state == DMIPARSER_STATE_BIOS) { setstr (nbuf, "Vendor:", "system.firmware.vendor"); setstr (nbuf, "Version:", "system.firmware.version"); setstr (nbuf, "Release Date:", "system.firmware.release_date"); dmiparser_done_bios = TRUE; } else if (dmiparser_state == DMIPARSER_STATE_SYSTEM) { setstr (nbuf, "Manufacturer:", "system.hardware.vendor"); setstr (nbuf, "Product Name:", "system.hardware.product"); setstr (nbuf, "Version:", "system.hardware.version"); setstr (nbuf, "Serial Number:", "system.hardware.serial"); setstr (nbuf, "UUID:", "system.hardware.uuid"); dmiparser_done_system = TRUE; } else if (dmiparser_state == DMIPARSER_STATE_CHASSIS) { setstr (nbuf, "Manufacturer:", "system.chassis.manufacturer"); setstr (nbuf, "Type:", "system.chassis.type"); dmiparser_done_chassis = TRUE; } else if (dmiparser_state == DMIPARSER_STATE_BOARD) { setstr (nbuf, "Manufacturer:", "system.board.vendor"); setstr (nbuf, "Product Name:", "system.board.product"); setstr (nbuf, "Version:", "system.board.version"); setstr (nbuf, "Serial Number:", "system.board.serial"); dmiparser_done_system = TRUE; } } /* as read to EOF, close */ fclose (f); out: LIBHAL_FREE_DBUS_ERROR (&error); /* free ctx */ if (ctx != NULL) { libhal_ctx_shutdown (ctx, &error); LIBHAL_FREE_DBUS_ERROR (&error); libhal_ctx_free (ctx); } return ret; }