int sam_usbhost_initialize(void) { pid_t pid; int ret; /* First, register all of the class drivers needed to support the drivers * that we care about: */ ret = usbhost_storageinit(); if (ret != OK) { udbg("ERROR: Failed to register the mass storage class: %d\n", ret); } #ifdef CONFIG_SAMA5_OHCI /* Get an instance of the USB OHCI interface */ g_ohciconn = sam_ohci_initialize(0); if (!g_ohciconn) { udbg("ERROR: sam_ohci_initialize failed\n"); return -ENODEV; } /* Start a thread to handle device connection. */ pid = TASK_CREATE("usbhost", CONFIG_USBHOST_DEFPRIO, CONFIG_USBHOST_STACKSIZE, (main_t)ohci_waiter, (FAR char * const *)NULL); if (pid < 0) { udbg("ERROR: Failed to create ohci_waiter task: %d\n", ret); return -ENODEV; } #endif #ifdef CONFIG_SAMA5_EHCI /* Get an instance of the USB EHCI interface */ g_ehciconn = sam_ehci_initialize(0); if (!g_ehciconn) { udbg("ERROR: sam_ehci_initialize failed\n"); return -ENODEV; } /* Start a thread to handle device connection. */ pid = TASK_CREATE("usbhost", CONFIG_USBHOST_DEFPRIO, CONFIG_USBHOST_STACKSIZE, (main_t)ehci_waiter, (FAR char * const *)NULL); if (pid < 0) { udbg("ERROR: Failed to create ehci_waiter task: %d\n", ret); return -ENODEV; } #endif return OK; }
int stm32_usbhost_initialize(void) { int pid; int ret; /* First, register all of the class drivers needed to support the drivers * that we care about: */ uvdbg("Register class drivers\n"); ret = usbhost_storageinit(); if (ret != OK) { udbg("Failed to register the mass storage class\n"); } /* Then get an instance of the USB host interface */ uvdbg("Initialize USB host\n"); g_drvr = usbhost_initialize(0); if (g_drvr) { /* Start a thread to handle device connection. */ uvdbg("Start usbhost_waiter\n"); pid = TASK_CREATE("usbhost", CONFIG_USBHOST_DEFPRIO, CONFIG_USBHOST_STACKSIZE, (main_t)usbhost_waiter, (FAR char * const *)NULL); return pid < 0 ? -ENOEXEC : OK; } return -ENODEV; }
int ftpd_main(int s_argc, char **s_argv) { /* Check if we have already initialized the network */ if (!g_ftpdglob.initialized) { /* Bring up the network */ printf("Initializing the network\n"); fptd_netinit(); /* Initialize daemon state */ g_ftpdglob.initialized = true; g_ftpdglob.pid = -1; #ifdef CONFIG_NSH_BUILTIN_APPS g_ftpdglob.stop = false; g_ftpdglob.running = false; #endif } /* Then start the new daemon (if it is not already running) */ #ifdef CONFIG_NSH_BUILTIN_APPS if (g_ftpdglob.stop && g_ftpdglob.running) { printf("Waiting for FTP daemon [%d] to stop\n", g_ftpdglob.pid); return EXIT_FAILURE; } else #endif if (!g_ftpdglob.running) { printf("Starting the FTP daemon\n"); g_ftpdglob.pid = TASK_CREATE("FTP daemon", CONFIG_EXAMPLES_FTPD_PRIO, CONFIG_EXAMPLES_FTPD_STACKSIZE, ftpd_daemon, NULL); if (g_ftpdglob.pid < 0) { printf("Failed to start the FTP daemon: %d\n", errno); return EXIT_FAILURE; } } else { printf("FTP daemon [%d] is running\n", g_ftpdglob.pid); } return EXIT_SUCCESS; }
int os_bringup(void) { int taskid; /* Setup up the initial environment for the idle task. At present, this * may consist of only the initial PATH variable. The PATH variable is * (probably) not used by the IDLE task. However, the environment * containing the PATH variable will be inherited by all of the threads * created by the IDLE task. */ #if !defined(CONFIG_DISABLE_ENVIRON) && defined(CONFIG_PATH_INITIAL) (void)setenv("PATH", CONFIG_PATH_INITIAL, 1); #endif /* Start the page fill worker kernel thread that will resolve page faults. * This should always be the first thread started because it may have to * resolve page faults in other threads */ #ifdef CONFIG_PAGING svdbg("Starting paging thread\n"); g_pgworker = KERNEL_THREAD("pgfill", CONFIG_PAGING_DEFPRIO, CONFIG_PAGING_STACKSIZE, (main_t)pg_worker, (FAR char * const *)NULL); DEBUGASSERT(g_pgworker > 0); #endif /* Start the worker thread that will serve as the device driver "bottom- * half" and will perform misc garbage clean-up. */ #ifdef CONFIG_SCHED_WORKQUEUE #ifdef CONFIG_SCHED_HPWORK #ifdef CONFIG_SCHED_LPWORK svdbg("Starting high-priority kernel worker thread\n"); #else svdbg("Starting kernel worker thread\n"); #endif g_work[HPWORK].pid = KERNEL_THREAD(HPWORKNAME, CONFIG_SCHED_WORKPRIORITY, CONFIG_SCHED_WORKSTACKSIZE, (main_t)work_hpthread, (FAR char * const *)NULL); DEBUGASSERT(g_work[HPWORK].pid > 0); /* Start a lower priority worker thread for other, non-critical continuation * tasks */ #ifdef CONFIG_SCHED_LPWORK svdbg("Starting low-priority kernel worker thread\n"); g_work[LPWORK].pid = KERNEL_THREAD(LPWORKNAME, CONFIG_SCHED_LPWORKPRIORITY, CONFIG_SCHED_LPWORKSTACKSIZE, (main_t)work_lpthread, (FAR char * const *)NULL); DEBUGASSERT(g_work[LPWORK].pid > 0); #endif /* CONFIG_SCHED_LPWORK */ #endif /* CONFIG_SCHED_HPWORK */ #if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_SCHED_USRWORK) /* Start the user-space work queue */ DEBUGASSERT(USERSPACE->work_usrstart != NULL); taskid = USERSPACE->work_usrstart(); DEBUGASSERT(taskid > 0); #endif #endif /* CONFIG_SCHED_WORKQUEUE */ /* Once the operating system has been initialized, the system must be * started by spawning the user init thread of execution. This is the * first user-mode thead. */ svdbg("Starting init thread\n"); /* Perform any last-minute, board-specific initialization, if so * configured. */ #ifdef CONFIG_BOARD_INITIALIZE board_initialize(); #endif /* Start the default application. In a flat build, this is entrypoint * is given by the definitions, CONFIG_USER_ENTRYPOINT. In the kernel * build, however, we must get the address of the entrypoint from the * header at the beginning of the user-space blob. */ #ifdef CONFIG_NUTTX_KERNEL DEBUGASSERT(USERSPACE->us_entrypoint != NULL); taskid = TASK_CREATE("init", SCHED_PRIORITY_DEFAULT, CONFIG_USERMAIN_STACKSIZE, USERSPACE->us_entrypoint, (FAR char * const *)NULL); #else taskid = TASK_CREATE("init", SCHED_PRIORITY_DEFAULT, CONFIG_USERMAIN_STACKSIZE, (main_t)CONFIG_USER_ENTRYPOINT, (FAR char * const *)NULL); #endif ASSERT(taskid > 0); /* We an save a few bytes by discarding the IDLE thread's environment. */ #if !defined(CONFIG_DISABLE_ENVIRON) && defined(CONFIG_PATH_INITIAL) (void)clearenv(); #endif return OK; }
int os_bringup(void) { int init_taskid; /* Setup up the initial environment for the idle task. At present, this * may consist of only the initial PATH variable. The PATH variable is * (probably) not used by the IDLE task. However, the environment * containing the PATH variable will be inherited by all of the threads * created by the IDLE task. */ #if !defined(CONFIG_DISABLE_ENVIRON) && defined(CONFIG_PATH_INITIAL) (void)setenv("PATH", CONFIG_PATH_INITIAL, 1); #endif /* Start the page fill worker kernel thread that will resolve page faults. * This should always be the first thread started because it may have to * resolve page faults in other threads */ #ifdef CONFIG_PAGING svdbg("Starting paging thread\n"); g_pgworker = KERNEL_THREAD("pgfill", CONFIG_PAGING_DEFPRIO, CONFIG_PAGING_STACKSIZE, (main_t)pg_worker, (const char **)NULL); ASSERT(g_pgworker != ERROR); #endif /* Start the worker thread that will serve as the device driver "bottom- * half" and will perform misc garbage clean-up. */ #ifdef CONFIG_SCHED_WORKQUEUE svdbg("Starting worker thread\n"); g_work[HPWORK].pid = KERNEL_THREAD("work0", CONFIG_SCHED_WORKPRIORITY, CONFIG_SCHED_WORKSTACKSIZE, (main_t)work_hpthread, (const char **)NULL); ASSERT(g_work[HPWORK].pid != ERROR); /* Start a lower priority worker thread for other, non-critical continuation * tasks */ #ifdef CONFIG_SCHED_LPWORK svdbg("Starting worker thread\n"); g_work[LPWORK].pid = KERNEL_THREAD("work1", CONFIG_SCHED_LPWORKPRIORITY, CONFIG_SCHED_LPWORKSTACKSIZE, (main_t)work_lpthread, (const char **)NULL); ASSERT(g_work[LPWORK].pid != ERROR); #endif #endif /* Once the operating system has been initialized, the system must be * started by spawning the user init thread of execution. This is the * first user-mode thead. */ svdbg("Starting init thread\n"); /* Start the default application at CONFIG_USER_ENTRYPOINT() */ init_taskid = TASK_CREATE("init", SCHED_PRIORITY_DEFAULT, CONFIG_USERMAIN_STACKSIZE, (main_t)CONFIG_USER_ENTRYPOINT, (const char **)NULL); ASSERT(init_taskid != ERROR); /* We an save a few bytes by discarding the IDLE thread's environment. */ #if !defined(CONFIG_DISABLE_ENVIRON) && defined(CONFIG_PATH_INITIAL) (void)clearenv(); #endif return OK; }
int posix_spawn(FAR pid_t *pid, FAR const char *path, FAR const posix_spawn_file_actions_t *file_actions, FAR const posix_spawnattr_t *attr, FAR char *const argv[], FAR char *const envp[]) #endif { struct sched_param param; pid_t proxy; #ifdef CONFIG_SCHED_WAITPID int status; #endif int ret; DEBUGASSERT(path); svdbg("pid=%p path=%s file_actions=%p attr=%p argv=%p\n", pid, path, file_actions, attr, argv); /* If there are no file actions to be performed and there is no change to * the signal mask, then start the new child task directly from the parent task. */ #ifndef CONFIG_DISABLE_SIGNALS if ((file_actions == NULL || *file_actions == NULL) && (attr == NULL || (attr->flags & POSIX_SPAWN_SETSIGMASK) == 0)) #else if (file_actions == NULL || *file_actions == NULL) #endif { return spawn_exec(pid, path, attr, argv); } /* Otherwise, we will have to go through an intermediary/proxy task in order * to perform the I/O redirection. This would be a natural place to fork(). * However, true fork() behavior requires an MMU and most implementations * of vfork() are not capable of these operations. * * Even without fork(), we can still do the job, but parameter passing is * messier. Unfortunately, there is no (clean) way to pass binary values * as a task parameter, so we will use a semaphore-protected global * structure. */ /* Get exclusive access to the global parameter structure */ spawn_semtake(&g_ps_parmsem); /* Populate the parameter structure */ g_ps_parms.result = ENOSYS; g_ps_parms.pid = pid; g_ps_parms.path = path; g_ps_parms.file_actions = file_actions; g_ps_parms.attr = attr; g_ps_parms.argv = argv; /* Get the priority of this (parent) task */ ret = sched_getparam(0, ¶m); if (ret < 0) { int errcode = errno; sdbg("ERROR: sched_getparam failed: %d\n", errcode); spawn_semgive(&g_ps_parmsem); return errcode; } /* Disable pre-emption so that the proxy does not run until we waitpid * is called. This is probably unnecessary since the spawn_proxy has * the same priority as this thread; it should be schedule behind this * task in the ready-to-run list. */ #ifdef CONFIG_SCHED_WAITPID sched_lock(); #endif /* Start the intermediary/proxy task at the same priority as the parent * task. */ proxy = TASK_CREATE("spawn_proxy", param.sched_priority, CONFIG_POSIX_SPAWN_STACKSIZE, (main_t)spawn_proxy, (FAR const char **)NULL); if (proxy < 0) { ret = get_errno(); sdbg("ERROR: Failed to start spawn_proxy: %d\n", ret); goto errout_with_lock; } /* Wait for the proxy to complete its job */ #ifdef CONFIG_SCHED_WAITPID ret = waitpid(proxy, &status, 0); if (ret < 0) { sdbg("ERROR: waitpid() failed: %d\n", errno); goto errout_with_lock; } #else spawn_semtake(&g_ps_execsem); #endif /* Get the result and relinquish our access to the parameter structure */ ret = g_ps_parms.result; errout_with_lock: #ifdef CONFIG_SCHED_WAITPID sched_unlock(); #endif spawn_semgive(&g_ps_parmsem); return ret; }
static int telnetd_daemon(int argc, char *argv[]) { FAR struct telnetd_s *daemon; struct sockaddr_in myaddr; #ifdef CONFIG_NET_SOLINGER struct linger ling; #endif socklen_t addrlen; FAR char *devpath; pid_t pid; int listensd; int acceptsd; int drvrfd; #ifdef CONFIG_NET_HAVE_REUSEADDR int optval; #endif /* Get daemon startup info */ daemon = g_telnetdcommon.daemon; g_telnetdcommon.daemon = NULL; sem_post(&g_telnetdcommon.startsem); DEBUGASSERT(daemon != NULL); /* Create a new TCP socket to use to listen for connections */ listensd = socket(PF_INET, SOCK_STREAM, 0); if (listensd < 0) { int errval = errno; ndbg("socket failure: %d\n", errval); return -errval; } /* Set socket to reuse address */ #ifdef CONFIG_NET_HAVE_REUSEADDR optval = 1; if (setsockopt(listensd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int)) < 0) { ndbg("setsockopt SO_REUSEADDR failure: %d\n", errno); goto errout_with_socket; } #endif /* Bind the socket to a local address */ myaddr.sin_family = AF_INET; myaddr.sin_port = daemon->port; myaddr.sin_addr.s_addr = INADDR_ANY; if (bind(listensd, (struct sockaddr*)&myaddr, sizeof(struct sockaddr_in)) < 0) { ndbg("bind failure: %d\n", errno); goto errout_with_socket; } /* Listen for connections on the bound TCP socket */ if (listen(listensd, 5) < 0) { ndbg("listen failure %d\n", errno); goto errout_with_socket; } /* Now go silent. Only the lldbg family of debug functions should * be used after this point because these do not depend on stdout * being available. */ #ifndef CONFIG_DEBUG close(0); close(1); close(2); #endif /* Begin accepting connections */ for (;;) { nllvdbg("Accepting connections on port %d\n", ntohs(daemon->port)); addrlen = sizeof(struct sockaddr_in); acceptsd = accept(listensd, (struct sockaddr*)&myaddr, &addrlen); if (acceptsd < 0) { nlldbg("accept failed: %d\n", errno); goto errout_with_socket; } /* Configure to "linger" until all data is sent when the socket is closed */ #ifdef CONFIG_NET_SOLINGER ling.l_onoff = 1; ling.l_linger = 30; /* timeout is seconds */ if (setsockopt(acceptsd, SOL_SOCKET, SO_LINGER, &ling, sizeof(struct linger)) < 0) { nlldbg("setsockopt failed: %d\n", errno); goto errout_with_acceptsd; } #endif /* Create a character device to "wrap" the accepted socket descriptor */ nllvdbg("Creating the telnet driver\n"); devpath = telnetd_driver(acceptsd, daemon); if (devpath < 0) { nlldbg("telnetd_driver failed\n"); goto errout_with_acceptsd; } /* Open the driver */ nllvdbg("Opening the telnet driver\n"); drvrfd = open(devpath, O_RDWR); if (drvrfd < 0) { nlldbg("Failed to open %s: %d\n", devpath, errno); goto errout_with_acceptsd; } /* We can now free the driver string */ free(devpath); /* Use this driver as stdin, stdout, and stderror */ (void)dup2(drvrfd, 0); (void)dup2(drvrfd, 1); (void)dup2(drvrfd, 2); /* And we can close our original driver fd */ if (drvrfd > 2) { close(drvrfd); } /* Create a task to handle the connection. The created task * will inherit the new stdin, stdout, and stderr. */ nllvdbg("Starting the telnet session\n"); pid = TASK_CREATE("Telnet session", daemon->priority, daemon->stacksize, daemon->entry, NULL); if (pid < 0) { nlldbg("Failed start the telnet session: %d\n", errno); goto errout_with_acceptsd; } /* Forget about the connection. */ close(0); close(1); close(2); } errout_with_acceptsd: close(acceptsd); errout_with_socket: close(listensd); free(daemon); return 1; }
int telnetd_start(FAR struct telnetd_config_s *config) { FAR struct telnetd_s *daemon; pid_t pid; int ret; /* Allocate a state structure for the new daemon */ daemon = (FAR struct telnetd_s *)malloc(sizeof(struct telnetd_s)); if (!daemon) { return -ENOMEM; } /* Initialize the daemon structure */ daemon->port = config->d_port; daemon->priority = config->t_priority; daemon->stacksize = config->t_stacksize; daemon->entry = config->t_entry; /* Initialize the common structure if this is the first daemon */ if (g_telnetdcommon.ndaemons < 1) { sem_init(&g_telnetdcommon.startsem, 0, 0); sem_init(&g_telnetdcommon.exclsem, 0, 1); g_telnetdcommon.minor = 0; } /* Then start the new daemon */ g_telnetdcommon.daemon = daemon; pid = TASK_CREATE("Telnet daemon", config->d_priority, config->d_stacksize, telnetd_daemon, NULL); if (pid < 0) { int errval = errno; free(daemon); ndbg("Failed to start the telnet daemon: %d\n", errval); return -errval; } /* Then wait for the daemon to start and complete the handshake */ do { ret = sem_wait(&g_telnetdcommon.startsem); /* The only expected error condition is for sem_wait to be awakened by * a receipt of a signal. */ if (ret < 0) { DEBUGASSERT(errno == -EINTR); } } while (ret < 0); /* Return success */ return pid; }
int nxcon_main(int argc, char **argv) { nxgl_mxpixel_t color; int fd; int ret; /* General Initialization *************************************************/ /* Reset all global data */ message("nxcon_main: Started\n"); memset(&g_nxcon_vars, 0, sizeof(struct nxcon_state_s)); /* Call all C++ static constructors */ #if defined(CONFIG_HAVE_CXX) && defined(CONFIG_HAVE_CXXINITIALIZE) up_cxxinitialize(); #endif /* NSH Initialization *****************************************************/ /* Initialize the NSH library */ message("nxcon_main: Initialize NSH\n"); nsh_initialize(); /* If the Telnet console is selected as a front-end, then start the * Telnet daemon. */ #ifdef CONFIG_NSH_TELNET ret = nsh_telnetstart(); if (ret < 0) { /* The daemon is NOT running. Report the the error then fail... * either with the serial console up or just exiting. */ fprintf(stderr, "ERROR: Failed to start TELNET daemon: %d\n", ret); } #endif /* NX Initialization ******************************************************/ /* Initialize NX */ message("nxcon_main: Initialize NX\n"); ret = nxcon_initialize(); message("nxcon_main: NX handle=%p\n", g_nxcon_vars.hnx); if (!g_nxcon_vars.hnx || ret < 0) { message("nxcon_main: Failed to get NX handle: %d\n", errno); goto errout; } /* Set the background to the configured background color */ message("nxcon_main: Set background color=%d\n", CONFIG_EXAMPLES_NXCON_BGCOLOR); color = CONFIG_EXAMPLES_NXCON_BGCOLOR; ret = nx_setbgcolor(g_nxcon_vars.hnx, &color); if (ret < 0) { message("nxcon_main: nx_setbgcolor failed: %d\n", errno); goto errout_with_nx; } /* Window Configuration ***************************************************/ /* Create a window */ message("nxcon_main: Create window\n"); g_nxcon_vars.hwnd = nxtk_openwindow(g_nxcon_vars.hnx, &g_nxconcb, NULL); if (!g_nxcon_vars.hwnd) { message("nxcon_main: nxtk_openwindow failed: %d\n", errno); goto errout_with_nx; } message("nxcon_main: hwnd=%p\n", g_nxcon_vars.hwnd); /* Wait until we have the screen resolution. We'll have this immediately * unless we are dealing with the NX server. */ while (!g_nxcon_vars.haveres) { (void)sem_wait(&g_nxcon_vars.eventsem); } message("nxcon_main: Screen resolution (%d,%d)\n", g_nxcon_vars.xres, g_nxcon_vars.yres); /* Determine the size and position of the window */ g_nxcon_vars.wndo.wsize.w = g_nxcon_vars.xres / 2 + g_nxcon_vars.xres / 4; g_nxcon_vars.wndo.wsize.h = g_nxcon_vars.yres / 2 + g_nxcon_vars.yres / 4; g_nxcon_vars.wpos.x = g_nxcon_vars.xres / 8; g_nxcon_vars.wpos.y = g_nxcon_vars.yres / 8; /* Set the window position */ message("nxcon_main: Set window position to (%d,%d)\n", g_nxcon_vars.wpos.x, g_nxcon_vars.wpos.y); ret = nxtk_setposition(g_nxcon_vars.hwnd, &g_nxcon_vars.wpos); if (ret < 0) { message("nxcon_main: nxtk_setposition failed: %d\n", errno); goto errout_with_hwnd; } /* Set the window size */ message("nxcon_main: Set window size to (%d,%d)\n", g_nxcon_vars.wndo.wsize.w, g_nxcon_vars.wndo.wsize.h); ret = nxtk_setsize(g_nxcon_vars.hwnd, &g_nxcon_vars.wndo.wsize); if (ret < 0) { message("nxcon_main: nxtk_setsize failed: %d\n", errno); goto errout_with_hwnd; } /* Open the toolbar */ message("nxcon_main: Add toolbar to window\n"); ret = nxtk_opentoolbar(g_nxcon_vars.hwnd, CONFIG_EXAMPLES_NXCON_TOOLBAR_HEIGHT, &g_nxtoolcb, NULL); if (ret < 0) { message("nxcon_main: nxtk_opentoolbar failed: %d\n", errno); goto errout_with_hwnd; } /* Sleep a little bit to allow the server to catch up */ sleep(2); /* NxConsole Configuration ************************************************/ /* Use the window to create an NX console */ g_nxcon_vars.wndo.wcolor[0] = CONFIG_EXAMPLES_NXCON_WCOLOR; g_nxcon_vars.wndo.fcolor[0] = CONFIG_EXAMPLES_NXCON_FONTCOLOR; g_nxcon_vars.wndo.fontid = CONFIG_EXAMPLES_NXCON_FONTID; g_nxcon_vars.hdrvr = nxtk_register(g_nxcon_vars.hwnd, &g_nxcon_vars.wndo, CONFIG_EXAMPLES_NXCON_MINOR); if (!g_nxcon_vars.hdrvr) { message("nxcon_main: nxtk_register failed: %d\n", errno); goto errout_with_hwnd; } /* Open the NxConsole driver */ fd = open(CONFIG_EXAMPLES_NXCON_DEVNAME, O_WRONLY); if (fd < 0) { message("nxcon_main: open %s read-only failed: %d\n", CONFIG_EXAMPLES_NXCON_DEVNAME, errno); goto errout_with_driver; } /* Start Console Task *****************************************************/ /* Now re-direct stdout and stderr so that they use the NX console driver. * Note that stdin is retained (file descriptor 0, probably the the serial console). */ message("nxcon_main: Starting the console task\n"); msgflush(); (void)fflush(stdout); (void)fflush(stderr); (void)fclose(stdout); (void)fclose(stderr); (void)dup2(fd, 1); (void)dup2(fd, 2); /* And we can close our original driver file descriptor */ close(fd); /* And start the console task. It will inherit stdin, stdout, and stderr * from this task. */ g_nxcon_vars.pid = TASK_CREATE("NxConsole", CONFIG_EXAMPLES_NXCONSOLE_PRIO, CONFIG_EXAMPLES_NXCONSOLE_STACKSIZE, nxcon_task, NULL); ASSERT(g_nxcon_vars.pid > 0); return EXIT_SUCCESS; /* Error Exits ************************************************************/ errout_with_driver: (void)nxcon_unregister(g_nxcon_vars.hdrvr); errout_with_hwnd: (void)nxtk_closewindow(g_nxcon_vars.hwnd); errout_with_nx: /* Disconnect from the server */ nx_disconnect(g_nxcon_vars.hnx); errout: return EXIT_FAILURE; }