/** * close_context * * Arguments: <context_id> * * Close the context's file descriptor, remove it from the global list, and * free the context data structures. **/ static int close_context(int argc, char **argv) { struct context *ctx; struct event_set *evt, *next_evt; int ctx_id; ctx_id = strtoul(argv[1], NULL, 0); if (ctx_id <= 0) { LOG_ERROR("context ID must be a positive integer."); return EINVAL; } ctx = find_context(ctx_id); if (!ctx) { LOG_ERROR("Can't find context with ID %d.", ctx_id); return EINVAL; } /* There's no perfmon system-call to delete a context. We simply call * close on the file handle. */ close(ctx->fd); remove_context(ctx); for (evt = ctx->event_sets; evt; evt = next_evt) { next_evt = evt->next; free(evt); } free(ctx); LOG_INFO("Closed and freed context %d.", ctx_id); return 0; }
static void TCPCOMM_detachThread(int socket, CONST CMPIBroker * broker, CONST CMPIContext * context) { CMPIStatus rc; CMPIData ctxid = CMGetContextEntry(context, RCMPI_CTX_ID, NULL); CONST CMPIContext *ctx = get_context(ctxid.value.uint32); remove_context(ctxid.value.uint32); rc = CBDetachThread(broker, ctx); (__sft)->serialize_CMPIStatus(socket, &rc); }
/* Process the raw netlink message and dispatch to helper functions * accordingly */ static void receive_netlink_message (GUPnPLinuxContextManager *self, GError **error) { static char buf[4096]; static const int bufsize = 4096; gssize len; GError *inner_error = NULL; struct nlmsghdr *header = (struct nlmsghdr *) buf; struct ifinfomsg *ifi; struct ifaddrmsg *ifa; len = g_socket_receive (self->priv->netlink_socket, buf, bufsize, NULL, &inner_error); if (len == -1) { if (inner_error->code != G_IO_ERROR_WOULD_BLOCK) g_warning ("Error receiving netlink message: %s", inner_error->message); g_propagate_error (error, inner_error); return; } for (;NLMSG_IS_VALID (header, len); header = NLMSG_NEXT (header,len)) { switch (header->nlmsg_type) { /* RTM_NEWADDR and RTM_DELADDR are sent on real address * changes. * RTM_NEWLINK is sent on varous occations: * - Creation of a new device * - Device goes up/down * - Wireless status changes * RTM_DELLINK is sent only if device is removed, like * openvpn --rmtun /dev/tun0, NOT on ifconfig down. */ case RTM_NEWADDR: { char *label = NULL; ifa = NLMSG_DATA (header); extract_info (header, &label); create_context (self, label, ifa); g_free (label); } break; case RTM_DELADDR: { char *label = NULL; ifa = NLMSG_DATA (header); extract_info (header, &label); remove_context (self, label, ifa); g_free (label); } break; case RTM_NEWLINK: ifi = NLMSG_DATA (header); /* Check if wireless is up for chit-chat */ if (is_wireless_status_message (header)) continue; handle_device_status_change (self, ifi); break; case RTM_DELLINK: ifi = NLMSG_DATA (header); remove_device (self, ifi); break; case NLMSG_ERROR: break; default: break; } } }
int main(int argc, char *argv[]) { int i; int rc; pid_t pid, retpid; int status; char *program; char *pdesc; char *pc; int pw_pipe; int expire_delta; int refresh_time; /* call me redundant, but it's satisfying to see this */ handler_refreshed_context = 0; have_login_context = 0; pid = 0; /*test for real deal or just version and exit*/ PRINT_VERSION_AND_EXIT(argc, argv); if (argc < 3) { fprintf(stderr, "usage: %s user program [arg(s)]\n", argv[0]); fprintf(stderr, " %s --version\n", argv[0]); exit(254); } /* In the event we inherited creds from the parent, ignore them. */ if (getenv("KRB5CCNAME") != NULL) { unsetenv("KRB5CCNAME"); } /* read password from descriptor, close descriptor */ if ((pdesc = getenv("PBS_PWPIPE")) == NULL) { fprintf(stderr, "PBS_PWPIPE not in the environment\n"); exit (254); } pw_pipe = atoi(pdesc); if (errno != 0) { fprintf(stderr, "Value of PBS_PWPIPE is bad\n"); exit (254); } for (;;) { i = read(pw_pipe, &tmp_passwd[0], sec_passwd_str_max_len); if (i == -1 && errno == EINTR) continue; break; } close(pw_pipe); username = argv[1]; program = strdup(argv[2]); /* when execv-ing a shell interpreter, cause it to be a login shell */ if (argc == 3) { if (pc = strrchr(argv[2], (int)'/')) { *pc = '-'; argv[2] = pc; } } /* Attempt to establish login context for user */ if (rc=establish_login_context(username)) { have_login_context = 0; } else { have_login_context = 1; rc=252; } /* * If we have a login context, fork the child that will become * the job. The parent sticks around to refresh the context * periodically. * * If we don't have a login context, exec the job over ourself. */ if (have_login_context) { if ((pid = fork()) == -1) { perror("fork"); (void)remove_context(); exit(254); } } if (pid == 0) { /* exec the program */ if (execv(program, &argv[2]) == -1) { /* execv system call failed */ perror("execv"); fprintf(stderr, "pbs_dcelogin: execv system call failed\n"); exit(rc); } /* child should never get here */ exit(99); } /* * go into a loop which will every so often refresh the * the DCE login context while it waits for the child to terminate */ refresh_time = compute_refresh_time(lcon); for (;;) { if ((retpid = waitpid(pid, &status, WNOHANG)) == -1) { perror("pbs_dcelogin: waitpid"); break; } else if (retpid > 0) /* child finished */ break; /* see if it is time to refresh */ if (0 < refresh_time && refresh_time <= time(NULL)) refresh_time = do_refresh(lcon); sleep(5); } /* after removing any created DCE login context and credential cache * files, pass back the exit status of the job */ (void)remove_context(); if (retpid == pid) { if (WIFEXITED(status)) { exit(WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { exit(WTERMSIG(status)); } else if (WIFSTOPPED(status)) { exit(WSTOPSIG(status)); } else { exit(253); } } else { exit(254); } }