static list_t * set_vendor_namespaces(void) { hscan_t hs; hnode_t *hn; int i; list_t *l = list_create(LISTCOUNT_T_MAX); for (i = 0; CimResource_Namespaces[i].ns != NULL; i++) { WsSupportedNamespaces *ns = (WsSupportedNamespaces *)u_malloc(sizeof(WsSupportedNamespaces)); ns->class_prefix = CimResource_Namespaces[i].class_prefix; ns->ns = (char*) CimResource_Namespaces[i].ns; lnode_t *node = lnode_create(ns); list_append(l, node); } if (vendor_namespaces && hash_count(vendor_namespaces) > 0 ) { hash_scan_begin(&hs, vendor_namespaces); while ((hn = hash_scan_next(&hs))) { WsSupportedNamespaces *ns = (WsSupportedNamespaces *)u_malloc(sizeof(WsSupportedNamespaces)); ns->class_prefix = (char*)hnode_getkey(hn); ns->ns = (char*) hnode_get(hn); lnode_t *node = lnode_create(ns); list_append(l, node); } } return l; }
void list_add(List* list, void* var, void (*destroy_var) (void *)){ if (list->start == NULL) { list->start = lnode_create(var, destroy_var); list->last = list->start; } else { ListNode* new_last = lnode_create(var, destroy_var); list->last->next = new_last; list->last = new_last; } list->len++; }
static void tst_collect_build(void *value, tst_collect_t *results) { if(!results->tester || results->tester(value, results->key, results->len)) { lnode_t *node = lnode_create(value); list_append(results->values, node); } }
/*Creates the root node and the corresponding lnode*/ error_t node_create_root (node_t ** root_node) { /*Try to create a new lnode */ lnode_t *lnode; error_t err = lnode_create (NULL, &lnode); /*Stop, if the creation failed */ if (err) return err; /*Try to derive the node corresponding to `lnode` */ node_t *node; err = node_create (lnode, &node); /*If the operation failed */ if (err) { /*destroy the created lnode */ lnode_destroy (lnode); /*stop */ return err; } /*Release the lock on the lnode */ mutex_unlock (&lnode->lock); /*Store the result in the parameter */ *root_node = node; /*Return the result */ return err; } /*node_create_root */
list_t* termFreeVars(TERM *t) { list_t *vars, *rvars; lnode_t *node; switch(t->type) { case(TM_VAR): vars = list_create(LISTCOUNT_T_MAX); list_append(vars, lnode_create(t->name)); break; case(TM_ALIAS): vars = list_create(LISTCOUNT_T_MAX); break; case(TM_ABSTR): vars = termFreeVars(t->rterm); while(node = list_find(vars, t->lterm->name, (int(*)(const void*, const void*))strcmp)) lnode_destroy(list_delete(vars, node)); break; case(TM_APPL): vars = termFreeVars(t->lterm); rvars = termFreeVars(t->rterm); list_transfer(vars, rvars, list_first(rvars)); list_destroy(rvars); break; } t->closed = list_isempty(vars); return vars; }
CP_C_API cp_status_t cp_register_logger(cp_context_t *context, cp_logger_func_t logger, void *user_data, cp_log_severity_t min_severity) { logger_t l; logger_t *lh = NULL; lnode_t *node = NULL; cp_status_t status = CP_OK; CHECK_NOT_NULL(context); CHECK_NOT_NULL(logger); cpi_lock_context(context); cpi_check_invocation(context, CPI_CF_LOGGER, __func__); do { // Check if logger already exists and allocate new holder if necessary l.logger = logger; if ((node = list_find(context->env->loggers, &l, comp_logger)) == NULL) { lh = malloc(sizeof(logger_t)); node = lnode_create(lh); if (lh == NULL || node == NULL) { status = CP_ERR_RESOURCE; break; } lh->logger = logger; lh->plugin = context->plugin; list_append(context->env->loggers, node); } else { lh = lnode_get(node); } // Initialize or update the logger holder lh->user_data = user_data; lh->min_severity = min_severity; // Update global limits update_logging_limits(context); } while (0); // Report error if (status == CP_ERR_RESOURCE) { cpi_error(context, N_("Logger could not be registered due to insufficient memory.")); } else if (cpi_is_logged(context, CP_LOG_DEBUG)) { char owner[64]; /* TRANSLATORS: %s is the context owner */ cpi_debugf(context, N_("%s registered a logger."), cpi_context_owner(context, owner, sizeof(owner))); } cpi_unlock_context(context); // Release resources on error if (status != CP_OK) { if (node != NULL) { lnode_destroy(node); } if (lh != NULL) { free(lh); } } return status; }
/* * Create node and append to list */ lnode_t *lnode_create_prepend (list_t *list, void *data) { lnode_t *ln; ln = lnode_create(data); list_prepend(list, ln); return ln; }
WsContextH wsman_init_plugins(WsManListenerH * listener) { list_t *list = list_create(LISTCOUNT_T_MAX); lnode_t *node; WsContextH cntx = NULL; WsDispatchInterfaceInfo *ifcinfo = NULL; wsman_plugins_load(listener); node = list_first(listener->plugins); while (node) { WsManPlugin *p = (WsManPlugin *) node->list_data; if (p->init == NULL || p->init(p->p_handle, &(p->data)) == 0 ) { error ("Plugin %s fails init()", p->p_name); error("invalid plugin"); goto next_plugin; } p->ifc = (WsDispatchInterfaceInfo *) malloc(sizeof(WsDispatchInterfaceInfo)); ifcinfo = p->ifc; ifcinfo->extraData = p->data; p->set_config = dlsym(p->p_handle, "set_config"); if (listener->config && p->set_config) { p->set_config(p->p_handle, listener->config); } else { debug("no configuration available for plugin: %s", p->p_name); } if (p->get_endpoints) p->get_endpoints(p->p_handle, p->ifc); if (p->ifc && wsman_server_verify_plugin(ifcinfo)) { lnode_t *i = lnode_create(p->ifc); list_append(list, i); } else { error ("Plugin '%s' is not compatible with version of the software or plugin is invalid", p->p_name); error("invalid plugin"); } next_plugin: node = list_next(listener->plugins, node); } cntx = ws_create_runtime(list); return cntx; }
void enqueue(queue_t *q, void* data) { lnode_t *n = lnode_create(data); pthread_mutex_lock(&q->lock); if (list_isfull(q->list)) { pthread_cond_wait(&q->notfull, &q->lock); } if (list_isempty(q->list)) { list_append(q->list, n); pthread_cond_broadcast(&q->notempty); } pthread_mutex_unlock(&q->lock); }
CP_HIDDEN int cpi_ptrset_add(list_t *set, void *ptr) { // Only add the pointer if it is not already included if (cpi_ptrset_contains(set, ptr)) { return 1; } else { lnode_t *node; /* Add the pointer to the list */ node = lnode_create(ptr); if (node == NULL) { return 0; } list_append(set, node); return 1; } }
void wsmand_shutdown_add_handler(WsmandShutdownFn fn, void *user_data) { ShutdownHandler *handler; lnode_t *n; if (fn == NULL) return; handler = u_zalloc(sizeof(ShutdownHandler)); handler->fn = fn; handler->user_data = user_data; n = lnode_create(handler); if (!shutdown_handlers) shutdown_handlers = list_create(LISTCOUNT_T_MAX); list_prepend(shutdown_handlers, n); }
static list_t * set_namespaces(void) { int i; list_t *l = list_create(LISTCOUNT_T_MAX); for (i = 0; WsManTest_Namespaces[i].ns != NULL; i++) { WsSupportedNamespaces *ns = (WsSupportedNamespaces *)u_malloc(sizeof(WsSupportedNamespaces)); ns->class_prefix = WsManTest_Namespaces[i].class_prefix; ns->ns = (char*) WsManTest_Namespaces[i].ns; lnode_t *node = lnode_create(ns); list_append(l, node); } return l; }
static void scan_plugins_in_directory ( WsManListenerH *listener, const char *dir_name) { list_t *files = scan_files_in_dir ( dir_name, select_all_files); lnode_t *node = list_first(files); listener->plugins = list_create(LISTCOUNT_T_MAX); while (node != NULL) { const char* entry_name; int retv = -1; entry_name = (const char*) node->list_data; node = list_next(files, node); if ((NULL != entry_name) && strlen (entry_name) > strlen(PLUGIN_EXT) && (0 == strcmp (&entry_name[strlen(entry_name)-strlen(PLUGIN_EXT)], PLUGIN_EXT))) { char *plugin_path = u_strdup_printf ("%s/%s", dir_name, entry_name); WsManPlugin *plugin = plugin_new(); if ((NULL != plugin) && (NULL != plugin_path)) { if (load_plugin(plugin, plugin_path) == 0 ) { lnode_t *plg = lnode_create (plugin); list_append (listener->plugins, plg); retv = 0 ; } } else { error("Out of memory scanning for plugins."); } if (plugin_path) u_free (plugin_path); if (retv != 0 && (NULL != plugin)) plugin_free(plugin); } } list_destroy_nodes(files); list_destroy(files); return; }
static list_t* scan_files_in_dir ( const char *dir, int (*select)(const struct dirent *)) { struct dirent **namelist; int n; list_t *files = list_create(LISTCOUNT_T_MAX); if (0 > (n = scandir (dir, &namelist, 0, alphasort))) { return files; } else { while (n--) { lnode_t *node; char *tmp = u_strdup(namelist[n]->d_name); node = lnode_create(tmp); list_append(files, node ); //debug("plugin file found: %s", namelist[n]->d_name ); u_free(namelist[n]); } u_free(namelist); } return files; }
hash_t * wsman_get_method_args(WsContextH cntx, const char *resource_uri) { char *input = NULL; WsXmlDocH doc = cntx->indoc; hash_t *h = hash_create(HASHCOUNT_T_MAX, 0, 0); hash_set_allocator(h, NULL, wsman_free_method_hnode, NULL); if (doc) { WsXmlNodeH in_node; WsXmlNodeH body = ws_xml_get_soap_body(doc); char *mn = wsman_get_method_name(cntx); input = u_strdup_printf("%s_INPUT", mn); in_node = ws_xml_get_child(body, 0, resource_uri, input); if (!in_node) { char *xsd = u_strdup_printf("%s.xsd", resource_uri); in_node = ws_xml_get_child(body, 0, xsd, input); u_free(xsd); } if (in_node) { WsXmlNodeH arg, epr; int index = 0; list_t *arglist = list_create(LISTCOUNT_T_MAX); lnode_t *argnode; while ((arg = ws_xml_get_child(in_node, index++, NULL, NULL))) { char *key = ws_xml_get_node_local_name(arg); selector_entry *sentry = u_malloc(sizeof(*sentry)); methodarglist_t *nodeval = u_malloc(sizeof(methodarglist_t)); epr = ws_xml_get_child(arg, 0, XML_NS_ADDRESSING, WSA_REFERENCE_PARAMETERS); nodeval->key = u_strdup(key); nodeval->arraycount = 0; argnode = lnode_create(nodeval); if (epr) { debug("epr: %s", key); sentry->type = 1; sentry->entry.eprp = epr_deserialize(arg, NULL, NULL, 1); //wsman_get_epr(cntx, arg, key, XML_NS_CIM_CLASS); } else { debug("text: %s", key); sentry->type = 0; sentry->entry.text = u_strdup(ws_xml_get_node_text(arg)); } nodeval->data = sentry; list_append(arglist, argnode); } if (!hash_alloc_insert(h, METHOD_ARGS_KEY, arglist)) { error("hash_alloc_insert failed"); wsman_free_method_list(arglist); } } u_free(mn); u_free(input); } else { error("error: xml document is NULL"); } if (!hash_isempty(h)) return h; hash_destroy(h); return NULL; }
/** * Check for duplicate Message ID * @param op operation * @return status */ static int wsman_is_duplicate_message_id(op_t * op) { WsXmlNodeH header = wsman_get_soap_header_element(op->in_doc, NULL, NULL); int retVal = 0; SoapH soap; WsXmlNodeH msgIdNode; soap = op->dispatch->soap; msgIdNode = ws_xml_get_child(header, 0, XML_NS_ADDRESSING, WSA_MESSAGE_ID); if (msgIdNode != NULL) { lnode_t *node; char *msgId; msgId = ws_xml_get_node_text(msgIdNode); if (msgId[0] == 0 ) { generate_op_fault(op, WSA_INVALID_MESSAGE_INFORMATION_HEADER, 0 ); debug("MessageId missing"); return 1; } debug("Checking Message ID: %s", msgId); u_lock(soap); if (soap->processedMsgIdList == NULL) { soap->processedMsgIdList = list_create(LISTCOUNT_T_MAX); } #ifndef IGNORE_DUPLICATE_ID node = list_first(soap->processedMsgIdList); while (node != NULL) { if (!strcmp(msgId, (char *) node->list_data)) { debug("Duplicate Message ID: %s", msgId); retVal = 1; generate_op_fault(op, WSA_INVALID_MESSAGE_INFORMATION_HEADER, WSA_DETAIL_DUPLICATE_MESSAGE_ID); break; } node = list_next(soap->processedMsgIdList, node); } #endif if (!retVal) { while (list_count(soap->processedMsgIdList) >= PROCESSED_MSG_ID_MAX_SIZE) { node = list_del_first(soap->processedMsgIdList); u_free(node->list_data); u_free(node); } node = lnode_create(NULL); if (node) { node->list_data = u_str_clone(msgId); if (node->list_data == NULL) { u_free(node); } else { list_append(soap->processedMsgIdList, node); } } } u_unlock(soap); } else if (!wsman_is_identify_request(op->in_doc)) { generate_op_fault(op, WSA_MESSAGE_INFORMATION_HEADER_REQUIRED, 0); debug("No MessageId Header found"); return 1; } return retVal; }
CP_C_API cp_status_t cp_scan_plugins(cp_context_t *context, int flags) { hash_t *avail_plugins = NULL; list_t *started_plugins = NULL; cp_plugin_info_t **plugins = NULL; char *pdir_path = NULL; int pdir_path_size = 0; int plugins_stopped = 0; cp_status_t status = CP_OK; CHECK_NOT_NULL(context); cpi_lock_context(context); cpi_check_invocation(context, CPI_CF_ANY, __func__); cpi_debug(context, N_("Plug-in scan is starting.")); do { lnode_t *lnode; hscan_t hscan; hnode_t *hnode; // Create a hash for available plug-ins if ((avail_plugins = hash_create(HASHCOUNT_T_MAX, (int (*)(const void *, const void *)) strcmp, NULL)) == NULL) { status = CP_ERR_RESOURCE; break; } // Scan plug-in directories for available plug-ins lnode = list_first(context->env->plugin_dirs); while (lnode != NULL) { const char *dir_path; DIR *dir; dir_path = lnode_get(lnode); dir = opendir(dir_path); if (dir != NULL) { int dir_path_len; struct dirent *de; dir_path_len = strlen(dir_path); if (dir_path[dir_path_len - 1] == CP_FNAMESEP_CHAR) { dir_path_len--; } errno = 0; while ((de = readdir(dir)) != NULL) { if (de->d_name[0] != '\0' && de->d_name[0] != '.') { int pdir_path_len = dir_path_len + 1 + strlen(de->d_name) + 1; cp_plugin_info_t *plugin; cp_status_t s; hnode_t *hnode; // Allocate memory for plug-in descriptor path if (pdir_path_size <= pdir_path_len) { char *new_pdir_path; if (pdir_path_size == 0) { pdir_path_size = 128; } while (pdir_path_size <= pdir_path_len) { pdir_path_size *= 2; } new_pdir_path = realloc(pdir_path, pdir_path_size * sizeof(char)); if (new_pdir_path == NULL) { cpi_errorf(context, N_("Could not check possible plug-in location %s%c%s due to insufficient system resources."), dir_path, CP_FNAMESEP_CHAR, de->d_name); status = CP_ERR_RESOURCE; // continue loading plug-ins from other directories continue; } pdir_path = new_pdir_path; } // Construct plug-in descriptor path strcpy(pdir_path, dir_path); pdir_path[dir_path_len] = CP_FNAMESEP_CHAR; strcpy(pdir_path + dir_path_len + 1, de->d_name); // Try to load a plug-in plugin = cp_load_plugin_descriptor(context, pdir_path, &s); if (plugin == NULL) { status = s; // continue loading plug-ins from other directories continue; } // Insert plug-in to the list of available plug-ins if ((hnode = hash_lookup(avail_plugins, plugin->identifier)) != NULL) { cp_plugin_info_t *plugin2 = hnode_get(hnode); if (cpi_vercmp(plugin->version, plugin2->version) > 0) { hash_delete_free(avail_plugins, hnode); cp_release_info(context, plugin2); hnode = NULL; } } if (hnode == NULL) { if (!hash_alloc_insert(avail_plugins, plugin->identifier, plugin)) { cpi_errorf(context, N_("Plug-in %s version %s could not be loaded due to insufficient system resources."), plugin->identifier, plugin->version); cp_release_info(context, plugin); status = CP_ERR_RESOURCE; // continue loading plug-ins from other directories continue; } } } errno = 0; } if (errno) { cpi_errorf(context, N_("Could not read plug-in directory %s: %s"), dir_path, strerror(errno)); status = CP_ERR_IO; // continue loading plug-ins from other directories } closedir(dir); } else { cpi_errorf(context, N_("Could not open plug-in directory %s: %s"), dir_path, strerror(errno)); status = CP_ERR_IO; // continue loading plug-ins from other directories } lnode = list_next(context->env->plugin_dirs, lnode); } // Copy the list of started plug-ins, if necessary if ((flags & CP_SP_RESTART_ACTIVE) && (flags & (CP_SP_UPGRADE | CP_SP_STOP_ALL_ON_INSTALL))) { int i; cp_status_t s; if ((plugins = cp_get_plugins_info(context, &s, NULL)) == NULL) { status = s; break; } if ((started_plugins = list_create(LISTCOUNT_T_MAX)) == NULL) { status = CP_ERR_RESOURCE; break; } for (i = 0; plugins[i] != NULL; i++) { cp_plugin_state_t state; state = cp_get_plugin_state(context, plugins[i]->identifier); if (state == CP_PLUGIN_STARTING || state == CP_PLUGIN_ACTIVE) { char *pid; if ((pid = strdup(plugins[i]->identifier)) == NULL) { status = CP_ERR_RESOURCE; break; } if ((lnode = lnode_create(pid)) == NULL) { free(pid); status = CP_ERR_RESOURCE; break; } list_append(started_plugins, lnode); } } cpi_release_info(context, plugins); plugins = NULL; } // Install/upgrade plug-ins hash_scan_begin(&hscan, avail_plugins); while ((hnode = hash_scan_next(&hscan)) != NULL) { cp_plugin_info_t *plugin; cp_plugin_t *ip = NULL; hnode_t *hn2; int s; plugin = hnode_get(hnode); hn2 = hash_lookup(context->env->plugins, plugin->identifier); if (hn2 != NULL) { ip = hnode_get(hn2); } // Unload the installed plug-in if it is to be upgraded if (ip != NULL && (flags & CP_SP_UPGRADE) && ((ip->plugin->version == NULL && plugin->version != NULL) || (ip->plugin->version != NULL && plugin->version != NULL && cpi_vercmp(plugin->version, ip->plugin->version) > 0))) { if ((flags & (CP_SP_STOP_ALL_ON_UPGRADE | CP_SP_STOP_ALL_ON_INSTALL)) && !plugins_stopped) { plugins_stopped = 1; cp_stop_plugins(context); } s = cp_uninstall_plugin(context, plugin->identifier); assert(s == CP_OK); ip = NULL; } // Install the plug-in, if to be installed if (ip == NULL) { if ((flags & CP_SP_STOP_ALL_ON_INSTALL) && !plugins_stopped) { plugins_stopped = 1; cp_stop_plugins(context); } if ((s = cp_install_plugin(context, plugin)) != CP_OK) { status = s; break; } } // Remove the plug-in from the hash hash_scan_delfree(avail_plugins, hnode); cp_release_info(context, plugin); } // Restart stopped plug-ins if necessary if (started_plugins != NULL) { lnode = list_first(started_plugins); while (lnode != NULL) { char *pid; int s; pid = lnode_get(lnode); s = cp_start_plugin(context, pid); if (s != CP_OK) { status = s; } lnode = list_next(started_plugins, lnode); } } } while (0); // Report error switch (status) { case CP_OK: cpi_debug(context, N_("Plug-in scan has completed successfully.")); break; case CP_ERR_RESOURCE: cpi_error(context, N_("Could not scan plug-ins due to insufficient system resources.")); break; default: cpi_error(context, N_("Could not scan plug-ins.")); break; } cpi_unlock_context(context); // Release resources if (pdir_path != NULL) { free(pdir_path); } if (avail_plugins != NULL) { hscan_t hscan; hnode_t *hnode; hash_scan_begin(&hscan, avail_plugins); while ((hnode = hash_scan_next(&hscan)) != NULL) { cp_plugin_info_t *p = hnode_get(hnode); hash_scan_delfree(avail_plugins, hnode); cp_release_info(context, p); } hash_destroy(avail_plugins); } if (started_plugins != NULL) { list_process(started_plugins, NULL, cpi_process_free_ptr); list_destroy(started_plugins); } if (plugins != NULL) { cp_release_info(context, plugins); } return status; }
static list_t * TargetEndpoints( void *self, void *data ) { int len, i; PyObject *instance = (PyObject *)data; PyObject *pyfunc, *pynamespaces = NULL; WsmanStatus status; wsman_status_init(&status); debug("TargetEndpoints(Python), data %p, instance %p", data, instance); /* * Get namespaces */ list_t *namespaces = list_create(LISTCOUNT_T_MAX); pyfunc = PyObject_GetAttrString(instance, "namespaces"); if (pyfunc == NULL) { PyErr_Print(); PyErr_Clear(); debug("Python module does not contain \"namespaces\""); status.fault_code = WSA_ENDPOINT_UNAVAILABLE; status.fault_detail_code = 0; goto cleanup; } if (! PyCallable_Check(pyfunc)) { debug("Python module attribute \"namespaces\" is not callable"); status.fault_code = WSA_ENDPOINT_UNAVAILABLE; status.fault_detail_code = 0; goto cleanup; } pynamespaces = PyObject_CallObject(pyfunc, NULL); if (PyErr_Occurred()) { status.fault_code = WSA_ENDPOINT_UNAVAILABLE; status.fault_detail_code = 0; PyErr_Clear(); goto cleanup; } if (! PyTuple_Check(pynamespaces)) { TARGET_THREAD_BEGIN_ALLOW; debug("Python function \"namespaces\" didn't return a two-tuple"); status.fault_code = WSA_ENDPOINT_UNAVAILABLE; status.fault_detail_code = 0; TARGET_THREAD_END_ALLOW; goto cleanup; } len = PyTuple_Size(pynamespaces); for (i = 0; i < len; ++i) { lnode_t *node; PyObject *ns, *prefix; PyObject* elem = PyTuple_GetItem(pynamespaces, i); if (! PyTuple_Check(elem) || ! (PyTuple_Size(elem) == 2)) { TARGET_THREAD_BEGIN_ALLOW; debug("Python function \"namespaces\" didn't return a list of two-tuple"); status.fault_code = WSA_ENDPOINT_UNAVAILABLE; status.fault_detail_code = 0; TARGET_THREAD_END_ALLOW; goto cleanup; } ns = PyTuple_GetItem(elem, 0); prefix = PyTuple_GetItem(elem, 1); if (!PyString_Check(ns) || !PyString_Check(prefix)) { TARGET_THREAD_BEGIN_ALLOW; debug("Python function \"namespaces\" didn't return a list of [<string>,<string>] tuples"); status.fault_code = WSA_ENDPOINT_UNAVAILABLE; status.fault_detail_code = 0; TARGET_THREAD_END_ALLOW; goto cleanup; } WsSupportedNamespaces *sup_ns = (WsSupportedNamespaces *)u_malloc(sizeof(WsSupportedNamespaces)); sup_ns->ns = PyString_AsString(ns); sup_ns->class_prefix = PyString_AsString(prefix); node = lnode_create(ns); list_append(namespaces, node); } cleanup: if (pyfunc) Py_DecRef(pyfunc); if (pynamespaces) Py_DecRef(pynamespaces); return namespaces; }
static void TimerCalcNextRun(Timer *timer, lnode_t *node) { struct tm *newtime; Timer *CurTimer, *NextTimer; lnode_t *CurNode, *NextNode; newtime = localtime(&timer->lastrun); switch(timer->type) { case TIMER_TYPE_DAILY: newtime->tm_hour = 0; newtime->tm_min = 0; newtime->tm_sec = 0; newtime->tm_mday += 1; break; case TIMER_TYPE_WEEKLY: /* weekly and monthly timers can run at any time */ newtime->tm_mday += 7; break; case TIMER_TYPE_MONTHLY: newtime->tm_mon += 1; break; case TIMER_TYPE_INTERVAL: newtime->tm_sec += timer->interval; break; case TIMER_TYPE_COUNTDOWN: #if 0 if( me.now - timer->lastrun < timer->interval ) { timer->interval -= ( me.now - timer->lastrun ); timer->lastrun = me.now; continue; } #endif newtime->tm_sec += timer->interval; break; } timer->nextrun = mktime(newtime); if (list_count(timerlist) == 0) { /* the list is empty, insert at the top */ node = lnode_create_prepend(timerlist, timer); return; } else { if (!node) node = lnode_create(timer); else list_delete(timerlist, node); } /* now move though the timer list and insert this at the right order */ CurNode = list_first(timerlist); NextNode = list_next(timerlist, CurNode); while (CurNode != NULL) { if (CurNode) CurTimer = lnode_get(CurNode); if (NextNode) { /* if the NextNode is NULL, we are at the end of the list already */ NextTimer = lnode_get(NextNode); } else { /* if the timer is after the CurNode, then */ if (CurTimer->nextrun < timer->nextrun) /* insert it afterwards */ list_ins_after(timerlist, node, CurNode); else /* else insert it before */ list_ins_before(timerlist, node, CurNode); /* and exit the while loop */ break; } /* if the Curent Timer is going to run before this one */ if (CurTimer->nextrun < timer->nextrun) { /* and the next timer is also going to run before this one */ if (NextTimer->nextrun < timer->nextrun) { /* then Swap CurNode for NextNode */ CurNode = NextNode; /* and get a new NextNode */ NextNode = list_next(timerlist, CurNode); } else { /* otherwise insert it after the NextNode */ list_ins_after(timerlist, node, CurNode); break; } } else { /* its before CurTimer, so insert it beforehand */ list_ins_before(timerlist, node, CurNode); break; } } NextSchedule(); }
static inline void Command_extra(Command *cmd, int next, struct params *p) { bstring extra = match_release(p, next, 0); list_append(cmd->extra, lnode_create(extra)); }
/* ** Perform a reduce action and the shift that must immediately ** follow the reduce. */ static void yy_reduce( yyParser *yypParser, /* The parser */ int yyruleno /* Number of the rule by which to reduce */ ){ int yygoto; /* The next state */ int yyact; /* The next action */ YYMINORTYPE yygotominor; /* The LHS of the rule reduced */ yyStackEntry *yymsp; /* The top of the parser's stack */ int yysize; /* Amount to pop the stack */ ParseARG_FETCH; yymsp = &yypParser->yystack[yypParser->yyidx]; #ifndef NDEBUG if( yyTraceFILE && yyruleno>=0 && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt, yyRuleName[yyruleno]); } #endif /* NDEBUG */ /* Silence complaints from purify about yygotominor being uninitialized ** in some cases when it is copied into the stack after the following ** switch. yygotominor is uninitialized when a rule reduces that does ** not set the value of its left-hand side nonterminal. Leaving the ** value of the nonterminal uninitialized is utterly harmless as long ** as the value is never used. So really the only thing this code ** accomplishes is to quieten purify. ** ** 2007-01-16: The wireshark project (www.wireshark.org) reports that ** without this code, their parser segfaults. I'm not sure what there ** parser is doing to make this happen. This is the second bug report ** from wireshark this week. Clearly they are stressing Lemon in ways ** that it has not been previously stressed... (SQLite ticket #2172) */ /*memset(&yygotominor, 0, sizeof(yygotominor));*/ yygotominor = yyzerominor; switch( yyruleno ){ /* Beginning here are the reduction cases. A typical example ** follows: ** case 0: ** #line <lineno> <grammarfile> ** { ... } // User supplied code ** #line <lineno> <thisfile> ** break; */ case 0: /* config ::= vars */ #line 30 "src/parser.y" { state->settings = yymsp[0].minor.yy13; } #line 754 "src/parser.c" break; case 1: /* vars ::= vars assignment */ #line 34 "src/parser.y" { yygotominor.yy13 = tst_insert(yymsp[-1].minor.yy13, bdata(yymsp[0].minor.yy7->key->data), blength(yymsp[0].minor.yy7->key->data), yymsp[0].minor.yy7); } #line 761 "src/parser.c" break; case 2: /* vars ::= assignment */ #line 39 "src/parser.y" { yygotominor.yy13 = tst_insert(yygotominor.yy13, bdata(yymsp[0].minor.yy7->key->data), blength(yymsp[0].minor.yy7->key->data), yymsp[0].minor.yy7); } #line 768 "src/parser.c" break; case 3: /* vars ::= vars EOF */ #line 43 "src/parser.y" { yygotominor.yy13 = yymsp[-1].minor.yy13; yy_destructor(yypParser,1,&yymsp[0].minor); } #line 774 "src/parser.c" break; case 4: /* expr ::= QSTRING */ #line 47 "src/parser.y" { yygotominor.yy8 = Value_create(VAL_QSTRING, yymsp[0].minor.yy0); } #line 779 "src/parser.c" break; case 5: /* expr ::= NUMBER */ #line 48 "src/parser.y" { yygotominor.yy8 = Value_create(VAL_NUMBER, yymsp[0].minor.yy0); } #line 784 "src/parser.c" break; case 6: /* expr ::= class */ #line 49 "src/parser.y" { yygotominor.yy8 = Value_create(VAL_CLASS, yymsp[0].minor.yy11); } #line 789 "src/parser.c" break; case 7: /* expr ::= list */ #line 50 "src/parser.y" { yygotominor.yy8 = Value_create(VAL_LIST, yymsp[0].minor.yy46); } #line 794 "src/parser.c" break; case 8: /* expr ::= hash */ #line 51 "src/parser.y" { yygotominor.yy8 = Value_create(VAL_HASH, yymsp[0].minor.yy13); } #line 799 "src/parser.c" break; case 9: /* expr ::= IDENT */ #line 52 "src/parser.y" { yygotominor.yy8 = Value_create(VAL_REF, yymsp[0].minor.yy0); } #line 804 "src/parser.c" break; case 10: /* assignment ::= IDENT EQ expr */ #line 57 "src/parser.y" { yygotominor.yy7 = malloc(sizeof(Pair)); yygotominor.yy7->key = yymsp[-2].minor.yy0; yygotominor.yy7->value = yymsp[0].minor.yy8; yy_destructor(yypParser,5,&yymsp[-1].minor); } #line 812 "src/parser.c" break; case 11: /* class ::= CLASS LPAREN parameters RPAREN */ #line 64 "src/parser.y" { yygotominor.yy11 = calloc(sizeof(Class), 1); yygotominor.yy11->id = -1; yygotominor.yy11->ident = yymsp[-3].minor.yy0; yygotominor.yy11->params = yymsp[-1].minor.yy13; yy_destructor(yypParser,7,&yymsp[-2].minor); yy_destructor(yypParser,8,&yymsp[0].minor); } #line 819 "src/parser.c" break; case 12: /* parameters ::= parameters COMMA assignment */ #line 69 "src/parser.y" { yygotominor.yy13 = tst_insert(yymsp[-2].minor.yy13, bdata(yymsp[0].minor.yy7->key->data), blength(yymsp[0].minor.yy7->key->data), yymsp[0].minor.yy7); yy_destructor(yypParser,9,&yymsp[-1].minor); } #line 825 "src/parser.c" break; case 13: /* parameters ::= parameters assignment */ #line 72 "src/parser.y" { yygotominor.yy13 = tst_insert(yymsp[-1].minor.yy13, bdata(yymsp[0].minor.yy7->key->data), blength(yymsp[0].minor.yy7->key->data), yymsp[0].minor.yy7); } #line 830 "src/parser.c" break; case 14: /* parameters ::= */ case 22: /* hash_elements ::= */ yytestcase(yyruleno==22); #line 75 "src/parser.y" { yygotominor.yy13 = NULL; } #line 836 "src/parser.c" break; case 15: /* list ::= LBRACE list_elements RBRACE */ #line 79 "src/parser.y" { yygotominor.yy46 = yymsp[-1].minor.yy46; yy_destructor(yypParser,10,&yymsp[-2].minor); yy_destructor(yypParser,11,&yymsp[0].minor); } #line 843 "src/parser.c" break; case 16: /* list_elements ::= list_elements COMMA expr */ #line 83 "src/parser.y" { yygotominor.yy46 = yymsp[-2].minor.yy46; list_append(yygotominor.yy46, lnode_create(yymsp[0].minor.yy8)); yy_destructor(yypParser,9,&yymsp[-1].minor); } #line 849 "src/parser.c" break; case 17: /* list_elements ::= list_elements expr */ #line 86 "src/parser.y" { yygotominor.yy46 = yymsp[-1].minor.yy46; list_append(yygotominor.yy46, lnode_create(yymsp[0].minor.yy8)); } #line 854 "src/parser.c" break; case 18: /* list_elements ::= */ #line 89 "src/parser.y" { yygotominor.yy46 = list_create(LISTCOUNT_T_MAX); } #line 859 "src/parser.c" break; case 19: /* hash ::= LBRACKET hash_elements RBRACKET */ #line 93 "src/parser.y" { yygotominor.yy13 = yymsp[-1].minor.yy13; yy_destructor(yypParser,12,&yymsp[-2].minor); yy_destructor(yypParser,13,&yymsp[0].minor); } #line 866 "src/parser.c" break; case 20: /* hash_elements ::= hash_elements COMMA hash_pair */ #line 97 "src/parser.y" { yygotominor.yy13 = tst_insert(yymsp[-2].minor.yy13, bdata(yymsp[0].minor.yy17->key->data), blength(yymsp[0].minor.yy17->key->data), yymsp[0].minor.yy17); yy_destructor(yypParser,9,&yymsp[-1].minor); } #line 872 "src/parser.c" break; case 21: /* hash_elements ::= hash_elements hash_pair */ #line 100 "src/parser.y" { yygotominor.yy13 = tst_insert(yymsp[-1].minor.yy13, bdata(yymsp[0].minor.yy17->key->data), blength(yymsp[0].minor.yy17->key->data), yymsp[0].minor.yy17); } #line 877 "src/parser.c" break; case 23: /* hash_pair ::= QSTRING COLON expr */ #line 108 "src/parser.y" { yygotominor.yy17 = malloc(sizeof(Pair)); yygotominor.yy17->key = yymsp[-2].minor.yy0; yygotominor.yy17->value = yymsp[0].minor.yy8; yy_destructor(yypParser,14,&yymsp[-1].minor); } #line 885 "src/parser.c" break; default: break; }; yygoto = yyRuleInfo[yyruleno].lhs; yysize = yyRuleInfo[yyruleno].nrhs; yypParser->yyidx -= yysize; yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto); if( yyact < YYNSTATE ){ #ifdef NDEBUG /* If we are not debugging and the reduce action popped at least ** one element off the stack, then we can push the new element back ** onto the stack here, and skip the stack overflow test in yy_shift(). ** That gives a significant speed improvement. */ if( yysize ){ yypParser->yyidx++; yymsp -= yysize-1; yymsp->stateno = (YYACTIONTYPE)yyact; yymsp->major = (YYCODETYPE)yygoto; yymsp->minor = yygotominor; }else #endif { yy_shift(yypParser,yyact,yygoto,&yygotominor); } }else{ assert( yyact == YYNSTATE + YYNRULE + 1 ); yy_accept(yypParser); } }
int main_loop( CamConfig *ccfg, Socket *picture_sock, char *picture_mem ){ Socket *listen_socket; SockSet *readset = NULL, *writeset = NULL; list_t *client_sockets; lnode_t *node; int cfg_listen_port, highest_fd, picture_client_ready; int num_sclients, num_clients; ClientInfo *clientinfo, *clientinfo2; if( (client_sockets = list_create( -1 )) == NULL) return -1; cfg_listen_port = camconfig_query_def_int( ccfg, SEC_SOCKET, "listen_port", CAMCONFIG_DEF_LISTEN_PORT ); if( (readset = sockset_new()) == NULL || (writeset = sockset_new()) == NULL ) { camserv_log( MODNAME, "Error allocating memory for socksets!"); if( readset ) sockset_dest( readset ); if( writeset ) sockset_dest( writeset ); list_destroy( client_sockets ); return -1; } if((listen_socket = socket_serve_tcp( NULL, cfg_listen_port, 100 )) == NULL ) { camserv_log( MODNAME, "Error setting up socket on port \"%d\". Exiting", cfg_listen_port ); list_destroy( client_sockets ); sockset_dest( readset ); sockset_dest( writeset ); return -1; } highest_fd = MAX( socket_query_fd( listen_socket ), socket_query_fd( picture_sock )); clientinfo = clientinfo_new( listen_socket ); clientinfo2 = clientinfo_new( picture_sock ); if( !clientinfo || !clientinfo2 || sockset_add_fd( readset, listen_socket, clientinfo ) == -1 || sockset_add_fd( readset, picture_sock, clientinfo2 ) == -1 ) { camserv_log( MODNAME, "Error adding initial sockets to sockset!"); sockset_dest( readset ); sockset_dest( writeset ); if( clientinfo ) clientinfo_dest( clientinfo ); if( clientinfo2 ) clientinfo_dest( clientinfo2 ); list_destroy( client_sockets ); return -1; } num_clients = 0; num_sclients = 0; picture_client_ready = 1; setup_signals(); Abort = 0; while( !Abort ){ int sel_res, i, nset_socks; void **set_socks; /* Only need to execute this if we have a streaming client */ if( (num_sclients > 0) && picture_client_ready == 1 ){ send( socket_query_fd( picture_sock ), "0", sizeof( "0" ), 0 ); picture_client_ready = 0; } sockset_reset( readset ); sockset_reset( writeset ); sel_res = sockset_select( highest_fd + 1, readset, writeset, NULL ); /* Service the event */ if( sel_res == -1 ){ camserv_log( MODNAME, "select() failure: %s", strerror( errno )); break; } else if( sel_res == 0 ){ camserv_log( MODNAME, "Unexpected select() fall through!" ); continue; } /* Readable sockets */ set_socks = sockset_query_socks( readset ); nset_socks = sockset_query_nsocks( readset ); for( i=0; i< nset_socks; i++ ){ ClientInfo *new_cinfo; clientinfo = set_socks[ i ]; if( clientinfo->socket == listen_socket ) { /* New client */ if( (new_cinfo = accept_client( listen_socket )) == NULL ) continue; if( (node = lnode_create( new_cinfo )) == NULL ){ clientinfo_dest( new_cinfo ); continue; } if( sockset_add_fd( readset, new_cinfo->socket, new_cinfo ) == -1 ){ camserv_log( MODNAME, "Failed to add socket %d to socket read set!", socket_query_fd( new_cinfo->socket )); clientinfo_dest( new_cinfo ); lnode_destroy( node ); continue; } if( socket_query_fd( new_cinfo->socket ) > highest_fd ) highest_fd = socket_query_fd( new_cinfo->socket ); list_append( client_sockets, node ); num_clients++; /* Init resource limit for this client */ new_cinfo->create_time = time( NULL ); new_cinfo->bytes = 0; new_cinfo->frames = 0; new_cinfo->max_seconds = camconfig_query_def_int( ccfg, SEC_SOCKET, "max_seconds", 0 ); new_cinfo->max_bytes = camconfig_query_def_int( ccfg, SEC_SOCKET, "max_bytes", 0 ); new_cinfo->max_frames = camconfig_query_def_int( ccfg, SEC_SOCKET, "max_frames", 0 ); /* Send fresh request for a picture */ send( socket_query_fd( picture_sock ), "0", sizeof( "0" ), 0 ); picture_client_ready = 0; /* Put this read socket on hold until the picture comes back */ sockset_hold( readset, new_cinfo->socket ); } else { char cmdbuf[ 1024 ]; int readlen; clientinfo = set_socks[ i ]; /* Regular joe client, set readable */ if( (readlen = read( socket_query_fd( clientinfo->socket), cmdbuf, sizeof( cmdbuf ) - 1)) <= 0 ) { camserv_log( MODNAME, "Closing socket: %s", socket_query_remote_name( clientinfo->socket )); if (clientinfo->client_type == CLIENT_T_BROWSER || clientinfo->client_type == CLIENT_T_PROXY) { num_sclients--; } client_remove( client_sockets, clientinfo ); sockset_del_fd( readset, clientinfo->socket ); sockset_unhold_all( writeset ); sockset_del_fd( writeset, clientinfo->socket ); clientinfo_dest( clientinfo ); num_clients--; } else { if( clientinfo->socket == picture_sock ) { if( dispatch_pictaker( cmdbuf, picture_mem ) == -1 ) camserv_log( MODNAME, "Pictaker dispatch failure!"); sockset_unhold_all( writeset ); /* Release the read hold as the picture has now been taken */ sockset_unhold_all( readset ); picture_client_ready = 1; } else { /* Information from a regular client */ cmdbuf[ readlen ] = '\0'; if( clientinfo->client_type == CLIENT_T_UNINIT ) { char *preamble; int pre_size; /* Figure out what type of client we have */ if( !strncmp( cmdbuf, "GET", 3 )) { if( strstr( cmdbuf, "/singleframe" )) { clientinfo->client_type = CLIENT_T_SINGLE; } else { clientinfo->client_type = CLIENT_T_BROWSER; num_sclients++; } } else if( !strncmp( cmdbuf, "PROXY", 5 )) { clientinfo->client_type = CLIENT_T_PROXY; /* Here we are in the same state as being done writing a pic */ clientinfo->state = CINFO_STATE_PICTURE; num_sclients++; databuf_buf_set( clientinfo->writebuf, NULL, 0 ); } else clientinfo->client_type = CLIENT_T_BROWSER; if( clientinfo->client_type != CLIENT_T_PROXY ) { /* Send the initial preamble. Only now we can decide which type of preamble to send (single vs. multi-part) */ if( clientinfo->client_type == CLIENT_T_SINGLE ) preamble = get_single_preamble_text( &pre_size ); else preamble = get_multi_preamble_text( &pre_size ); databuf_buf_set( clientinfo->writebuf, preamble, pre_size ); } if( sockset_add_fd( writeset, clientinfo->socket, clientinfo ) == -1 ) { camserv_log( MODNAME, "Failed to add socket %d to write set!", socket_query_fd( clientinfo->socket )); } } } } } } if( set_socks != NULL ) free( set_socks ); /* Writable sockets */ set_socks = sockset_query_socks( writeset ); nset_socks = sockset_query_nsocks( writeset ); for( i=0; i< nset_socks; i++ ){ ClientInfo *cinfo; cinfo = set_socks[ i ]; if( cinfo->client_type == CLIENT_T_BROWSER || cinfo->client_type == CLIENT_T_SINGLE ) { int result; if( (result = write_regular_client( cinfo, writeset )) != 0 ){ /* result: 1=close requested, -1=error detected */ if( result == -1 ) camserv_log( MODNAME, "Databuf write error on socket: %s\n", socket_query_remote_name( cinfo->socket )); if (cinfo->client_type == CLIENT_T_BROWSER) { num_sclients--; } client_remove( client_sockets, cinfo ); sockset_del_fd( readset, cinfo->socket ); sockset_del_fd( writeset, cinfo->socket ); clientinfo_dest( cinfo ); num_clients--; } } else { if( write_proxy_client( cinfo, writeset ) == -1 ){ camserv_log( MODNAME, "Databuf write error on socket: %d", socket_query_fd( cinfo->socket )); /* Should be proxy, but better check */ if (cinfo->client_type == CLIENT_T_PROXY) { num_sclients--; } client_remove( client_sockets, cinfo ); sockset_del_fd( readset, cinfo->socket ); sockset_del_fd( writeset, cinfo->socket ); clientinfo_dest( cinfo ); num_clients--; } } } if( set_socks != NULL ) free( set_socks ); } camserv_log( MODNAME, "Aborting."); sockset_dest( readset ); sockset_dest( writeset ); for( node = list_first( client_sockets) ; node; node=list_next( client_sockets, node )) { clientinfo_dest( node->data ); } /* Tell the picture taker to get out! Get out! */ camserv_log( MODNAME, "Closing picture taker"); send( socket_query_fd( picture_sock ), "9", sizeof( "9" ), 0 ); sleep( 3 ); camserv_log( MODNAME, "done\n"); list_destroy_nodes( client_sockets ); list_destroy( client_sockets ); socket_dest( listen_socket ); return 0; }
CP_C_API cp_context_t * cp_create_context(cp_status_t *error) { cp_plugin_env_t *env = NULL; cp_context_t *context = NULL; cp_status_t status = CP_OK; // Initialize internal state do { // Allocate memory for the plug-in environment if ((env = malloc(sizeof(cp_plugin_env_t))) == NULL) { status = CP_ERR_RESOURCE; break; } // Initialize plug-in environment memset(env, 0, sizeof(cp_plugin_env_t)); #ifdef CP_THREADS env->mutex = cpi_create_mutex(); #endif env->argc = 0; env->argv = NULL; env->plugin_listeners = list_create(LISTCOUNT_T_MAX); env->loggers = list_create(LISTCOUNT_T_MAX); env->log_min_severity = CP_LOG_NONE; env->local_loader = NULL; env->loaders_to_plugins = hash_create(LISTCOUNT_T_MAX, cpi_comp_ptr, cpi_hashfunc_ptr); env->infos = hash_create(HASHCOUNT_T_MAX, cpi_comp_ptr, cpi_hashfunc_ptr); env->plugins = hash_create(HASHCOUNT_T_MAX, (int (*)(const void *, const void *)) strcmp, NULL); env->started_plugins = list_create(LISTCOUNT_T_MAX); env->ext_points = hash_create(HASHCOUNT_T_MAX, (int (*)(const void *, const void *)) strcmp, NULL); env->extensions = hash_create(HASHCOUNT_T_MAX, (int (*)(const void *, const void *)) strcmp, NULL); env->run_funcs = list_create(LISTCOUNT_T_MAX); env->run_wait = NULL; if (env->plugin_listeners == NULL || env->loggers == NULL #ifdef CP_THREADS || env->mutex == NULL #endif || env->loaders_to_plugins == NULL || env->infos == NULL || env->plugins == NULL || env->started_plugins == NULL || env->ext_points == NULL || env->extensions == NULL || env->run_funcs == NULL) { status = CP_ERR_RESOURCE; break; } // Create the plug-in context if ((context = cpi_new_context(NULL, env, &status)) == NULL) { break; } env = NULL; // Create a context list, if necessary, and add context to the list cpi_lock_framework(); if (contexts == NULL) { if ((contexts = list_create(LISTCOUNT_T_MAX)) == NULL) { status = CP_ERR_RESOURCE; } } if (status == CP_OK) { lnode_t *node; if ((node = lnode_create(context)) == NULL) { status = CP_ERR_RESOURCE; } else { list_append(contexts, node); } } cpi_unlock_framework(); } while (0); // Release resources on failure if (status != CP_OK) { if (env != NULL) { free_plugin_env(env); } if (context != NULL) { cpi_free_context(context); } context = NULL; } // Return the final status if (error != NULL) { *error = status; } // Return the context (or NULL on failure) return context; }
int main(void) { input_t in; list_t *l = list_create(LISTCOUNT_T_MAX); lnode_t *ln; char *tok1, *val; int prompt = 0; char *help = "a <val> append value to list\n" "d <val> delete value from list\n" "l <val> lookup value in list\n" "s sort list\n" "c show number of entries\n" "t dump whole list\n" "p turn prompt on\n" "q quit"; if (!l) puts("list_create failed"); for (;;) { if (prompt) putchar('>'); fflush(stdout); if (!fgets(in, sizeof(input_t), stdin)) break; switch(in[0]) { case '?': puts(help); break; case 'a': if (tokenize(in+1, &tok1, (char **) 0) != 1) { puts("what?"); break; } val = dupstring(tok1); ln = lnode_create(val); if (!val || !ln) { puts("allocation failure"); if (ln) lnode_destroy(ln); free(val); break; } list_append(l, ln); break; case 'd': if (tokenize(in+1, &tok1, (char **) 0) != 1) { puts("what?"); break; } ln = list_find(l, tok1, comparef); if (!ln) { puts("list_find failed"); break; } list_delete(l, ln); val = (char *) lnode_get(ln); lnode_destroy(ln); free(val); break; case 'l': if (tokenize(in+1, &tok1, (char **) 0) != 1) { puts("what?"); break; } ln = list_find(l, tok1, comparef); if (!ln) puts("list_find failed"); else puts("found"); break; case 's': list_sort(l, comparef); break; case 'c': printf("%lu\n", (unsigned long) list_count(l)); break; case 't': for (ln = list_first(l); ln != 0; ln = list_next(l, ln)) puts((char *) lnode_get(ln)); break; case 'q': exit(0); break; case '\0': break; case 'p': prompt = 1; break; default: putchar('?'); putchar('\n'); break; } } return 0; }