Example #1
0
/*
 * 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));
    }
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
int virshStreamSink(virStreamPtr st ATTRIBUTE_UNUSED,
                    const char *bytes, size_t nbytes, void *opaque)
{
    int *fd = opaque;

    return safewrite(*fd, bytes, nbytes);
}
Example #5
0
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;
}
Example #6
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;
}
Example #7
0
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;
}
Example #8
0
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
}
Example #9
0
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));
}
Example #10
0
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;
}
Example #11
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);

}
Example #12
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)) {
        goto error_out;
    }

    rc = 0;
error_out:
    return rc;
}
Example #13
0
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;
}
Example #14
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));
}
Example #15
0
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);
}
Example #16
0
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;
}
Example #17
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;
}
Example #18
0
/**
 * 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;
}
Example #19
0
File: qmail2bbs.c Project: wyat/kbs
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;
}
Example #20
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;
}
Example #21
0
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;
}
Example #22
0
/*
 * 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;
}
Example #23
0
/* 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;

}
Example #24
0
/**
 * 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);
}
Example #25
0
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;
}
Example #26
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;
}
Example #27
0
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;
}
Example #28
0
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;
}
Example #29
0
/**
 * 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;
}
Example #30
0
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;
}