/* * Call after adding all arguments and environment settings, but before * Run/RunAsync, to immediately output the environment and arguments of * cmd to logfd. If virCommandRun cannot succeed (because of an * out-of-memory condition while building cmd), nothing will be logged. */ void virCommandWriteArgLog(virCommandPtr cmd, int logfd) { int ioError = 0; size_t i; /* Any errors will be reported later by virCommandRun, which means * no command will be run, so there is nothing to log. */ if (!cmd || cmd->has_error) return; for (i = 0 ; i < cmd->nenv ; i++) { if (safewrite(logfd, cmd->env[i], strlen(cmd->env[i])) < 0) ioError = errno; if (safewrite(logfd, " ", 1) < 0) ioError = errno; } for (i = 0 ; i < cmd->nargs ; i++) { if (safewrite(logfd, cmd->args[i], strlen(cmd->args[i])) < 0) ioError = errno; if (safewrite(logfd, i == cmd->nargs - 1 ? "\n" : " ", 1) < 0) ioError = errno; } if (ioError) { char ebuf[1024]; VIR_WARN("Unable to write command %s args to logfile: %s", cmd->args[0], virStrerror(ioError, ebuf, sizeof ebuf)); } }
static int openvzWriteConfigParam(const char * conf_file, const char *param, const char *value) { char * temp_file = NULL; int temp_fd = -1; FILE *fp; char *line = NULL; size_t line_size = 0; if (virAsprintf(&temp_file, "%s.tmp", conf_file)<0) { virReportOOMError(); return -1; } fp = fopen(conf_file, "r"); if (fp == NULL) goto error; temp_fd = open(temp_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (temp_fd == -1) { goto error; } while (1) { if (getline(&line, &line_size, fp) <= 0) break; if (!(STRPREFIX(line, param) && line[strlen(param)] == '=')) { if (safewrite(temp_fd, line, strlen(line)) != strlen(line)) goto error; } } if (safewrite(temp_fd, param, strlen(param)) < 0 || safewrite(temp_fd, "=\"", 2) < 0 || safewrite(temp_fd, value, strlen(value)) < 0 || safewrite(temp_fd, "\"\n", 2) < 0) goto error; if (VIR_FCLOSE(fp) < 0) goto error; if (VIR_CLOSE(temp_fd) < 0) goto error; if (rename(temp_file, conf_file) < 0) goto error; VIR_FREE(line); return 0; error: VIR_FREE(line); VIR_FORCE_FCLOSE(fp); VIR_FORCE_CLOSE(temp_fd); if (temp_file) unlink(temp_file); VIR_FREE(temp_file); return -1; }
int write_sf_packet(int fd, const void *packet, int len) /* Effects: writes len byte packet to serial forwarder on file descriptor fd Returns: 0 if packet successfully written, -1 otherwise */ { unsigned char l = len; if (safewrite(fd, &l, 1) != 1 || safewrite(fd, packet, l) != l) return -1; return 0; }
int virshStreamSink(virStreamPtr st ATTRIBUTE_UNUSED, const char *bytes, size_t nbytes, void *opaque) { int *fd = opaque; return safewrite(*fd, bytes, nbytes); }
static int testRotatingFileInitOne(const char *filename, off_t size, char pattern) { if (size == (off_t)-1) { VIR_DEBUG("Deleting %s", filename); unlink(filename); } else { VIR_DEBUG("Creating %s size %zu", filename, (size_t)size); char buf[1024]; int fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0700); if (fd < 0) { fprintf(stderr, "Cannot create %s\n", filename); return -1; } memset(buf, pattern, sizeof(buf)); while (size) { size_t towrite = size; if (towrite > sizeof(buf)) towrite = sizeof(buf); if (safewrite(fd, buf, towrite) != towrite) { fprintf(stderr, "Cannot write to %s\n", filename); VIR_FORCE_CLOSE(fd); return -1; } size -= towrite; } VIR_FORCE_CLOSE(fd); } return 0; }
/** * lxcFdForward: * @readFd: file descriptor to read * @writeFd: file desriptor to write * * Reads 1 byte of data from readFd and writes to writeFd. * * Returns 0 on success, EAGAIN if returned on read, or -1 in case of error */ static int lxcFdForward(int readFd, int writeFd) { int rc = -1; char buf[2]; if (1 != (saferead(readFd, buf, 1))) { if (EAGAIN == errno) { rc = EAGAIN; goto cleanup; } virReportSystemError(errno, _("read of fd %d failed"), readFd); goto cleanup; } if (1 != (safewrite(writeFd, buf, 1))) { virReportSystemError(errno, _("write to fd %d failed"), writeFd); goto cleanup; } rc = 0; cleanup: return rc; }
int virPidFileWritePath(const char *pidfile, pid_t pid) { int rc; int fd; char pidstr[INT_BUFSIZE_BOUND(pid)]; if ((fd = open(pidfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) < 0) { rc = -errno; goto cleanup; } snprintf(pidstr, sizeof(pidstr), "%lld", (long long) pid); if (safewrite(fd, pidstr, strlen(pidstr)) < 0) { rc = -errno; VIR_FORCE_CLOSE(fd); goto cleanup; } rc = 0; cleanup: if (VIR_CLOSE(fd) < 0) rc = -errno; return rc; }
static void virLogStackTraceToFd(int fd) { void *array[100]; int size; static bool doneWarning = false; const char *msg = "Stack trace not available on this platform\n"; #define STRIP_DEPTH 3 size = backtrace(array, ARRAY_CARDINALITY(array)); if (size) { backtrace_symbols_fd(array + STRIP_DEPTH, size - STRIP_DEPTH, fd); ignore_value(safewrite(fd, "\n", 1)); } else if (!doneWarning) { ignore_value(safewrite(fd, msg, strlen(msg))); doneWarning = true; } #undef STRIP_DEPTH }
static void virLogDumpAllFD(const char *msg, int len) { int i, found = 0; if (len <= 0) len = strlen(msg); for (i = 0; i < virLogNbOutputs;i++) { if (virLogOutputs[i].f == virLogOutputToFd) { int fd = (intptr_t) virLogOutputs[i].data; if (fd >= 0) { ignore_value (safewrite(fd, msg, len)); found = 1; } } } if (!found) ignore_value (safewrite(STDERR_FILENO, msg, len)); }
int init_sf_source(int fd) /* Effects: Checks that fd is following the serial forwarder protocol Sends 'platform' for protocol version '!', and sets 'platform' to the received platform value. Modifies: platform Returns: 0 if it is, -1 otherwise */ { char check[2], us[2]; int version; unsigned char nonce[4]; /* Indicate version and check if serial forwarder on the other end */ us[0] = 'T'; us[1] = '!'; if (safewrite(fd, us, 2) != 2 || saferead(fd, check, 2) != 2 || check[0] != 'T' || check[1] < ' ') return -1; version = check[1]; if (us[1] < version) version = us[1]; switch (version) { case ' ': break; case '!': nonce[0] = platform; nonce[1] = platform >> 8; nonce[2] = platform >> 16; nonce[3] = platform >> 24; if (safewrite(fd, nonce, 4) != 4) return -1; if (saferead(fd, nonce, 4) != 4) return -1; //Unlike the more general SFProtocol.java this piece of code always knows what platform it is connected to; just drop the preferred platform from the client //platform = nonce[0] | nonce[1] << 8 | nonce[2] << 16 | nonce[3] << 24; break; } return 0; }
void Send_data(int id) { int len, ret,slen; void *buf,*index; init_msgheader(id); if(id == 1) { len = 8+2+mh_length+si_length; slen = 8+mh_length+si_length; buf = malloc(len); index = buf; sprintf(buf,"%d%s",slen,"MUSHROOM"); index += strlen(buf); //move to the end memmove((void *)index,buf_mh,mh_length); index += mh_length; memmove((void *)index,buf_si,si_length); //printf("%d\n",len); free(buf_si); }else if(id == 2) { len = 8+2 + mh_length +st_length; slen = 8+mh_length+st_length; buf = malloc(len+10); index = buf; sprintf(buf,"%d%s",slen,"MUSHROOM"); index += strlen(buf); //move to the end memmove((void *)index,buf_mh,mh_length); //strcat(buf,buf_st); index += mh_length; memmove((void *)index,buf_st,st_length); //printf("buf length:%d %d\n",strlen(buf),st_length); free(buf_st); } //fwrite(buf,strlen(buf),1,stdout); //putchar('\n'); //printf("%d %d\n",strlen(buf),len); //if(FD_ISSET(fd,&wset)) //{ ret = safewrite(fd,buf,len); if(ret < 0) { printf("Send msg error,waiting for heartbeat test\n"); } // } free(buf); free(buf_mh); }
/** * lxcContainerSendContinue: * @control: control FD to child * * Sends the continue message via the socket pair stored in the vm * structure. * * Returns 0 on success or -1 in case of error */ int lxcContainerSendContinue(int control) { int rc = -1; lxc_message_t msg = LXC_CONTINUE_MSG; int writeCount = 0; writeCount = safewrite(control, &msg, sizeof(msg)); if (writeCount != sizeof(msg)) { goto error_out; } rc = 0; error_out: return rc; }
static int pciWrite(pciDevice *dev, unsigned pos, uint8_t *buf, unsigned buflen) { if (pciOpenConfig(dev) < 0) return -1; if (lseek(dev->fd, pos, SEEK_SET) != pos || safewrite(dev->fd, buf, buflen) != buflen) { char ebuf[1024]; VIR_WARN("Failed to write to '%s' : %s", dev->path, virStrerror(errno, ebuf, sizeof(ebuf))); return -1; } return 0; }
void monitorhook(struct udata *userdata, time_t now, char *topic) { // struct udata *ud = (struct udata *)userdata; /* TODO: add monitor hook to a "monitor" key in LMDB ? */ char mpath[BUFSIZ]; static UT_string *us = NULL; utstring_renew(us); utstring_printf(us, "%ld %s\n", now, topic); snprintf(mpath, sizeof(mpath), "%s/monitor", STORAGEDIR); safewrite(mpath, UB(us)); }
void log_message(LOG_LEVEL log_evel, int line, const char *funcname, const char *fmt, ...) { struct timespec now; struct tm *p; char timep[128] = {0}; char errorinfo[128] = {0}; char str[1024] = {0}; char msg[1024] = {0}; va_list vargs; if(log_evel < log_filter) { return ; } pthread_mutex_lock(&log_thread_mutex); va_start(vargs, fmt); vsnprintf(str, sizeof(str), fmt, vargs); /*get time string*/ clock_gettime(CLOCK_REALTIME, &now); p = localtime(&now.tv_sec); snprintf(timep, sizeof(timep), "%04d-%02d-%02d %02d:%02d:%02d:%03d", (1900 + p->tm_year), (1 + p->tm_mon), p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, (int)(now.tv_nsec/1000000)); snprintf(msg, sizeof(msg), "%s: %s : %s:%d : %s\n", timep, log_level_string(log_evel), funcname, line, str); if (NULL == msg) goto cleanup; log_file_open(); if (gLogFd > 0) { if (safewrite(gLogFd, msg, strlen(msg)) < 0) { print_log_to_syslog(msg); } close(gLogFd); } else { print_log_to_syslog(msg); } cleanup: va_end(vargs); pthread_mutex_unlock(&log_thread_mutex); }
int append_record(char *filename, char *record,int size) { int fd; if ((fd = open(filename, O_WRONLY | O_CREAT, 0644)) == -1) { printf("open file error in append_record()"); return -1; } flock(fd, LOCK_EX); lseek(fd, 0, SEEK_END); if (safewrite(fd, record, size) == -1) printf("apprec write err!"); flock(fd, LOCK_UN); close(fd); return 0; }
/** * lxcContainerSendContinue: * @control: control FD to child * * Sends the continue message via the socket pair stored in the vm * structure. * * Returns 0 on success or -1 in case of error */ int lxcContainerSendContinue(int control) { int rc = -1; lxc_message_t msg = LXC_CONTINUE_MSG; int writeCount = 0; writeCount = safewrite(control, &msg, sizeof(msg)); if (writeCount != sizeof(msg)) { virReportSystemError(errno, "%s", _("Unable to send container continue message")); goto error_out; } rc = 0; error_out: return rc; }
/** * virConfWriteFile: * @filename: the path to the configuration file. * @conf: the conf * * Writes a configuration file back to a file. * * Returns the number of bytes written or -1 in case of error. */ int virConfWriteFile(const char *filename, virConfPtr conf) { virBuffer buf = VIR_BUFFER_INITIALIZER; virConfEntryPtr cur; int ret; int fd; char *content; unsigned int use; if (conf == NULL) return -1; cur = conf->entries; while (cur != NULL) { virConfSaveEntry(&buf, cur); cur = cur->next; } if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); return -1; } fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (fd < 0) { virBufferFreeAndReset(&buf); virConfError(NULL, VIR_ERR_WRITE_FAILED, _("failed to open file")); return -1; } use = virBufferUse(&buf); content = virBufferContentAndReset(&buf); ret = safewrite(fd, content, use); VIR_FREE(content); VIR_FORCE_CLOSE(fd); if (ret != (int)use) { virConfError(NULL, VIR_ERR_WRITE_FAILED, _("failed to save content")); return -1; } return ret; }
int my_after_post(struct fileheader *fh, char *boardname) { char buf[256]; int fd, err = 0, nowid = 0; if (!strncmp(fh->title, "Re:", 3)) { strncpy(fh->title, fh->title + 4, STRLEN); } setbfile(buf, boardname, DOT_DIR); if ((fd = open(buf, O_WRONLY | O_CREAT, 0664)) == -1) { err = 1; } if (!err) { writew_lock(fd, 0, SEEK_SET, 0); nowid = get_nextid(boardname); fh->id = nowid; fh->groupid = fh->id; fh->reid = fh->id; #ifdef HAVE_REPLY_COUNT fh->replycount = 1; #endif /* HAVE_REPLY_COUNT */ set_posttime(fh); lseek(fd, 0, SEEK_END); if (safewrite(fd, fh, sizeof(fileheader)) == -1) { err = 1; } un_lock(fd, 0, SEEK_SET, 0); close(fd); } if (err) { setbfile(buf, boardname, fh->filename); unlink(buf); return 1; } updatelastpost(boardname); if (fh->id == fh->groupid) setboardorigin(boardname, 1); setboardtitle(boardname, 1); return 0; }
static int openvz_copyfile(char* from_path, char* to_path) { char *line = NULL; size_t line_size = 0; FILE *fp; int copy_fd; int bytes_read; fp = fopen(from_path, "r"); if (fp == NULL) return -1; copy_fd = open(to_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (copy_fd == -1) { VIR_FORCE_FCLOSE(fp); return -1; } while (1) { if (getline(&line, &line_size, fp) <= 0) break; bytes_read = strlen(line); if (safewrite(copy_fd, line, bytes_read) != bytes_read) goto error; } if (VIR_FCLOSE(fp) < 0) goto error; if (VIR_CLOSE(copy_fd) < 0) goto error; VIR_FREE(line); return 0; error: VIR_FREE(line); VIR_FORCE_FCLOSE(fp); VIR_FORCE_CLOSE(copy_fd); return -1; }
int conv_h(int msgc, const struct pam_message **msgv, struct pam_response **res, void *app) { int i, err; char reply[1024]; *res = malloc(sizeof(*reply) * msgc); if(!*res) return PAM_CONV_ERR; memset(*res, '\0', sizeof(*reply) * msgc); for(i = 0; i < msgc; i++) { switch(msgv[i]->msg_style) { case PAM_PROMPT_ECHO_OFF: if(safewrite(1, msgv[i]->msg, strlen(msgv[i]->msg)) == -1) return PAM_CONV_ERR; err = conv_read(0, 1, reply, sizeof(reply), 0); if(err <= 0) return PAM_CONV_ERR; res[i]->resp = strdup(reply); break; case PAM_PROMPT_ECHO_ON: if(safewrite(1, msgv[i]->msg, strlen(msgv[i]->msg)) == -1) return PAM_CONV_ERR; err = conv_read(0, 1, reply, sizeof(reply), 1); if(err <= 0) return PAM_CONV_ERR; res[i]->resp = strdup(reply); break; case PAM_ERROR_MSG: if(safewrite(1, msgv[i]->msg, strlen(msgv[i]->msg)) == -1) return PAM_CONV_ERR; if(safewrite(1, "\n", 1) == -1) return PAM_CONV_ERR; break; case PAM_TEXT_INFO: if(safewrite(1, msgv[i]->msg, strlen(msgv[i]->msg)) <= 0) return PAM_CONV_ERR; if(safewrite(1, "\n", 1) == -1) return PAM_CONV_ERR; break; default: return PAM_CONV_ERR; } } return PAM_SUCCESS; }
/* * Called when the monitor is able to write data * Call this function while holding the monitor lock. */ static int qemuAgentIOWrite(qemuAgentPtr mon) { int done; /* If no active message, or fully transmitted, then no-op */ if (!mon->msg || mon->msg->txOffset == mon->msg->txLength) return 0; done = safewrite(mon->fd, mon->msg->txBuffer + mon->msg->txOffset, mon->msg->txLength - mon->msg->txOffset); if (done < 0) { if (errno == EAGAIN) return 0; virReportSystemError(errno, "%s", _("Unable to write to monitor")); return -1; } mon->msg->txOffset += done; return done; }
/* shishi authentication */ int auth (Shishi * h, int verbose, const char *cname, const char *sname, int sock, char *cmd, char *port, Shishi_key ** enckey, Shishi_key * deckey) { Shishi_ap *ap; Shishi_tkt *tkt; Shishi_tkts_hint hint; int rc; char *out; int outlen; int krb5len, msglen; char auth; /* KERBEROS 5 SENDAUTH MESSAGE */ char krb5sendauth[] = "KRB5_SENDAUTH_V1.0"; /* PROTOCOL VERSION */ char krb5sendclient[] = "KCMDV0.2"; /* to store error msg sent by server */ char errormsg[101]; char cksumdata[101]; /* size of KRB5 auth message */ krb5len = strlen (krb5sendauth) + 1; msglen = htonl (krb5len); safewrite (sock, &msglen, sizeof (int)); /* KRB5 authentication message */ safewrite (sock, krb5sendauth, krb5len); /* size of client message */ krb5len = strlen (krb5sendclient) + 1; msglen = htonl (krb5len); safewrite (sock, &msglen, sizeof (int)); /* KRB5 client message */ safewrite (sock, krb5sendclient, krb5len); /* get answer from server 0 = ok, 1 = error with message */ read (sock, &auth, 1); if (auth) { read (sock, errormsg, 100); errormsg[100] = '\0'; printf ("Error during server authentication : %s\n", errormsg); return 1; } if (verbose) { printf ("Client: %s\n", cname); printf ("Server: %s\n", sname); } /* Get a ticket for the server. */ memset (&hint, 0, sizeof (hint)); hint.client = (char *) cname; hint.server = (char *) sname; tkt = shishi_tkts_get (shishi_tkts_default (h), &hint); if (!tkt) { printf ("cannot find ticket for \"%s\"\n", sname); return 1; } if (verbose) shishi_tkt_pretty_print (tkt, stderr); /* Create Authentication context */ rc = shishi_ap_tktoptions (h, &ap, tkt, SHISHI_APOPTIONS_MUTUAL_REQUIRED); if (rc != SHISHI_OK) { printf ("cannot create authentication context\n"); return 1; } /* checksum = port: terminal name */ snprintf (cksumdata, 100, "%s:%s%s", port, cmd, cname); /* add checksum to authenticator */ shishi_ap_authenticator_cksumdata_set (ap, cksumdata, strlen (cksumdata)); /* To be compatible with MIT rlogind */ shishi_ap_authenticator_cksumtype_set (ap, SHISHI_RSA_MD5); /* create der encoded AP-REQ */ rc = shishi_ap_req_der (ap, &out, &outlen); if (rc != SHISHI_OK) { printf ("cannot build authentication request: %s\n", shishi_strerror (rc)); return 1; } if (verbose) shishi_authenticator_print (h, stderr, shishi_ap_authenticator (ap)); /* extract subkey if present from ap exchange for secure connection */ shishi_authenticator_get_subkey (h, shishi_ap_authenticator (ap), enckey); /* send size of AP-REQ to the server */ msglen = htonl (outlen); safewrite (sock, (char *) &msglen, sizeof (int)); /* send AP-REQ to the server */ safewrite (sock, out, outlen); /* read a respond from server - what ? */ read (sock, &auth, sizeof (int)); /* For mutual authentication, wait for server reply. */ if (shishi_apreq_mutual_required_p (h, shishi_ap_req (ap))) { if (verbose) printf ("Waiting for server to authenticate itself...\n"); /* read size of the AP-REP */ read (sock, (char *) &outlen, sizeof (int)); /* read AP-REP */ outlen = ntohl (outlen); outlen = read (sock, out, outlen); rc = shishi_ap_rep_verify_der (ap, out, outlen); if (rc == SHISHI_OK) { if (verbose) printf ("AP-REP verification OK...\n"); } else { if (rc == SHISHI_APREP_VERIFY_FAILED) printf ("AP-REP verification failed...\n"); else printf ("AP-REP verification error: %s\n", shishi_strerror (rc)); return 1; } /* The server is authenticated. */ if (verbose) printf ("Server authenticated.\n"); } /* We are now authenticated. */ if (verbose) printf ("User authenticated.\n"); return AUTH_OK; }
/** * virLogMessage: * @category: where is that message coming from * @priority: the priority level * @funcname: the function emitting the (debug) message * @linenr: line where the message was emitted * @flags: extra flags, 1 if coming from the error handler * @fmt: the string format * @...: the arguments * * Call the libvirt logger with some informations. Based on the configuration * the message may be stored, sent to output or just discarded */ void virLogMessage(const char *category, int priority, const char *funcname, long long linenr, int flags, const char *fmt, ...) { char *str = NULL; char *msg; struct timeval cur_time; struct tm time_info; int len, fprio, i, ret; if (!virLogInitialized) virLogStartup(); if (fmt == NULL) return; /* * check against list of specific logging patterns */ fprio = virLogFiltersCheck(category); if (fprio == 0) { if (priority < virLogDefaultPriority) return; } else if (priority < fprio) return; /* * serialize the error message, add level and timestamp */ VIR_GET_VAR_STR(fmt, str); if (str == NULL) return; gettimeofday(&cur_time, NULL); localtime_r(&cur_time.tv_sec, &time_info); if ((funcname != NULL)) { ret = virAsprintf(&msg, "%02d:%02d:%02d.%03d: %s : %s:%lld : %s\n", time_info.tm_hour, time_info.tm_min, time_info.tm_sec, (int) cur_time.tv_usec / 1000, virLogPriorityString(priority), funcname, linenr, str); } else { ret = virAsprintf(&msg, "%02d:%02d:%02d.%03d: %s : %s\n", time_info.tm_hour, time_info.tm_min, time_info.tm_sec, (int) cur_time.tv_usec / 1000, virLogPriorityString(priority), str); } VIR_FREE(str); if (ret < 0) { /* apparently we're running out of memory */ return; } /* * Log based on defaults, first store in the history buffer * then push the message on the outputs defined, if none * use stderr. * NOTE: the locking is a single point of contention for multiple * threads, but avoid intermixing. Maybe set up locks per output * to improve paralellism. */ len = strlen(msg); virLogStr(msg, len); virLogLock(); for (i = 0; i < virLogNbOutputs;i++) { if (priority >= virLogOutputs[i].priority) virLogOutputs[i].f(category, priority, funcname, linenr, msg, len, virLogOutputs[i].data); } if ((virLogNbOutputs == 0) && (flags != 1)) ignore_value (safewrite(STDERR_FILENO, msg, len)); virLogUnlock(); VIR_FREE(msg); }
int main (int argc, char **argv) { char *user = NULL; char *luser = NULL; char *host = NULL; char *port = "shell"; char *p; char lport[5]; struct passwd *pw; int af = AF_UNSPEC; struct addrinfo hint, *ai, *aip, *lai; struct sockaddr raddr; int raddrlen; int err, sock = -1, lsock = -1, esock = -1, i; int opt; bool verbose = false; char hostaddr[NI_MAXHOST]; char portnr[NI_MAXSERV]; char buf[3][BUFLEN], *bufp[3]; int len[3], wlen; fd_set infd, outfd, infdset, outfdset, errfd; int maxfd; int flags; #ifdef SHISHI Shishi *h; Shishi_key *enckey = NULL, *deckey = NULL; int rc; char *sname = NULL; int shishi = 0; int encryption = 0; int auth2 = 0; char *cmd, *tcmd; int hostlen, cmdlen; struct hostent *hostdata; char *iv = NULL; char *iv2 = NULL; char *iv3 = NULL; int ivlen; int ivlen2; int ivlen3; #endif argv0 = argv[0]; /* Lookup local username */ if (!(pw = getpwuid (getuid ()))) { fprintf (stderr, "%s: Could not lookup username: %s\n", argv0, strerror (errno)); return 1; } /* Process options */ #ifdef SHISHI while ((opt = getopt (argc, argv, "+l:p:46vsx")) != -1) #else while ((opt = getopt (argc, argv, "+l:p:46v")) != -1) #endif { switch (opt) { case 'l': user = optarg; break; case 'p': port = optarg; break; case '4': af = AF_INET; break; case '6': af = AF_INET6; break; case 'v': verbose = true; break; #ifdef SHISHI case 's': shishi = 1; port = "544"; break; case 'x': shishi = 1; encryption = 1; port = "544"; break; #endif default: fprintf (stderr, "%s: Unknown option!\n", argv0); usage (); return 1; } } if (optind == argc) { fprintf (stderr, "%s: No host specified!\n", argv0); usage (); return 1; } #ifdef SHISHI if (!shishi) { luser = pw->pw_name; if (!user) user = luser; } #endif host = argv[optind++]; if ((p = strchr (host, '@'))) { user = host; *p = '\0'; host = p + 1; } /* Resolve hostname and try to make a connection */ memset (&hint, '\0', sizeof (hint)); hint.ai_family = af; hint.ai_socktype = SOCK_STREAM; err = getaddrinfo (host, port, &hint, &ai); if (err) { fprintf (stderr, "%s: Error looking up host: %s\n", argv0, gai_strerror (err)); return 1; } hint.ai_flags = AI_PASSIVE; for (aip = ai; aip; aip = aip->ai_next) { if (getnameinfo (aip->ai_addr, aip->ai_addrlen, hostaddr, sizeof (hostaddr), portnr, sizeof (portnr), NI_NUMERICHOST | NI_NUMERICSERV)) { fprintf (stderr, "%s: Error resolving address: %s\n", argv0, strerror (errno)); return 1; } if (verbose) fprintf (stderr, "Trying %s port %s...", hostaddr, portnr); if ((sock = socket (aip->ai_family, aip->ai_socktype, aip->ai_protocol)) == -1) { if (verbose) fprintf (stderr, " Could not open socket: %s\n", strerror (errno)); continue; } hint.ai_family = aip->ai_family; /* Bind to a privileged port */ for (i = 1023; i >= 512; i--) { snprintf (lport, sizeof (lport), "%d", i); err = getaddrinfo (NULL, lport, &hint, &lai); if (err) { fprintf (stderr, " Error looking up localhost: %s\n", gai_strerror (err)); return 1; } err = bind (sock, lai->ai_addr, lai->ai_addrlen); freeaddrinfo (lai); if (err) continue; else break; } if (err) { if (verbose) fprintf (stderr, " Could not bind to privileged port: %s\n", strerror (errno)); continue; } if (connect (sock, aip->ai_addr, aip->ai_addrlen) == -1) { if (verbose) fprintf (stderr, " Connection failed: %s\n", strerror (errno)); continue; } if (verbose) fprintf (stderr, " Connected.\n"); break; } if (!aip) { fprintf (stderr, "%s: Could not make a connection.\n", argv0); return 1; } /* Create a socket for the incoming connection for stderr output */ if ((lsock = socket (aip->ai_family, aip->ai_socktype, aip->ai_protocol)) == -1) { fprintf (stderr, "%s: Could not open socket: %s\n", argv0, strerror (errno)); return 1; } hint.ai_family = aip->ai_family; freeaddrinfo (ai); for (i--; i >= 512; i--) { snprintf (lport, sizeof (lport), "%d", i); err = getaddrinfo (NULL, lport, &hint, &lai); if (err) { fprintf (stderr, "%s: Error looking up localhost: %s\n", argv0, gai_strerror (err)); return 1; } err = bind (lsock, lai->ai_addr, lai->ai_addrlen); freeaddrinfo (lai); if (err) continue; else break; } if (err) { fprintf (stderr, "%s: Could not bind to privileged port: %s\n", argv0, strerror (errno)); return 1; } if (listen (lsock, 1)) { fprintf (stderr, "%s: Could not listen: %s\n", argv0, strerror (errno)); return 1; } /* Drop privileges */ if (setuid (getuid ())) { fprintf (stderr, "%s: Unable to drop privileges: %s\n", argv0, strerror (errno)); return 1; } /* Send required information to the server */ bufp[0] = buf[0]; len[0] = sizeof (buf[0]); #ifdef SHISHI if (shishi) { if (!shishi_check_version (SHISHI_VERSION)) { printf ("shishi_check_version() failed:\n" "Header file incompatible with shared library.\n"); return 1; } rc = shishi_init (&h); if (rc != SHISHI_OK) { printf ("error initializing shishi: %s\n", shishi_strerror (rc)); return 1; } hostdata = gethostbyname (host); hostlen = strlen (hostdata->h_name) + strlen (SERVICE) + 2; sname = malloc (hostlen); snprintf (sname, hostlen, "%s/%s", SERVICE, hostdata->h_name); rc = optind; cmdlen = BUFLEN; cmd = malloc (cmdlen); tcmd = cmd; if (encryption) safecpy (&tcmd, &cmdlen, "-x ", 0); for (; optind < argc; optind++) { safecpy (&tcmd, &cmdlen, argv[optind], 0); if (optind < argc - 1) safecpy (&tcmd, &cmdlen, " ", 0); } safecpy (&tcmd, &cmdlen, "", 1); optind = rc; if (!user) user = (char *) shishi_principal_default (h); safewrite (sock, lport, strlen (lport) + 1); /* Wait for incoming connection from server */ if ((esock = accept (lsock, &raddr, &raddrlen)) == -1) { fprintf (stderr, "%s: Could not accept stderr connection: %s\n", argv0, strerror (errno)); return 1; } close (lsock); if (auth (h, 0, user, sname, sock, cmd, port, &enckey, deckey) != AUTH_OK) return 1; free (cmd); } else { safecpy (&bufp[0], &len[0], lport, 1); safecpy (&bufp[0], &len[0], luser, 1); } #else safecpy (&bufp[0], &len[0], lport, 1); safecpy (&bufp[0], &len[0], luser, 1); #endif safecpy (&bufp[0], &len[0], user, 1); #ifdef SHISHI if (encryption) safecpy (&bufp[0], &len[0], "-x ", 0); #endif for (; optind < argc; optind++) { safecpy (&bufp[0], &len[0], argv[optind], 0); if (optind < argc - 1) safecpy (&bufp[0], &len[0], " ", 0); } #ifdef SHISHI if (shishi) { safecpy (&bufp[0], &len[0], "", 1); safecpy (&bufp[0], &len[0], user, 1); } else #endif safecpy (&bufp[0], &len[0], "", 1); if (!len[0]) { fprintf (stderr, "%s: Arguments too long!\n", argv0); return 1; } if (safewrite (sock, buf[0], bufp[0] - buf[0]) == -1) { fprintf (stderr, "%s: Unable to send required information: %s\n", argv0, strerror (errno)); return 1; } #ifdef SHISHI if (shishi) { safewrite (sock, &auth2, sizeof (int)); } #endif /* Wait for acknowledgement from server */ errno = 0; if (read (sock, buf[0], 1) != 1 || *buf[0]) { fprintf (stderr, "%s: Didn't receive NULL byte from server: %s\n", argv0, strerror (errno)); return 1; } #ifdef SHISHI if (encryption) { ivlen = ivlen2 = ivlen3 = shishi_key_length (enckey); iv = malloc (ivlen); memset (iv, 1, ivlen); iv2 = malloc (ivlen2); memset (iv2, 3, ivlen2); iv3 = malloc (ivlen3); memset (iv3, 0, ivlen3); } if (!shishi) { /* Wait for incoming connection from server */ if ((esock = accept (lsock, &raddr, &raddrlen)) == -1) { fprintf (stderr, "%s: Could not accept stderr connection: %s\n", argv0, strerror (errno)); return 1; } close (lsock); } #else /* Wait for incoming connection from server */ if ((esock = accept (lsock, &raddr, &raddrlen)) == -1) { fprintf (stderr, "%s: Could not accept stderr connection: %s\n", argv0, strerror (errno)); return 1; } close (lsock); #endif /* Process input/output */ flags = fcntl (sock, F_GETFL); fcntl (sock, F_SETFL, flags | O_NONBLOCK); flags = fcntl (esock, F_GETFL); fcntl (esock, F_SETFL, flags | O_NONBLOCK); bufp[0] = buf[0]; bufp[1] = buf[1]; bufp[2] = buf[2]; FD_ZERO (&infdset); FD_ZERO (&outfdset); FD_SET (0, &infdset); FD_SET (sock, &infdset); FD_SET (esock, &infdset); maxfd = (sock > esock ? sock : esock) + 1; for (;;) { errno = 0; infd = infdset; outfd = outfdset; errfd = infdset; if (select (maxfd, &infd, &outfd, &errfd, NULL) <= 0) { if (errno == EINTR) continue; else break; } if (FD_ISSET (esock, &infd)) { #ifdef SHISHI if (encryption) { rc = readenc (h, esock, buf[2], &len[2], iv2, &ivlen2, enckey); if (rc != SHISHI_OK) break; } else #endif len[2] = read (esock, buf[2], BUFLEN); if (len[2] <= 0) { if (errno != EINTR) { if (FD_ISSET (sock, &infdset) || FD_ISSET (1, &outfdset)) FD_CLR (esock, &infdset); else break; } } else { FD_SET (2, &outfdset); FD_CLR (esock, &infdset); } } if (FD_ISSET (2, &outfd)) { wlen = write (2, bufp[2], len[2]); if (wlen <= 0) { if (errno != EINTR) { if (FD_ISSET (sock, &infdset) || FD_ISSET (1, &outfdset)) FD_CLR (esock, &infdset); else break; } } else { len[2] -= wlen; bufp[2] += wlen; if (!len[2]) { FD_CLR (2, &outfdset); FD_SET (esock, &infdset); bufp[2] = buf[2]; } } } if (FD_ISSET (sock, &infd)) { #ifdef SHISHI if (encryption) { rc = readenc (h, sock, buf[1], &len[1], iv, &ivlen, enckey); if (rc != SHISHI_OK) break; } else #endif len[1] = read (sock, buf[1], BUFLEN); if (len[1] <= 0) { if (errno != EINTR) { if (FD_ISSET (esock, &infdset) || FD_ISSET (2, &outfdset)) FD_CLR (sock, &infdset); else break; } } else { FD_SET (1, &outfdset); FD_CLR (sock, &infdset); } } if (FD_ISSET (1, &outfd)) { wlen = write (1, bufp[1], len[1]); if (wlen <= 0) { if (errno != EINTR) { if (FD_ISSET (esock, &infdset) || FD_ISSET (2, &outfdset)) FD_CLR (sock, &infdset); else break; } } else { len[1] -= wlen; bufp[1] += wlen; if (!len[1]) { FD_CLR (1, &outfdset); FD_SET (sock, &infdset); bufp[1] = buf[1]; } } } if (FD_ISSET (0, &infd)) { len[0] = read (0, buf[0], BUFLEN); if (len[0] <= 0) { if (errno != EINTR) { FD_CLR (0, &infdset); shutdown (sock, SHUT_WR); } } else { FD_SET (sock, &outfdset); FD_CLR (0, &infdset); } } if (FD_ISSET (sock, &outfd)) { #ifdef SHISHI if (encryption) { rc = writeenc (h, sock, bufp[0], len[0], &wlen, iv3, &ivlen3, enckey); if (rc != SHISHI_OK) break; } else #endif wlen = write (sock, bufp[0], len[0]); if (wlen <= 0) { if (errno != EINTR) break; } else { len[0] -= wlen; bufp[0] += wlen; if (!len[0]) { FD_CLR (sock, &outfdset); FD_SET (0, &infdset); bufp[0] = buf[0]; } } } } if (errno) { fprintf (stderr, "%s: %s\n", argv0, strerror (errno)); return 1; } close (sock); close (esock); #ifdef SHISHI if (shishi) { shishi_done (h); if (encryption) { free (iv); free (iv2); free (iv3); } } #endif return 0; }
/** * virRotatingFileWriterAppend: * @file: the file context * @buf: the data buffer * @len: the number of bytes in @buf * * Append the data in @buf to the file, performing rollover * of the files if their size would exceed the limit * * Returns the number of bytes written, or -1 on error */ ssize_t virRotatingFileWriterAppend(virRotatingFileWriterPtr file, const char *buf, size_t len) { ssize_t ret = 0; size_t i; while (len) { size_t towrite = len; bool forceRollover = false; if (file->entry->pos > file->maxlen) { /* If existing file is for some reason larger then max length we * won't write to this file anymore, but we rollover this file.*/ forceRollover = true; towrite = 0; } else if ((file->entry->pos + towrite) > file->maxlen) { towrite = file->maxlen - file->entry->pos; /* * If there's a newline in the last 80 chars * we're about to write, then break at that * point to avoid splitting lines across * separate files */ for (i = 0; i < towrite && i < 80; i++) { if (buf[towrite - i - 1] == '\n') { towrite -= i; forceRollover = true; break; } } } if (towrite) { if (safewrite(file->entry->fd, buf, towrite) != towrite) { virReportSystemError(errno, _("Unable to write to file %s"), file->basepath); return -1; } len -= towrite; buf += towrite; ret += towrite; file->entry->pos += towrite; file->entry->len += towrite; } if ((file->entry->pos == file->maxlen && len) || forceRollover) { virRotatingFileWriterEntryPtr tmp = file->entry; VIR_DEBUG("Hit max size %zu on %s (force=%d)\n", file->maxlen, file->basepath, forceRollover); if (virRotatingFileWriterRollover(file) < 0) return -1; if (!(file->entry = virRotatingFileWriterEntryNew(file->basepath, file->mode))) return -1; virRotatingFileWriterEntryFree(tmp); } } return ret; }
int delete_range(const char *fpath, int id1, int id2) { fileheader_t fhdr; nol_t my; char fullpath[STRLEN], *t; int fdr, fdw, fd; int count, dcount=0; nolfilename(&my, fpath); if ((fd = OpenCreate(my.lockfn, O_RDWR | O_APPEND)) == -1) return -1; flock(fd, LOCK_EX); if ((fdr = open(fpath, O_RDONLY)) == -1) { flock(fd, LOCK_UN); close(fd); return -1; } if ( ((fdw = OpenCreate(my.newfn, O_WRONLY | O_EXCL)) == -1) && ((fdw = force_open(my.newfn)) == -1)) { close(fdr); flock(fd, LOCK_UN); close(fd); return -1; } count = 1; strlcpy(fullpath, fpath, sizeof(fullpath)); t = strrchr(fullpath, '/'); assert(t); t++; while (read(fdr, &fhdr, sizeof(fileheader_t)) == sizeof(fileheader_t)) { strcpy(t, fhdr.filename); /* rocker.011018: add new tag delete */ if ( (fhdr.filemode & FILE_MARKED) || /* 標記 */ ((fhdr.filemode & FILE_DIGEST) && (currstat != RMAIL) )|| /* 文摘 , FILE_DIGEST is used as REPLIED in mail menu.*/ (id1 && (count < id1 || count > id2)) || /* range */ (!id1 && !FindTaggedItem(&fhdr))) { /* TagList */ if ((safewrite(fdw, &fhdr, sizeof(fileheader_t)) == -1)) { close(fdr); close(fdw); unlink(my.newfn); flock(fd, LOCK_UN); close(fd); return -1; } } else { unlink(fullpath); dcount++; RemoveTagItem(&fhdr); } ++count; } close(fdr); close(fdw); if (Rename(fpath, my.oldfn) == -1 || Rename(my.newfn, fpath) == -1) { flock(fd, LOCK_UN); close(fd); return -1; } flock(fd, LOCK_UN); close(fd); return dcount; }
int main(int argc, char **argv) { int i, n; char **origenv; char **newenv; char *cwd; FILE *log = fopen(abs_builddir "/commandhelper.log", "w"); if (!log) goto error; for (i = 1 ; i < argc ; i++) { fprintf(log, "ARG:%s\n", argv[i]); } origenv = environ; n = 0; while (*origenv != NULL) { n++; origenv++; } if (VIR_ALLOC_N(newenv, n) < 0) { exit(EXIT_FAILURE); } origenv = environ; n = i = 0; while (*origenv != NULL) { newenv[i++] = *origenv; n++; origenv++; } qsort(newenv, n, sizeof(newenv[0]), envsort); for (i = 0 ; i < n ; i++) { /* Ignore the variables used to instruct the loader into * behaving differently, as they could throw the tests off. */ if (!STRPREFIX(newenv[i], "LD_")) fprintf(log, "ENV:%s\n", newenv[i]); } for (i = 0 ; i < sysconf(_SC_OPEN_MAX) ; i++) { int f; int closed; if (i == fileno(log)) continue; closed = fcntl(i, F_GETFD, &f) == -1 && errno == EBADF; if (!closed) fprintf(log, "FD:%d\n", i); } fprintf(log, "DAEMON:%s\n", getpgrp() == getsid(0) ? "yes" : "no"); if (!(cwd = getcwd(NULL, 0))) return EXIT_FAILURE; if (strlen(cwd) > strlen(".../commanddata") && STREQ(cwd + strlen(cwd) - strlen("/commanddata"), "/commanddata")) strcpy(cwd, ".../commanddata"); fprintf(log, "CWD:%s\n", cwd); VIR_FREE(cwd); VIR_FORCE_FCLOSE(log); if (argc > 1 && STREQ(argv[1], "--close-stdin")) { if (freopen("/dev/null", "r", stdin) != stdin) goto error; usleep(100*1000); } char buf[1024]; ssize_t got; fprintf(stdout, "BEGIN STDOUT\n"); fflush(stdout); fprintf(stderr, "BEGIN STDERR\n"); fflush(stderr); for (;;) { got = read(STDIN_FILENO, buf, sizeof(buf)); if (got < 0) goto error; if (got == 0) break; if (safewrite(STDOUT_FILENO, buf, got) != got) goto error; if (safewrite(STDERR_FILENO, buf, got) != got) goto error; } fprintf(stdout, "END STDOUT\n"); fflush(stdout); fprintf(stderr, "END STDERR\n"); fflush(stderr); return EXIT_SUCCESS; error: return EXIT_FAILURE; }
/** * virLXCProcessStart: * @conn: pointer to connection * @driver: pointer to driver structure * @vm: pointer to virtual machine structure * @autoDestroy: mark the domain for auto destruction * @reason: reason for switching vm to running state * * Starts a vm * * Returns 0 on success or -1 in case of error */ int virLXCProcessStart(virConnectPtr conn, virLXCDriverPtr driver, virDomainObjPtr vm, unsigned int nfiles, int *files, bool autoDestroy, virDomainRunningReason reason) { int rc = -1, r; size_t nttyFDs = 0; int *ttyFDs = NULL; size_t i; char *logfile = NULL; int logfd = -1; size_t nveths = 0; char **veths = NULL; int handshakefds[2] = { -1, -1 }; off_t pos = -1; char ebuf[1024]; char *timestamp; virCommandPtr cmd = NULL; virLXCDomainObjPrivatePtr priv = vm->privateData; virCapsPtr caps = NULL; virErrorPtr err = NULL; virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver); virCgroupPtr selfcgroup; int status; if (virCgroupNewSelf(&selfcgroup) < 0) return -1; if (!virCgroupHasController(selfcgroup, VIR_CGROUP_CONTROLLER_CPUACCT)) { virCgroupFree(&selfcgroup); virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unable to find 'cpuacct' cgroups controller mount")); return -1; } if (!virCgroupHasController(selfcgroup, VIR_CGROUP_CONTROLLER_DEVICES)) { virCgroupFree(&selfcgroup); virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unable to find 'devices' cgroups controller mount")); return -1; } if (!virCgroupHasController(selfcgroup, VIR_CGROUP_CONTROLLER_MEMORY)) { virCgroupFree(&selfcgroup); virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unable to find 'memory' cgroups controller mount")); return -1; } virCgroupFree(&selfcgroup); if (virFileMakePath(cfg->logDir) < 0) { virReportSystemError(errno, _("Cannot create log directory '%s'"), cfg->logDir); return -1; } if (!vm->def->resource) { virDomainResourceDefPtr res; if (VIR_ALLOC(res) < 0) goto cleanup; if (VIR_STRDUP(res->partition, "/machine") < 0) { VIR_FREE(res); goto cleanup; } vm->def->resource = res; } if (virAsprintf(&logfile, "%s/%s.log", cfg->logDir, vm->def->name) < 0) return -1; if (!(caps = virLXCDriverGetCapabilities(driver, false))) goto cleanup; /* Do this up front, so any part of the startup process can add * runtime state to vm->def that won't be persisted. This let's us * report implicit runtime defaults in the XML, like vnc listen/socket */ VIR_DEBUG("Setting current domain def as transient"); if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, true) < 0) goto cleanup; /* Run an early hook to set-up missing devices */ if (virHookPresent(VIR_HOOK_DRIVER_LXC)) { char *xml = virDomainDefFormat(vm->def, 0); int hookret; hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name, VIR_HOOK_LXC_OP_PREPARE, VIR_HOOK_SUBOP_BEGIN, NULL, xml, NULL); VIR_FREE(xml); /* * If the script raised an error abort the launch */ if (hookret < 0) goto cleanup; } if (virLXCProcessEnsureRootFS(vm) < 0) goto cleanup; /* Must be run before security labelling */ VIR_DEBUG("Preparing host devices"); if (virLXCPrepareHostDevices(driver, vm->def) < 0) goto cleanup; /* Here we open all the PTYs we need on the host OS side. * The LXC controller will open the guest OS side PTYs * and forward I/O between them. */ nttyFDs = vm->def->nconsoles; if (VIR_ALLOC_N(ttyFDs, nttyFDs) < 0) goto cleanup; for (i = 0; i < vm->def->nconsoles; i++) ttyFDs[i] = -1; /* If you are using a SecurityDriver with dynamic labelling, then generate a security label for isolation */ VIR_DEBUG("Generating domain security label (if required)"); if (vm->def->nseclabels && vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DEFAULT) vm->def->seclabels[0]->type = VIR_DOMAIN_SECLABEL_NONE; if (virSecurityManagerGenLabel(driver->securityManager, vm->def) < 0) { virDomainAuditSecurityLabel(vm, false); goto cleanup; } virDomainAuditSecurityLabel(vm, true); VIR_DEBUG("Setting domain security labels"); if (virSecurityManagerSetAllLabel(driver->securityManager, vm->def, NULL) < 0) goto cleanup; for (i = 0; i < vm->def->nconsoles; i++) { char *ttyPath; if (vm->def->consoles[i]->source.type != VIR_DOMAIN_CHR_TYPE_PTY) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Only PTY console types are supported")); goto cleanup; } if (virFileOpenTty(&ttyFDs[i], &ttyPath, 1) < 0) { virReportSystemError(errno, "%s", _("Failed to allocate tty")); goto cleanup; } VIR_FREE(vm->def->consoles[i]->source.data.file.path); vm->def->consoles[i]->source.data.file.path = ttyPath; VIR_FREE(vm->def->consoles[i]->info.alias); if (virAsprintf(&vm->def->consoles[i]->info.alias, "console%zu", i) < 0) goto cleanup; } if (virLXCProcessSetupInterfaces(conn, vm->def, &nveths, &veths) < 0) goto cleanup; /* Save the configuration for the controller */ if (virDomainSaveConfig(cfg->stateDir, vm->def) < 0) goto cleanup; if ((logfd = open(logfile, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR|S_IWUSR)) < 0) { virReportSystemError(errno, _("Failed to open '%s'"), logfile); goto cleanup; } if (pipe(handshakefds) < 0) { virReportSystemError(errno, "%s", _("Unable to create pipe")); goto cleanup; } if (!(cmd = virLXCProcessBuildControllerCmd(driver, vm, nveths, veths, ttyFDs, nttyFDs, files, nfiles, handshakefds[1]))) goto cleanup; virCommandSetOutputFD(cmd, &logfd); virCommandSetErrorFD(cmd, &logfd); /* now that we know it is about to start call the hook if present */ if (virHookPresent(VIR_HOOK_DRIVER_LXC)) { char *xml = virDomainDefFormat(vm->def, 0); int hookret; hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name, VIR_HOOK_LXC_OP_START, VIR_HOOK_SUBOP_BEGIN, NULL, xml, NULL); VIR_FREE(xml); /* * If the script raised an error abort the launch */ if (hookret < 0) goto cleanup; } /* Log timestamp */ if ((timestamp = virTimeStringNow()) == NULL) goto cleanup; if (safewrite(logfd, timestamp, strlen(timestamp)) < 0 || safewrite(logfd, START_POSTFIX, strlen(START_POSTFIX)) < 0) { VIR_WARN("Unable to write timestamp to logfile: %s", virStrerror(errno, ebuf, sizeof(ebuf))); } VIR_FREE(timestamp); /* Log generated command line */ virCommandWriteArgLog(cmd, logfd); if ((pos = lseek(logfd, 0, SEEK_END)) < 0) VIR_WARN("Unable to seek to end of logfile: %s", virStrerror(errno, ebuf, sizeof(ebuf))); virCommandRawStatus(cmd); if (virCommandRun(cmd, &status) < 0) goto cleanup; if (status != 0) { if (virLXCProcessReadLogOutput(vm, logfile, pos, ebuf, sizeof(ebuf)) <= 0) { if (WIFEXITED(status)) snprintf(ebuf, sizeof(ebuf), _("unexpected exit status %d"), WEXITSTATUS(status)); else snprintf(ebuf, sizeof(ebuf), "%s", _("terminated abnormally")); } virReportError(VIR_ERR_INTERNAL_ERROR, _("guest failed to start: %s"), ebuf); goto cleanup; } if (VIR_CLOSE(handshakefds[1]) < 0) { virReportSystemError(errno, "%s", _("could not close handshake fd")); goto cleanup; } /* Connect to the controller as a client *first* because * this will block until the child has written their * pid file out to disk & created their cgroup */ if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm))) { /* Intentionally overwrite the real monitor error message, * since a better one is almost always found in the logs */ if (virLXCProcessReadLogOutput(vm, logfile, pos, ebuf, sizeof(ebuf)) > 0) { virResetLastError(); virReportError(VIR_ERR_INTERNAL_ERROR, _("guest failed to start: %s"), ebuf); } goto cleanup; } /* And get its pid */ if ((r = virPidFileRead(cfg->stateDir, vm->def->name, &vm->pid)) < 0) { if (virLXCProcessReadLogOutput(vm, logfile, pos, ebuf, sizeof(ebuf)) > 0) virReportError(VIR_ERR_INTERNAL_ERROR, _("guest failed to start: %s"), ebuf); else virReportSystemError(-r, _("Failed to read pid file %s/%s.pid"), cfg->stateDir, vm->def->name); goto cleanup; } if (virCgroupNewDetectMachine(vm->def->name, "lxc", vm->pid, vm->def->resource ? vm->def->resource->partition : NULL, -1, &priv->cgroup) < 0) goto error; if (!priv->cgroup) { virReportError(VIR_ERR_INTERNAL_ERROR, _("No valid cgroup for machine %s"), vm->def->name); goto error; } priv->stopReason = VIR_DOMAIN_EVENT_STOPPED_FAILED; priv->wantReboot = false; vm->def->id = vm->pid; virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason); priv->doneStopEvent = false; if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback) driver->inhibitCallback(true, driver->inhibitOpaque); if (lxcContainerWaitForContinue(handshakefds[0]) < 0) { char out[1024]; if (!(virLXCProcessReadLogOutput(vm, logfile, pos, out, 1024) < 0)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("guest failed to start: %s"), out); } goto error; } if (autoDestroy && virCloseCallbacksSet(driver->closeCallbacks, vm, conn, lxcProcessAutoDestroy) < 0) goto error; if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, false) < 0) goto error; /* Write domain status to disk. * * XXX: Earlier we wrote the plain "live" domain XML to this * location for the benefit of libvirt_lxc. We're now overwriting * it with the live status XML instead. This is a (currently * harmless) inconsistency we should fix one day */ if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) goto error; /* finally we can call the 'started' hook script if any */ if (virHookPresent(VIR_HOOK_DRIVER_LXC)) { char *xml = virDomainDefFormat(vm->def, 0); int hookret; hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name, VIR_HOOK_LXC_OP_STARTED, VIR_HOOK_SUBOP_BEGIN, NULL, xml, NULL); VIR_FREE(xml); /* * If the script raised an error abort the launch */ if (hookret < 0) goto error; } rc = 0; cleanup: if (rc != 0 && !err) err = virSaveLastError(); virCommandFree(cmd); if (VIR_CLOSE(logfd) < 0) { virReportSystemError(errno, "%s", _("could not close logfile")); rc = -1; } for (i = 0; i < nveths; i++) { if (rc != 0 && veths[i]) ignore_value(virNetDevVethDelete(veths[i])); VIR_FREE(veths[i]); } if (rc != 0) { if (vm->newDef) { virDomainDefFree(vm->newDef); vm->newDef = NULL; } if (priv->monitor) { virObjectUnref(priv->monitor); priv->monitor = NULL; } virDomainConfVMNWFilterTeardown(vm); virSecurityManagerRestoreAllLabel(driver->securityManager, vm->def, false); virSecurityManagerReleaseLabel(driver->securityManager, vm->def); /* Clear out dynamically assigned labels */ if (vm->def->nseclabels && vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC) { VIR_FREE(vm->def->seclabels[0]->model); VIR_FREE(vm->def->seclabels[0]->label); VIR_FREE(vm->def->seclabels[0]->imagelabel); } } for (i = 0; i < nttyFDs; i++) VIR_FORCE_CLOSE(ttyFDs[i]); VIR_FREE(ttyFDs); VIR_FORCE_CLOSE(handshakefds[0]); VIR_FORCE_CLOSE(handshakefds[1]); VIR_FREE(logfile); virObjectUnref(cfg); virObjectUnref(caps); if (err) { virSetError(err); virFreeError(err); } return rc; error: err = virSaveLastError(); virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED); goto cleanup; }
int main(int argc, char **argv) { char *user = NULL; char *luser = NULL; char *host = NULL; char *port = "shell"; char *p; char lport[5]; struct passwd *pw; int af = AF_UNSPEC; struct addrinfo hint, *ai, *aip, *lai; int err, sock = -1, lsock = -1, esock = -1, i; int opt; bool verbose = false; char hostaddr[NI_MAXHOST]; char portnr[NI_MAXSERV]; char buf[3][BUFLEN], *bufp[3]; int len[3], wlen; fd_set infd, outfd, infdset, outfdset, errfd; int maxfd; int flags; argv0 = argv[0]; /* Lookup local username */ if (!(pw = getpwuid(getuid()))) { fprintf(stderr, "%s: Could not lookup username: %s\n", argv0, strerror(errno)); return 1; } user = luser = pw->pw_name; /* if we were called with something else from rsh use the name as host */ host = basename(argv0); if(!strcmp(host, "rsh") || !strcmp(host, "rsh-redone-rsh")) host = NULL; /* Process options */ while((opt = getopt(argc, argv, "-l:p:46vn")) != -1) { switch(opt) { case 1: if(!host) { host = optarg; break; } else { optind--; goto done; } case 'l': user = optarg; break; case 'p': port = optarg; break; case '4': af = AF_INET; break; case '6': af = AF_INET6; break; case 'v': verbose = true; break; case 'n': closestdin(); break; default: fprintf(stderr, "%s: Unknown option!\n", argv0); usage(); return 1; } } done: if(!host) { fprintf(stderr, "%s: No host specified!\n", argv0); usage(); return 1; } if(optind == argc) { execv(BINDIR "/rlogin", argv); fprintf(stderr, "%s: Could not execute " BINDIR "/rlogin: %s\n", argv0, strerror(errno)); return 1; } if((p = strchr(host, '@'))) { user = host; *p = '\0'; host = p + 1; } /* Resolve hostname and try to make a connection */ memset(&hint, '\0', sizeof hint); hint.ai_family = af; hint.ai_socktype = SOCK_STREAM; err = getaddrinfo(host, port, &hint, &ai); if(err) { fprintf(stderr, "%s: Error looking up host: %s\n", argv0, gai_strerror(err)); return 1; } hint.ai_flags = AI_PASSIVE; for(aip = ai; aip; aip = aip->ai_next) { if(getnameinfo(aip->ai_addr, aip->ai_addrlen, hostaddr, sizeof hostaddr, portnr, sizeof portnr, NI_NUMERICHOST | NI_NUMERICSERV)) { fprintf(stderr, "%s: Error resolving address: %s\n", argv0, strerror(errno)); return 1; } if(verbose) fprintf(stderr, "Trying %s port %s...", hostaddr, portnr); if((sock = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol)) == -1) { if(verbose) fprintf(stderr, " Could not open socket: %s\n", strerror(errno)); continue; } hint.ai_family = aip->ai_family; /* Bind to a privileged port */ for(i = 1023; i >= 512; i--) { snprintf(lport, sizeof lport, "%d", i); err = getaddrinfo(NULL, lport, &hint, &lai); if(err) { fprintf(stderr, " Error looking up localhost: %s\n", gai_strerror(err)); return 1; } err = bind(sock, lai->ai_addr, lai->ai_addrlen); freeaddrinfo(lai); if(err) continue; else break; } if(err) { if(verbose) fprintf(stderr, " Could not bind to privileged port: %s\n", strerror(errno)); continue; } if(connect(sock, aip->ai_addr, aip->ai_addrlen) == -1) { if(verbose) fprintf(stderr, " Connection failed: %s\n", strerror(errno)); continue; } if(verbose) fprintf(stderr, " Connected.\n"); break; } if(!aip) { fprintf(stderr, "%s: Could not make a connection.\n", argv0); return 1; } /* Create a socket for the incoming connection for stderr output */ if((lsock = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol)) == -1) { fprintf(stderr, "%s: Could not open socket: %s\n", argv0, strerror(errno)); return 1; } hint.ai_family = aip->ai_family; freeaddrinfo(ai); for(i--; i >= 512; i--) { snprintf(lport, sizeof lport, "%d", i); err = getaddrinfo(NULL, lport, &hint, &lai); if(err) { fprintf(stderr, "%s: Error looking up localhost: %s\n", argv0, gai_strerror(err)); return 1; } err = bind(lsock, lai->ai_addr, lai->ai_addrlen); freeaddrinfo(lai); if(err) continue; else break; } if(err) { fprintf(stderr, "%s: Could not bind to privileged port: %s\n", argv0, strerror(errno)); return 1; } if(listen(lsock, 10)) { fprintf(stderr, "%s: Could not listen: %s\n", argv0, strerror(errno)); return 1; } /* Drop privileges */ if(setuid(getuid())) { fprintf(stderr, "%s: Unable to drop privileges: %s\n", argv0, strerror(errno)); return 1; } /* Send required information to the server */ bufp[0] = buf[0]; len[0] = sizeof buf[0]; safecpy(&bufp[0], &len[0], lport, 1); safecpy(&bufp[0], &len[0], luser, 1); safecpy(&bufp[0], &len[0], user, 1); for(; optind < argc; optind++) { safecpy(&bufp[0], &len[0], argv[optind], 0); if(optind < argc - 1) safecpy(&bufp[0], &len[0], " ", 0); } safecpy(&bufp[0], &len[0], "", 1); if(!len[0]) { fprintf(stderr, "%s: Arguments too long!\n", argv0); return 1; } if(safewrite(sock, buf[0], bufp[0] - buf[0]) == -1) { fprintf(stderr, "%s: Unable to send required information: %s\n", argv0, strerror(errno)); return 1; } /* Wait for acknowledgement from server */ errno = 0; if(read(sock, buf[0], 1) != 1 || *buf[0]) { fprintf(stderr, "%s: Didn't receive NULL byte from server: %s\n", argv0, strerror(errno)); return 1; } /* Wait for incoming connection from server */ if((esock = accept(lsock, NULL, 0)) == -1) { fprintf(stderr, "%s: Could not accept stderr connection: %s\n", argv0, strerror(errno)); return 1; } close(lsock); /* Process input/output */ flags = fcntl(sock, F_GETFL); fcntl(sock, F_SETFL, flags | O_NONBLOCK); flags = fcntl(esock, F_GETFL); fcntl(esock, F_SETFL, flags | O_NONBLOCK); bufp[0] = buf[0]; bufp[1] = buf[1]; bufp[2] = buf[2]; FD_ZERO(&infdset); FD_ZERO(&outfdset); FD_SET(0, &infdset); FD_SET(sock, &infdset); FD_SET(esock, &infdset); maxfd = (sock>esock?sock:esock) + 1; for(;;) { errno = 0; infd = infdset; outfd = outfdset; errfd = infdset; if(select(maxfd, &infd, &outfd, &errfd, NULL) <= 0) { if(errno == EINTR) continue; else break; } if(FD_ISSET(esock, &infd)) { len[2] = read(esock, buf[2], BUFLEN); if(len[2] <= 0) { if(errno != EINTR) { if(FD_ISSET(sock, &infdset) || FD_ISSET(1, &outfdset)) FD_CLR(esock, &infdset); else break; } } else { FD_SET(2, &outfdset); FD_CLR(esock, &infdset); } } if(FD_ISSET(2, &outfd)) { wlen = write(2, bufp[2], len[2]); if(wlen <= 0) { if(errno != EINTR) { if(FD_ISSET(sock, &infdset) || FD_ISSET(1, &outfdset)) FD_CLR(esock, &infdset); else break; } } else { len[2] -= wlen; bufp[2] += wlen; if(!len[2]) { FD_CLR(2, &outfdset); FD_SET(esock, &infdset); bufp[2] = buf[2]; } } } if(FD_ISSET(sock, &infd)) { len[1] = read(sock, buf[1], BUFLEN); if(len[1] <= 0) { if(errno != EINTR) { if(FD_ISSET(esock, &infdset) || FD_ISSET(2, &outfdset)) FD_CLR(sock, &infdset); else break; } } else { FD_SET(1, &outfdset); FD_CLR(sock, &infdset); } } if(FD_ISSET(1, &outfd)) { wlen = write(1, bufp[1], len[1]); if(wlen <= 0) { if(errno != EINTR) { if(FD_ISSET(esock, &infdset) || FD_ISSET(2, &outfdset)) FD_CLR(sock, &infdset); else break; } } else { len[1] -= wlen; bufp[1] += wlen; if(!len[1]) { FD_CLR(1, &outfdset); FD_SET(sock, &infdset); bufp[1] = buf[1]; } } } if(FD_ISSET(0, &infd)) { len[0] = read(0, buf[0], BUFLEN); if(len[0] <= 0) { if(errno != EINTR) { FD_CLR(0, &infdset); shutdown(sock, SHUT_WR); } } else { FD_SET(sock, &outfdset); FD_CLR(0, &infdset); } } if(FD_ISSET(sock, &outfd)) { wlen = write(sock, bufp[0], len[0]); if(wlen <= 0) { if(errno != EINTR) break; } else { len[0] -= wlen; bufp[0] += wlen; if(!len[0]) { FD_CLR(sock, &outfdset); FD_SET(0, &infdset); bufp[0] = buf[0]; } } } } if(errno) { fprintf(stderr, "%s: %s\n", argv0, strerror(errno)); return 1; } close(sock); close(esock); return 0; }