示例#1
0
文件: run_erl.c 项目: aiyuefine/otp
/*
 * find_next_log_num()
 * Searches through the log directory to check which logs that already
 * exist. It finds the "hole" in the sequence, and returns the index
 * number for the last log in the log sequence. If there is no hole, index
 * 1 is returned.
 */
static int find_next_log_num(void) {
  int i, next_gen, log_gen;
  DIR *dirp;
  struct dirent *direntp;
  int log_exists[LOG_MAX_GENERATIONS+1];
  int stub_len = strlen(LOG_STUBNAME);

  /* Initialize exiting log table */

  for(i=log_generations; i>=0; i--)
    log_exists[i] = 0;
  dirp = opendir(log_dir);
  if(!dirp) {
    ERRNO_ERR1(LOG_ERR,"Can't access log directory '%s'", log_dir);
    exit(1);
  }

  /* Check the directory for existing logs */

  while((direntp=readdir(dirp)) != NULL) {
    if(strncmp(direntp->d_name,LOG_STUBNAME,stub_len)==0) {
      int num = atoi(direntp->d_name+stub_len);
      if(num < 1 || num > log_generations)
	continue;
      log_exists[num] = 1;
    }
  }	
  closedir(dirp);

  /* Find out the next available log file number */

  next_gen = 0;
  for(i=log_generations; i>=0; i--) {
    if(log_exists[i])
      if(next_gen)
	break;
      else 
	;
    else
      next_gen = i;
  }

  /* Find out the current log file number */

  if(next_gen)
    log_gen = prev_log(next_gen);
  else
    log_gen = 1;

  return log_gen;
} /* find_next_log_num() */
示例#2
0
static int open_log(int log_num, int flags)
{
  char buf[FILENAME_MAX];
  time_t now;
  struct tm *tmptr;
  char log_buffer[ALIVE_BUFFSIZ+1];

  /* Remove the next log (to keep a "hole" in the log sequence) */
  sn_printf(buf, sizeof(buf), "%s/%s%d",
	    LOG_DIR, LOG_STUBNAME, next_log(log_num));
  unlink(buf);

  /* Create or continue on the current log file */
  sn_printf(buf, sizeof(buf), "%s/%s%d", LOG_DIR, LOG_STUBNAME, log_num);

  LFD = sf_open(buf, flags, LOG_PERM);

  if(LFD <0){
      ERRNO_ERR1(LOG_ERR,"Can't open log file '%s'.", buf);
    exit(1);
  }

  /* Write a LOGGING STARTED and time stamp into the log file */
  time(&now);
  if (LOG_ALIVE_IN_GMT) {
      tmptr = gmtime(&now);
  } else {
      tmptr = localtime(&now);
  }
  if (!strftime(log_buffer, ALIVE_BUFFSIZ, LOG_ALIVE_FORMAT,
		tmptr)) {
      strn_cpy(log_buffer, sizeof(log_buffer),
	      "(could not format time in 256 positions "
	      "with current format string.)");
  }
  log_buffer[ALIVE_BUFFSIZ] = '\0';

  sn_printf(buf, sizeof(buf), "\n=====\n===== LOGGING STARTED %s\n=====\n",
	    log_buffer);
  if (erts_run_erl_write_all(LFD, buf, strlen(buf)) < 0)
      erts_run_erl_log_status("Error in writing to log.\n");

#if USE_FSYNC
  fsync(LFD);
#endif

  return LFD;
}
示例#3
0
文件: run_erl.c 项目: aiyuefine/otp
/* pass_on()
 * Is the work loop of the logger. Selects on the pipe to the to_erl
 * program erlang. If input arrives from to_erl it is passed on to
 * erlang.
 */
static void pass_on(pid_t childpid)
{
    int len;
    fd_set readfds;
    fd_set writefds;
    fd_set* writefds_ptr;
    struct timeval timeout;
    time_t last_activity;
    char buf[BUFSIZ];
    char log_alive_buffer[ALIVE_BUFFSIZ+1];
    int lognum;
    int rfd, wfd=0, lfd=0;
    int maxfd;
    int ready;
    int got_some = 0; /* from to_erl */
    
    /* Open the to_erl pipe for reading.
     * We can't open the writing side because nobody is reading and 
     * we'd either hang or get an error.
     */
    if ((rfd = sf_open(fifo2, O_RDONLY|DONT_BLOCK_PLEASE, 0)) < 0) {
	ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.", fifo2);
	exit(1);
    }
    
#ifdef DEBUG
    status("run_erl: %s opened for reading\n", fifo2);
#endif
    
    /* Open the log file */
    
    lognum = find_next_log_num();
    lfd = open_log(lognum, O_RDWR|O_APPEND|O_CREAT|O_SYNC);
    
    /* Enter the work loop */
    
    while (1) {
	int exit_status;
	maxfd = MAX(rfd, mfd);
	maxfd = MAX(wfd, maxfd);
	FD_ZERO(&readfds);
	FD_SET(rfd, &readfds);
	FD_SET(mfd, &readfds);
	FD_ZERO(&writefds);
	if (outbuf_size() == 0) {
	    writefds_ptr = NULL;
	} else {
	    FD_SET(wfd, &writefds);
	    writefds_ptr = &writefds;
	}
	time(&last_activity);
	timeout.tv_sec  = log_alive_minutes*60; /* don't assume old BSD bug */
	timeout.tv_usec = 0;
	ready = select(maxfd + 1, &readfds, writefds_ptr, NULL, &timeout);
	if (ready < 0) {
	    if (errno == EINTR) {
		if (waitpid(childpid, &exit_status, WNOHANG) == childpid) {
		    /*
		     * The Erlang emulator has terminated. Give us some more
		     * time to write out any pending data before we terminate too.
		     */
		    alarm(5);
		}
		FD_ZERO(&readfds);
		FD_ZERO(&writefds);
	    } else {
		/* Some error occured */
		ERRNO_ERR0(LOG_ERR,"Error in select.");
		exit(1);
	    }
	} else {
	    time_t now;

	    if (waitpid(childpid, &exit_status, WNOHANG) == childpid) {
		alarm(5);
		FD_ZERO(&readfds);
		FD_ZERO(&writefds);
	    }

	    /* Check how long time we've been inactive */
	    time(&now);
	    if(!ready || now - last_activity > log_activity_minutes*60) {
		/* Either a time out: 15 minutes without action, */
		/* or something is coming in right now, but it's a long time */
		/* since last time, so let's write a time stamp this message */
		struct tm *tmptr;
		if (log_alive_in_gmt) {
		    tmptr = gmtime(&now);
		} else {
		    tmptr = localtime(&now);
		}
		if (!strftime(log_alive_buffer, ALIVE_BUFFSIZ, log_alive_format,
			      tmptr)) {
		    strn_cpy(log_alive_buffer, sizeof(log_alive_buffer),
			     "(could not format time in 256 positions "
			     "with current format string.)");
		}
		log_alive_buffer[ALIVE_BUFFSIZ] = '\0';

		sn_printf(buf, sizeof(buf), "\n===== %s%s\n", 
			  ready?"":"ALIVE ", log_alive_buffer);
		write_to_log(&lfd, &lognum, buf, strlen(buf));
	    }
	}

	/*
	 * Write any pending output first.
	 */
	if (FD_ISSET(wfd, &writefds)) {
	    int written;
	    char* buf = outbuf_first();

	    len = outbuf_size();
	    written = sf_write(wfd, buf, len);
	    if (written < 0 && errno == EAGAIN) {
		/*
		 * Nothing was written - this is really strange because
		 * select() told us we could write. Ignore.
		 */
	    } else if (written < 0) {
		/*
		 * A write error. Assume that to_erl has terminated.
		 */
		clear_outbuf();
		sf_close(wfd);
		wfd = 0;
	    } else {
		/* Delete the written part (or all) from the buffer. */
		outbuf_delete(written);
	    }
	}
	
	/*
	 * Read master pty and write to FIFO.
	 */
	if (FD_ISSET(mfd, &readfds)) {
#ifdef DEBUG
	    status("Pty master read; ");
#endif
	    if ((len = sf_read(mfd, buf, BUFSIZ)) <= 0) {
		sf_close(rfd);
		if(wfd) sf_close(wfd);
		sf_close(mfd);
		unlink(fifo1);
		unlink(fifo2);
		if (len < 0) {
		    if(errno == EIO)
			ERROR0(LOG_ERR,"Erlang closed the connection.");
		    else
			ERRNO_ERR0(LOG_ERR,"Error in reading from terminal");
		    exit(1);
		}
		exit(0);
	    }

	    write_to_log(&lfd, &lognum, buf, len);

	    /*
	     * Save in the output queue.
	     */

	    if (wfd) {
		outbuf_append(buf, len);
	    }
	}	    

	/*
	 * Read from FIFO, write to master pty
	 */
	if (FD_ISSET(rfd, &readfds)) {
#ifdef DEBUG
	    status("FIFO read; ");
#endif
	    if ((len = sf_read(rfd, buf, BUFSIZ)) < 0) {
		sf_close(rfd);
		if(wfd) sf_close(wfd);
		sf_close(mfd);
		unlink(fifo1);
		unlink(fifo2);
		ERRNO_ERR0(LOG_ERR,"Error in reading from FIFO.");
		exit(1);
	    }

	    if(!len) {
		/* to_erl closed its end of the pipe */
		sf_close(rfd);
		rfd = sf_open(fifo2, O_RDONLY|DONT_BLOCK_PLEASE, 0);
		if (rfd < 0) {
		    ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.", fifo2);
		    exit(1);
		}
		got_some = 0; /* reset for next session */
	    }
	    else { 
		if(!wfd) {
		    /* Try to open the write pipe to to_erl. Now that we got some data
		     * from to_erl, to_erl should already be reading this pipe - open
		     * should succeed. But in case of error, we just ignore it.
		     */
		    if ((wfd = sf_open(fifo1, O_WRONLY|DONT_BLOCK_PLEASE, 0)) < 0) {
			status("Client expected on FIFO %s, but can't open (len=%d)\n",
			       fifo1, len);
			sf_close(rfd);
			rfd = sf_open(fifo2, O_RDONLY|DONT_BLOCK_PLEASE, 0);
			if (rfd < 0) {
			    ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.", fifo2);
			    exit(1);
			}
			wfd = 0;
		    } 
		    else {
#ifdef DEBUG
			status("run_erl: %s opened for writing\n", fifo1);
#endif
		    }
		}

		if (!got_some && wfd && buf[0] == '\014') {
		    char wbuf[30];
		    int wlen = sn_printf(wbuf,sizeof(wbuf),"[run_erl v%u-%u]\n",
					 RUN_ERL_HI_VER, RUN_ERL_LO_VER);
		    outbuf_append(wbuf,wlen);
		}
		got_some = 1;


		/* Write the message */
#ifdef DEBUG
		status("Pty master write; ");
#endif
		len = extract_ctrl_seq(buf, len);

		if(len==1 && buf[0] == '\003') {
		    kill(childpid,SIGINT);
		} 
		else if (len>0 && write_all(mfd, buf, len) != len) {
		    ERRNO_ERR0(LOG_ERR,"Error in writing to terminal.");
		    sf_close(rfd);
		    if(wfd) sf_close(wfd);
		    sf_close(mfd);
		    exit(1);
		}
	    }
#ifdef DEBUG
	    status("OK\n");
#endif
	}
    }
} /* pass_on() */
示例#4
0
文件: run_erl.c 项目: aiyuefine/otp
int main(int argc, char **argv)
{
  int childpid;
  int sfd = -1;
  int fd;
  char *p, *ptyslave=NULL;
  int i = 1;
  int off_argv;
  int calculated_pipename = 0;
  int highest_pipe_num = 0;

  program_name = argv[0];

  if(argc<4) {
    usage(argv[0]);
    exit(1);
  }

  init_outbuf();

  if (!strcmp(argv[1],"-daemon")) {
      daemon_init();
      ++i;
  }

  off_argv = i;
  strn_cpy(pipename, sizeof(pipename), argv[i++]);
  strn_cpy(log_dir, sizeof(log_dir), argv[i]);
  strn_cpy(statusfile, sizeof(statusfile), log_dir);
  strn_cat(statusfile, sizeof(statusfile), STATUSFILENAME);

#ifdef DEBUG
  status("%s: pid is : %d\n", argv[0], getpid());
#endif

  /* Get values for LOG file handling from the environment */
  if ((p = getenv("RUN_ERL_LOG_ALIVE_MINUTES"))) {
      log_alive_minutes = atoi(p);
      if (!log_alive_minutes) {
	  ERROR1(LOG_ERR,"Minimum value for RUN_ERL_LOG_ALIVE_MINUTES is 1 "
		 "(current value is %s)",p);
      }
      log_activity_minutes = log_alive_minutes / 3;
      if (!log_activity_minutes) {
	  ++log_activity_minutes;
      }
  }
  if ((p = getenv("RUN_ERL_LOG_ACTIVITY_MINUTES"))) {
     log_activity_minutes = atoi(p);
      if (!log_activity_minutes) {
	  ERROR1(LOG_ERR,"Minimum value for RUN_ERL_LOG_ACTIVITY_MINUTES is 1 "
		 "(current value is %s)",p);
      }
  } 
  if ((p = getenv("RUN_ERL_LOG_ALIVE_FORMAT"))) {
      if (strlen(p) > ALIVE_BUFFSIZ) {
	  ERROR1(LOG_ERR, "RUN_ERL_LOG_ALIVE_FORMAT can contain a maximum of "
		 "%d characters", ALIVE_BUFFSIZ);
      }
      strn_cpy(log_alive_format, sizeof(log_alive_format), p);
  } else {
      strn_cpy(log_alive_format, sizeof(log_alive_format), DEFAULT_LOG_ALIVE_FORMAT);
  }
  if ((p = getenv("RUN_ERL_LOG_ALIVE_IN_UTC")) && strcmp(p,"0")) {
      ++log_alive_in_gmt;
  }
  if ((p = getenv("RUN_ERL_LOG_GENERATIONS"))) {
    log_generations = atoi(p);
    if (log_generations < LOG_MIN_GENERATIONS)
      ERROR1(LOG_ERR,"Minimum RUN_ERL_LOG_GENERATIONS is %d", LOG_MIN_GENERATIONS);
    if (log_generations > LOG_MAX_GENERATIONS)
      ERROR1(LOG_ERR,"Maximum RUN_ERL_LOG_GENERATIONS is %d", LOG_MAX_GENERATIONS);
  }

  if ((p = getenv("RUN_ERL_LOG_MAXSIZE"))) {
    log_maxsize = atoi(p);
    if (log_maxsize < LOG_MIN_MAXSIZE)
      ERROR1(LOG_ERR,"Minimum RUN_ERL_LOG_MAXSIZE is %d", LOG_MIN_MAXSIZE);
  }

  /*
   * Create FIFOs and open them 
   */

  if(*pipename && pipename[strlen(pipename)-1] == '/') {
    /* The user wishes us to find a unique pipe name in the specified */
    /* directory */
    DIR *dirp;
    struct dirent *direntp;

    calculated_pipename = 1;
    dirp = opendir(pipename);
    if(!dirp) {
      ERRNO_ERR1(LOG_ERR,"Can't access pipe directory '%s'.", pipename);
      exit(1);
    }

    /* Check the directory for existing pipes */
    
    while((direntp=readdir(dirp)) != NULL) {
      if(strncmp(direntp->d_name,PIPE_STUBNAME,PIPE_STUBLEN)==0) {
	int num = atoi(direntp->d_name+PIPE_STUBLEN+1);
	if(num > highest_pipe_num)
	  highest_pipe_num = num;
      }
    }	
    closedir(dirp);
    strn_catf(pipename, sizeof(pipename), "%s.%d",
	      PIPE_STUBNAME, highest_pipe_num+1);
  } /* if */

  for(;;) {
      /* write FIFO - is read FIFO for `to_erl' program */
      strn_cpy(fifo1, sizeof(fifo1), pipename);
      strn_cat(fifo1, sizeof(fifo1), ".r");
      if (create_fifo(fifo1, PERM) < 0) {
	  ERRNO_ERR1(LOG_ERR,"Cannot create FIFO %s for writing.", fifo1);
	  exit(1);
      }
      
      /* read FIFO - is write FIFO for `to_erl' program */
      strn_cpy(fifo2, sizeof(fifo2), pipename);
      strn_cat(fifo2, sizeof(fifo2), ".w");
      
      /* Check that nobody is running run_erl already */
      if ((fd = sf_open(fifo2, O_WRONLY|DONT_BLOCK_PLEASE, 0)) >= 0) {
	  /* Open as client succeeded -- run_erl is already running! */
	  sf_close(fd);
	  if (calculated_pipename) {
	      ++highest_pipe_num;
	      strn_catf(pipename, sizeof(pipename), "%s.%d",
			PIPE_STUBNAME, highest_pipe_num+1);
	      continue;
	  } 
	  fprintf(stderr, "Erlang already running on pipe %s.\n", pipename);
	  exit(1);
      }
      if (create_fifo(fifo2, PERM) < 0) { 
	  ERRNO_ERR1(LOG_ERR,"Cannot create FIFO %s for reading.", fifo2);
	  exit(1);
      }
      break;
  }

  /*
   * Open master pseudo-terminal
   */

  if ((mfd = open_pty_master(&ptyslave, &sfd)) < 0) {
    ERRNO_ERR0(LOG_ERR,"Could not open pty master");
    exit(1);
  }

  /* 
   * Now create a child process
   */

  if ((childpid = fork()) < 0) {
    ERRNO_ERR0(LOG_ERR,"Cannot fork");
    exit(1);
  }
  if (childpid == 0) {
    /* Child */
    sf_close(mfd);
    /* disassociate from control terminal */
#ifdef USE_SETPGRP_NOARGS       /* SysV */
    setpgrp();
#elif defined(USE_SETPGRP)       /* BSD */
    setpgrp(0,getpid());
#else                           /* POSIX */
    setsid();
#endif
    /* Open the slave pty */
    if (sfd < 0) {
	/* not allocated by open_pty_master */
	if ((sfd = open_pty_slave(ptyslave)) < 0) {
	    ERRNO_ERR1(LOG_ERR,"Could not open pty slave '%s'", ptyslave);
	    exit(1);
	}
	/* But sfd may be one of the stdio fd's now, and we should be unmodern and not use dup2... */
	/* easiest to dup it up... */
	while (sfd < 3) {
	    sfd = dup(sfd);
	}
    }
#if defined(HAVE_OPENPTY) && defined(TIOCSCTTY)
    else {
	/* sfd is from open_pty_master 
	 * openpty -> fork -> login_tty (forkpty)
	 * 
	 * It would be preferable to implement a portable 
	 * forkpty instead of open_pty_master / open_pty_slave
	 */
	/* login_tty(sfd);  <- FAIL */
	ioctl(sfd, TIOCSCTTY, (char *)NULL);
    }
#endif

#ifndef NO_SYSLOG
    /* Before fiddling with file descriptors we make sure syslog is turned off
       or "closed". In the single case where we might want it again, 
       we will open it again instead. Would not want syslog to
       go to some other fd... */
    if (run_daemon) {
	closelog();
    }
#endif

    /* Close stdio */
    sf_close(0);
    sf_close(1);
    sf_close(2);

    if (dup(sfd) != 0 || dup(sfd) != 1 || dup(sfd) != 2) {
      status("Cannot dup\n");
    }
    sf_close(sfd);
    exec_shell(argv+off_argv); /* exec_shell expects argv[2] to be */
                        /* the command name, so we have to */
                        /* adjust. */
  } else {
    /* Parent */
    /* Ignore the SIGPIPE signal, write() will return errno=EPIPE */
    struct sigaction sig_act;
    sigemptyset(&sig_act.sa_mask);
    sig_act.sa_flags = 0;
    sig_act.sa_handler = SIG_IGN;
    sigaction(SIGPIPE, &sig_act, (struct sigaction *)NULL);

    sigemptyset(&sig_act.sa_mask);
    sig_act.sa_flags = SA_NOCLDSTOP;
    sig_act.sa_handler = catch_sigchild;
    sigaction(SIGCHLD, &sig_act, (struct sigaction *)NULL);

    /*
     * read and write: enter the workloop
     */

    pass_on(childpid);
  }
  return 0;
} /* main() */
示例#5
0
文件: run_erl.c 项目: NaughtyCode/otp
int pass_on(ProgramState *s) {
  SIGSELECT sigsel[] = {0,FM_READ_PTR_REPLY};
  union SIGNAL *sig;
  char child_read_buff[BUFSIZ], pipe_read_buff[BUFSIZ];
  struct aiocb child_read_req, pipe_read_req;
  int rfd, wfd = 0;
  FmHandle rfh, child_rfh;
  int outstanding_writes = 0, got_some = 0, child_done = 0;

  if ((rfd = sf_open(s->r_pipe, O_RDONLY, 0)) < 0) {
    ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.\n", s->r_pipe);
    rfd = 0;
    return 1;
  }

  attach(NULL,s->progpid);

  /* Open the log file */
  erts_run_erl_log_open();

  efs_examine_fd(rfd,FLIB_FD_HANDLE,&rfh);
  efs_examine_fd(s->ifd,FLIB_FD_HANDLE,&child_rfh);

  READ_AIO(child_read_req,s->ifd,BUFSIZ,child_read_buff);
  READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_read_buff);

  while (1) {
    time_t now,last_activity;

    time(&last_activity);
    sig = receive_w_tmo(erts_run_erl_log_alive_minutes()*60000,sigsel);

    time(&now);

    if (sig) {
      erts_run_erl_log_activity(0,now,last_activity);
    } else {
      /* timeout */
      erts_run_erl_log_activity(1,now,last_activity);
      continue;
    }

    switch (sig->signo) {
    case OS_ATTACH_SIG: {
      if (rfd) { sf_close(rfd); rfd = 0; }
      free_buf(&sig);
      child_done = 1;
      /* Make sure to to let all outstanding write request finish */
      if (outstanding_writes)
	break;
      if (wfd) sf_close(wfd);
      return 0;
    }
    case FM_WRITE_PTR_REPLY: {
      if (sig->fm_write_ptr.status == EFS_SUCCESS) {
	if (sig->fm_write_ptr.actual < sig->fm_write_ptr.requested) {
	  WRITE_AIO(wfd, sig->fm_write_ptr.requested-sig->fm_write_ptr.actual,
		    sig->fm_write_ptr.buffer+sig->fm_write_ptr.actual);
	}
      } else {
	/* Assume to_erl has terminated. */
	sf_close(wfd);
	wfd = 0;
      }
      free((char*)sig->fm_write_ptr.buffer);
      aio_dispatch(sig);
      if ((--outstanding_writes == 0) && child_done) {
	if (wfd) sf_close(wfd);
	return 0;
      }
      break;
    }
    case FM_READ_PTR_REPLY: {
      /* Child fd */
      if (sig->fm_read_ptr.handle == child_rfh) {

	/* Child terminated */
	if (sig->fm_read_ptr.status != EFS_SUCCESS ||
	    sig->fm_read_ptr.actual == 0) {

	  if (rfd) { sf_close(rfd); rfd = 0; }

	  if (sig->fm_read_ptr.status != EFS_SUCCESS) {
	    ERROR0(LOG_ERR,"Erlang closed the connection.");
	    aio_dispatch(sig);
	    return 1;
	  }

	  /* child closed connection gracefully */
	  aio_dispatch(sig);
	  if (outstanding_writes) {
	    child_done = 1;
	    break;
	  }

	  if (wfd) sf_close(wfd);

	  return 0;
	} else {
	  erts_run_erl_log_write(sig->fm_read_ptr.buffer,
				 sig->fm_read_ptr.actual);
	  if (wfd) {
	    WRITE_AIO(wfd, sig->fm_read_ptr.actual, sig->fm_read_ptr.buffer);
	    outstanding_writes++;
	  }
	  aio_dispatch(sig);
	  READ_AIO(child_read_req, s->ifd,BUFSIZ, child_read_buff);
	}
      /* pipe fd */
      } else if (sig->fm_read_ptr.handle == rfh) {
	if (sig->fm_read_ptr.status != EFS_SUCCESS) {
	  if(rfd) sf_close(rfd);
	  if(wfd) sf_close(wfd);
	  aio_dispatch(sig);
	  ERRNO_ERR0(LOG_ERR,"Error in reading from FIFO.");
	  return 1;
	}
	if (sig->fm_read_ptr.actual == 0) {
	  /* to_erl closed its end of the pipe */
	  aio_dispatch(sig);
	  sf_close(rfd);
	  rfd = sf_open(s->r_pipe,O_RDONLY|DONT_BLOCK_PLEASE, 0);
	  if (rfd < 0) {
	    ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.",
		       s->r_pipe);
	    rfd = 0;
	  } else {
	    READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_read_buff);
	  }
	  got_some = 0; /* reset for next session */
	} else {
	  int len = sig->fm_read_ptr.actual;
	  char *buffer = sig->fm_read_ptr.buffer;
	  if (!wfd) {
	    /* Try to open the write pipe to to_erl. Now that we got some data
	     * from to_erl, to_erl should already be reading this pipe - open
	     * should succeed. But in case of error, we just ignore it.
	     */
	    if ((wfd = sf_open(s->w_pipe, O_WRONLY|DONT_BLOCK_PLEASE, 0)) < 0) {
	      erts_run_erl_log_status("Client expected on FIFO %s, "
				      "but can't open (len=%d)\n",
				      s->w_pipe, sig->fm_read_ptr.actual);
	      sf_close(rfd);
	      rfd = sf_open(s->r_pipe, O_RDONLY|DONT_BLOCK_PLEASE, 0);
	      if (rfd < 0) {
		ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.",
			   s->r_pipe);
		return 1;
	      }
	      wfd = 0;
	    } else {
#ifdef DEBUG
	      erts_run_erl_log_status("run_erl: %s opened for writing\n",
				      s->w_pipe);
#endif
	    }
	  }

	  if (!got_some && wfd && buffer[0] == '\014') {
	    char wbuf[30];
	    int wlen = sn_printf(wbuf,sizeof(wbuf),"[run_erl v%u-%u]\n",
				 RUN_ERL_HI_VER, RUN_ERL_LO_VER);
	    /* For some reason this, the first write aio seems to
	       not get an FM_WRITE_PTR_REPLY, so we do not do:
	       outstanding_writes++;
	    */
	    WRITE_AIO(wfd, wlen, wbuf);
	  }
	  got_some = 1;

	  /* Write the message */
#ifdef DEBUG
	  erts_run_erl_log_status("Pty master write; ");
#endif
	  len = erts_run_erl_extract_ctrl_seq(buffer,len, s->ofd);

	  if (len > 0) {
	    int wlen = erts_run_erl_write_all(s->ofd, buffer, len);
	    if (wlen != len) {
	      aio_dispatch(sig);
	      ERRNO_ERR0(LOG_ERR,"Error in writing to terminal.");
	      if(rfd) sf_close(rfd);
	      if(wfd) sf_close(wfd);
	      return 1;
	    }
	  }
#ifdef DEBUG
	  erts_run_erl_log_status("OK\n");
#endif
	  aio_dispatch(sig);
	  READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_read_buff);
	}
	}
      break;
    }
    default: {
      free_buf(&sig);
      break;
    }
    }
  }
}
示例#6
0
/*
 * w- and r_pipename have to be pre-allocated of atleast FILENAME_MAX size
 */
int erts_run_erl_open_fifo(char *pipename,char *w_pipename,char *r_pipename) {
  int calculated_pipename = 0;
  int highest_pipe_num = 0;
  int fd;

  /*
   * Create FIFOs and open them
   */

  if(*pipename && pipename[strlen(pipename)-1] == '/') {
    /* The user wishes us to find a unique pipe name in the specified */
    /* directory */
    DIR *dirp;
    struct dirent *direntp;

    calculated_pipename = 1;
    dirp = opendir(pipename);
    if(!dirp) {
      ERRNO_ERR1(LOG_ERR,"Can't access pipe directory '%s'.", pipename);
      return 1;
    }

    /* Check the directory for existing pipes */

    while((direntp=readdir(dirp)) != NULL) {
      if(strncmp(direntp->d_name,PIPE_STUBNAME,PIPE_STUBLEN)==0) {
	int num = atoi(direntp->d_name+PIPE_STUBLEN+1);
	if(num > highest_pipe_num)
	  highest_pipe_num = num;
      }
    }
    closedir(dirp);
    strn_catf(pipename, BUFSIZ, "%s.%d",
	      PIPE_STUBNAME, highest_pipe_num+1);
  } /* if */

  for(;;) {
      /* write FIFO - is read FIFO for `to_erl' program */
      strn_cpy(w_pipename, BUFSIZ, pipename);
      strn_cat(w_pipename, BUFSIZ, ".r");
      if (create_fifo(w_pipename, PERM) < 0) {
	  ERRNO_ERR1(LOG_ERR,"Cannot create FIFO %s for writing.",
		     w_pipename);
	  return 1;
      }

      /* read FIFO - is write FIFO for `to_erl' program */
      strn_cpy(r_pipename, BUFSIZ, pipename);
      strn_cat(r_pipename, BUFSIZ, ".w");

      /* Check that nobody is running run_erl already */
      if ((fd = sf_open(r_pipename, O_WRONLY|DONT_BLOCK_PLEASE, 0)) >= 0) {
	  /* Open as client succeeded -- run_erl is already running! */
	  sf_close(fd);
	  if (calculated_pipename) {
	      ++highest_pipe_num;
	      strn_catf(pipename, BUFSIZ, "%s.%d",
			PIPE_STUBNAME, highest_pipe_num+1);
	      continue;
	  }
	  ERROR1(LOG_ERR, "Erlang already running on pipe %s.\n", pipename);
	  unlink(w_pipename);
	  return 1;
      }
      if (create_fifo(r_pipename, PERM) < 0) {
	  unlink(w_pipename);
	  ERRNO_ERR1(LOG_ERR,"Cannot create FIFO %s for reading.",
		     r_pipename);
	  return 1;
      }
      break;
  }
  return 0;
}