Exemplo n.º 1
0
static void simple_readpipe(SIMPLE_THREAD_REC *rec, GIOChannel *pipe)
{
	RESOLVED_IP_REC iprec;
	GIOChannel *handle;
	IPADDR *ip;

	g_return_if_fail(rec != NULL);

	g_source_remove(rec->tag);

	net_gethostbyname_return(pipe, &iprec);
	g_free_not_null(iprec.errorstr);

	g_io_channel_close(rec->pipes[0]);
	g_io_channel_unref(rec->pipes[0]);
	g_io_channel_close(rec->pipes[1]);
	g_io_channel_unref(rec->pipes[1]);

	ip = iprec.ip4.family != 0 ? &iprec.ip4 : &iprec.ip6;
	handle = iprec.error == -1 ? NULL :
		net_connect_ip(ip, rec->port, rec->my_ip);

	g_free_not_null(rec->my_ip);

	if (handle == NULL) {
		/* failed */
		rec->func(NULL, rec->data);
		g_free(rec);
		return;
	}

	rec->tag = g_input_add(handle, G_INPUT_READ | G_INPUT_WRITE,
			       (GInputFunction) simple_init, rec);
}
Exemplo n.º 2
0
/* connection to server failed */
void server_connect_failed(SERVER_REC *server, const char *msg)
{
	g_return_if_fail(IS_SERVER(server));

	lookup_servers = g_slist_remove(lookup_servers, server);

	signal_emit("server connect failed", 2, server, msg);

	if (server->connect_tag != -1) {
		g_source_remove(server->connect_tag);
		server->connect_tag = -1;
	}
	if (server->handle != NULL) {
		net_sendbuffer_destroy(server->handle, TRUE);
		server->handle = NULL;
	}

	if (server->connect_pipe[0] != NULL) {
		g_io_channel_close(server->connect_pipe[0]);
		g_io_channel_unref(server->connect_pipe[0]);
		g_io_channel_close(server->connect_pipe[1]);
		g_io_channel_unref(server->connect_pipe[1]);
		server->connect_pipe[0] = NULL;
		server->connect_pipe[1] = NULL;
	}

	server_unref(server);
}
Exemplo n.º 3
0
static gboolean
input_callback (GIOChannel   *source,
		GIOCondition  condition,
		gpointer      data)
{
  int val;
  GIOChannel *dest = (GIOChannel *)data;
  
  if (!read_all (source, (char *)&val, sizeof(val)))
    {
      fprintf (stderr, "Unexpected EOF\n");
      exit (1);
    }

  if (val)
    {
      write_all (dest, (char *)&val, sizeof(val));
      
      return TRUE;
    }
  else
    {
      g_io_channel_close (source);
      g_io_channel_close (dest);

      n_active_children--;
      if (n_active_children == 0)
	g_main_loop_quit (loop);
      
      return FALSE;
    }
}
Exemplo n.º 4
0
static gboolean incoming_data(GIOChannel *io, GIOCondition cond, gpointer ptr)
{
	int fd = g_io_channel_unix_get_fd(io);
	UNUSED(cond);
	UNUSED(ptr);

	char filename[FILENAME_MAX + 1];
	ssize_t len = recvfrom(fd, filename, FILENAME_MAX, 0, NULL, 0);
	if (len < 0) {
		if (errno == EAGAIN)
			return 0;
		warning("recv failed (%s)\n", strerror(errno));
		g_io_channel_close(io);
		return FALSE;
	}
	if (len == 0) {
		g_io_channel_close(io);
		return FALSE;
	}
	filename[len] = 0;
	struct playlist_entry *entry = add_file_playlist(main_playlist, filename);
	if (entry)
		put_entry(entry);
	return TRUE;
}
Exemplo n.º 5
0
/*---------------------------------------------------------------------*/
static void
close_io_channels() {
   if( hop_stdout ) g_io_channel_close( hop_stdout );
   if( hop_stderr ) g_io_channel_close( hop_stderr );

   close( hop_pipe_stdout[ 0 ] );
   close( hop_pipe_stdout[ 1 ] );
   close( hop_pipe_stderr[ 0 ] );
   close( hop_pipe_stderr[ 1 ] );
}
Exemplo n.º 6
0
static gboolean	listen_from_server(GIOChannel *io, GIOCondition condition,
				   void *cnt)
{
  gchar		buf[512];
  gsize		nbr;
  t_message	msg;

  debug("listen_from_server()");
  (void) condition;
  if (g_io_channel_read(io, buf, CLIENT_READ_BUF_SIZE, &nbr)
      != G_IO_ERROR_NONE)
    {
      g_io_channel_close(io);
      return (-1);
    }
  buf[nbr] = '\0';
  if (nbr > 0)
    {
      extract_msg((char *) buf, &msg);
      printf("[%s]\n", msg.command);
      mesg_init(cnt, &msg);
      insert_mesg_to_list(cnt, EMPTY, "server", trim(buf));
    }
  scrolled_window(cnt, SCROLL_MESG);
  g_io_add_watch(io, G_IO_IN, listen_from_server, cnt);
  return (0);
}
Exemplo n.º 7
0
static void
save_log (const char *filename)
{
	GIOChannel *file;
	GError *err;
	gssize size;
	char *history;

	err = NULL;
	file = g_io_channel_new_file (filename, "w", &err);
	if (file == NULL) {
		print_error (err);
		return;
	}
	print_error (err);
	g_assert (err == NULL);

	history = warlock_view_get_text (NULL);

	(void)g_io_channel_write_chars (file, history, -1, &size, &err);
	debug ("%" G_GSSIZE_FORMAT " characters written to file\n", size);
	print_error (err);

	g_free (history);

	g_io_channel_close (file);
	g_io_channel_unref (file);
}
Exemplo n.º 8
0
/* Disconnect socket */
void net_disconnect(GIOChannel *handle)
{
	g_return_if_fail(handle != NULL);

	g_io_channel_close(handle);
	g_io_channel_unref(handle);
}
Exemplo n.º 9
0
static void
rc_line_buf_finalize (GObject *obj)
{
    RCLineBuf *line_buf;

    line_buf = RC_LINE_BUF (obj);

    if (line_buf->priv->buf) {
        g_string_free (line_buf->priv->buf, TRUE);
    }

    if (line_buf->priv->cb_id) {
        g_source_remove (line_buf->priv->cb_id);
    }

    if (line_buf->priv->channel) {
        g_io_channel_close (line_buf->priv->channel);
        g_io_channel_unref (line_buf->priv->channel);
    }

    g_free (line_buf->priv);

    if (parent_class->finalize)
        parent_class->finalize (obj);
} /* rc_line_buf_finalize */
Exemplo n.º 10
0
static void
create_child (void)
{
  int pid;
  GIOChannel *in_channels[2];
  GIOChannel *out_channels[2];
  GSource *source;
  
  io_pipe (in_channels);
  io_pipe (out_channels);

  pid = fork ();

  if (pid > 0)			/* Parent */
    {
      g_io_channel_close (in_channels[0]);
      g_io_channel_close (out_channels[1]);

      source = g_io_create_watch (out_channels[0], G_IO_IN | G_IO_HUP);
      g_source_set_closure (source,
                            g_cclosure_new (G_CALLBACK (input_callback), in_channels[1],
                                            (GClosureNotify)g_io_channel_unref));
      g_source_attach (source, NULL);
      g_source_unref (source);

      g_io_channel_unref (in_channels[0]);
      g_io_channel_unref (out_channels[0]);
      g_io_channel_unref (out_channels[1]);

    }
  else if (pid == 0)		/* Child */
    {
      g_io_channel_close (in_channels[1]);
      g_io_channel_close (out_channels[0]);

      setsid ();

      run_child (in_channels[0], out_channels[1]);
    }
  else				/* Error */
    {
      fprintf (stderr, "Cannot fork: %s\n", g_strerror (errno));
      exit (1);
    }
}
Exemplo n.º 11
0
static void on_log_button_toggled (GtkWidget *widget, gpointer data) {
   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
     gtk_editable_set_editable( GTK_EDITABLE(mb_gui.entry_log), FALSE );
     const gchar *log_file_name = gtk_entry_get_text (GTK_ENTRY (mb_gui.entry_log));
     GError* my_err = NULL;
     mb_state.log_channel = g_io_channel_new_file (log_file_name, "w", &my_err);
     GString* static_name = g_string_sized_new(128);
     g_string_printf(static_name,"%s%s", log_file_name, "_static"); 
     mb_state.log_channel_static = g_io_channel_new_file (static_name->str, "w", &my_err);
     g_string_free(static_name, TRUE);
   }
   else {
     gtk_editable_set_editable( GTK_EDITABLE(mb_gui.entry_log), TRUE );
     if (mb_state.log_channel) {
       g_io_channel_close(mb_state.log_channel);
       g_io_channel_close(mb_state.log_channel_static);
       mb_state.log_channel = NULL;
       mb_state.log_channel_static = NULL;
     }
   }
}
Exemplo n.º 12
0
static void close_connection(struct vhci_conn *conn)
{
	syslog(LOG_INFO, "Closing connection %s handle %d",
					batostr(&conn->dest), conn->handle);

	g_io_channel_close(conn->chan);
	g_io_channel_unref(conn->chan);

	vconn[conn->handle - 1] = NULL;
	disconn_complete(conn);
	free(conn);
}
Exemplo n.º 13
0
static int scan_enable(uint8_t *data)
{
	struct sockaddr_in sa;
	GIOChannel *sk_io;
	bdaddr_t ba;
	int sk, opt;

	if (!(*data & SCAN_PAGE)) {
		if (vdev.scan) {
			g_io_channel_close(vdev.scan);
			vdev.scan = NULL;
		}
		return 0;
	}

	if (vdev.scan)
		return 0;

	if ((sk = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		syslog(LOG_ERR, "Can't create socket: %s (%d)",
						strerror(errno), errno);
		return 1;
	}

	opt = 1;
	setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

	baswap(&ba, &vdev.bdaddr);
	sa.sin_family = AF_INET;
	sa.sin_addr.s_addr = *(uint32_t *) &ba;
	sa.sin_port = *(uint16_t *) &ba.b[4];
	if (bind(sk, (struct sockaddr *) &sa, sizeof(sa))) {
		syslog(LOG_ERR, "Can't bind socket: %s (%d)",
						strerror(errno), errno);
		goto failed;
	}

	if (listen(sk, 10)) {
		syslog(LOG_ERR, "Can't listen on socket: %s (%d)",
						strerror(errno), errno);
		goto failed;
	}

	sk_io = g_io_channel_unix_new(sk);
	g_io_add_watch(sk_io, G_IO_IN | G_IO_NVAL, io_conn_ind, NULL);
	vdev.scan = sk_io;
	return 0;

failed:
	close(sk);
	return 1;
}
Exemplo n.º 14
0
static void
create_child (void)
{
  int pid, errsv;
  GIOChannel *in_channels[2];
  GIOChannel *out_channels[2];
  
  io_pipe (in_channels);
  io_pipe (out_channels);

  pid = fork ();
  errsv = errno;

  if (pid > 0)			/* Parent */
    {
      g_io_channel_close (in_channels[0]);
      g_io_channel_unref (in_channels[0]);
      g_io_channel_close (out_channels[1]);
      g_io_channel_unref (out_channels[1]);

      g_io_add_watch (out_channels[0], G_IO_IN | G_IO_HUP,
		      input_callback, in_channels[1]);
    }
  else if (pid == 0)		/* Child */
    {
      g_io_channel_close (in_channels[1]);
      g_io_channel_close (out_channels[0]);

      setsid ();

      run_child (in_channels[0], out_channels[1]);
    }
  else				/* Error */
    {
      fprintf (stderr, "Cannot fork: %s\n", g_strerror (errsv));
      exit (1);
    }
}
Exemplo n.º 15
0
gboolean handle_read( GIOChannel *sock, GIOCondition cond, http_request *h ) {
    g_debug( "entering handle_read" );
    http_request_read( h );

    if (! http_request_ok(h))
	return TRUE;

    handle_request(h);

    g_io_channel_close( h->sock );
    g_io_channel_unref( h->sock );
    http_request_free( h );
    g_debug( "exiting handle_read" );
    return FALSE;
}
Exemplo n.º 16
0
static void simple_init(SIMPLE_THREAD_REC *rec, GIOChannel *handle)
{
	g_return_if_fail(rec != NULL);

	g_source_remove(rec->tag);

	if (net_geterror(handle) != 0) {
		/* failed */
		g_io_channel_close(handle);
                g_io_channel_unref(handle);
		handle = NULL;
	}

	rec->func(handle, rec->data);
	g_free(rec);
}
Exemplo n.º 17
0
static gboolean
file_read_data (GIOChannel   *iochannel,
                GIOCondition  condition,
                gpointer      user_data)
{
    RCDTransfer *t = user_data;
    RCDTransferProtocolFile *protocol = (RCDTransferProtocolFile *) t->protocol;
    GIOError err;
    char buf[BLOCK_SIZE];
    gsize bytes;

    if (!(condition & G_IO_IN))
        goto ERROR;

    err = g_io_channel_read (iochannel, buf, BLOCK_SIZE, &bytes);

    if (bytes)
        rcd_transfer_emit_data (t, buf, bytes);

    if (err == G_IO_ERROR_AGAIN)
        return TRUE;

    if (err != G_IO_ERROR_NONE)
        goto ERROR;

    if (bytes > 0) {
        /* More data to read.  Whee. */
        return TRUE;
    }
    else {
        /* No more bytes to read and no error condition; the file is done */
        g_io_channel_close (iochannel);
        rcd_transfer_emit_done (t);

        return FALSE;
    }

ERROR:
    g_source_remove (protocol->watch);

    rcd_transfer_set_error (t, RCD_TRANSFER_ERROR_IO, NULL);
    rcd_transfer_emit_done (t);

    return FALSE;
}
Exemplo n.º 18
0
static void rfcomm_node_free(struct rfcomm_node *node)
{
	if (node->device)
		g_free(node->device);
	if (node->conn)
		dbus_connection_unref(node->conn);
	if (node->owner)
		g_free(node->owner);
	if (node->svcname)
		g_free(node->svcname);
	if (node->io) {
		g_source_remove(node->io_id);
		g_io_channel_close(node->io);
		g_io_channel_unref(node->io);
	}
	rfcomm_release(node->id);
	g_free(node);
}
Exemplo n.º 19
0
void avrcp_exit(void)
{
	if (!avctp_server)
		return;

	g_io_channel_close(avctp_server);
	g_io_channel_unref(avctp_server);
	avctp_server = NULL;

#ifndef ANDROID
	remove_record_from_server(ct_record_id);
	ct_record_id = 0;
#endif
	remove_record_from_server(tg_record_id);
	tg_record_id = 0;

	dbus_connection_unref(connection);
	connection = NULL;
}
Exemplo n.º 20
0
RemminaFile* remmina_rdp_file_import(const gchar* from_file)
{
	GIOChannel* channel;
	GError* error = NULL;
	RemminaFile* remminafile;

	channel = g_io_channel_new_file(from_file, "r", &error);

	if (channel == NULL)
	{
		g_print("Failed to import %s: %s\n", from_file, error->message);
		return NULL;
	}

	remminafile = remmina_rdp_file_import_channel(channel);
	g_io_channel_close(channel);

	return remminafile;
}
Exemplo n.º 21
0
/* Callback handling data */
static int receive_data(int fd, int revents, void *session_data)
{
	struct sr_datafeed_packet packet;
	struct sr_datafeed_logic logic;
	static uint64_t samples_received = 0;
	unsigned char c[BUFSIZE];
	gsize z;

	/* Avoid compiler warnings. */
	(void)fd;
	(void)revents;

	do {
		g_io_channel_read_chars(channels[0],
				        (gchar *)&c, BUFSIZE, &z, NULL);

		if (z > 0) {
			packet.type = SR_DF_LOGIC;
			packet.payload = &logic;
			packet.timeoffset =  samples_received * period_ps;
			packet.duration = z * period_ps;
			logic.length = z;
			logic.unitsize = 1;
			logic.data = c;
			sr_session_bus(session_data, &packet);
			samples_received += z;
		}
	} while (z > 0);

	if (!thread_running && z <= 0) {
		/* Make sure we don't receive more packets. */
		g_io_channel_close(channels[0]);

		/* Send last packet. */
		packet.type = SR_DF_END;
		sr_session_bus(session_data, &packet);

		return FALSE;
	}

	return TRUE;
}
Exemplo n.º 22
0
void
alleyoop_kill (Alleyoop *grind)
{
	vg_tool_view_disconnect ((VgToolView *) grind->view);
	
	if (grind->gio) {
		g_io_channel_close (grind->gio);
		g_io_channel_unref (grind->gio);
		grind->watch_id = 0;
		grind->gio = NULL;
	}
	
	if (grind->pid != (pid_t) -1) {
		process_kill (grind->pid);
		grind->pid = (pid_t) -1;
	}
	
	gtk_widget_set_sensitive (grind->toolbar_run, TRUE);
	gtk_widget_set_sensitive (grind->toolbar_kill, FALSE);
}
Exemplo n.º 23
0
static gboolean server_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
{
	struct sockaddr_un addr;
	socklen_t addrlen;
	int sk, cli_sk;
	struct unix_client *client;
	GIOChannel *io;

	if (cond & G_IO_NVAL)
		return FALSE;

	if (cond & (G_IO_HUP | G_IO_ERR)) {
		g_io_channel_close(chan);
		return FALSE;
	}

	sk = g_io_channel_unix_get_fd(chan);

	memset(&addr, 0, sizeof(addr));
	addrlen = sizeof(addr);

	cli_sk = accept(sk, (struct sockaddr *) &addr, &addrlen);
	if (cli_sk < 0) {
		error("accept: %s (%d)", strerror(errno), errno);
		return TRUE;
	}

	DBG("Accepted new client connection on unix socket (fd=%d)", cli_sk);
	set_nonblocking(cli_sk);

	client = g_new0(struct unix_client, 1);
	client->sock = cli_sk;
	clients = g_slist_append(clients, client);

	io = g_io_channel_unix_new(cli_sk);
	g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
							client_cb, client);
	g_io_channel_unref(io);

	return TRUE;
}
Exemplo n.º 24
0
static void process_destroy(PROCESS_REC *rec, int status)
{
	processes = g_slist_remove(processes, rec);

	signal_emit("exec remove", 2, rec, GINT_TO_POINTER(status));

	if (rec->read_tag != -1)
		g_source_remove(rec->read_tag);
	if (rec->target_item != NULL)
                exec_wi_destroy(rec->target_item);

	line_split_free(rec->databuf);
        g_io_channel_close(rec->in);
        g_io_channel_unref(rec->in);
        net_sendbuffer_destroy(rec->out, TRUE);

	g_free_not_null(rec->name);
	g_free_not_null(rec->target);
        g_free(rec->args);
        g_free(rec);
}
Exemplo n.º 25
0
static gint
generate_support_data (const gchar *filename)
{
	GIOChannel *channel;
	GError     *error = NULL;

	if (g_str_equal (filename, "-")) {
		channel = g_io_channel_unix_new (0);
	}
	else if (!(channel = g_io_channel_new_file (filename, "w", &error))) {
		g_printerr ("%s\n", error->message);
		g_error_free (error);
		return EXIT_FAILURE;
	}

	g_io_channel_write_chars (channel, "[system]\n", -1, NULL, NULL);
	generate_date (channel);
	generate_system_info (channel);
	g_io_channel_write_chars (channel, "\n", -1, NULL, NULL);

	g_io_channel_write_chars (channel, "[perfkit]\n", -1, NULL, NULL);
	write_kv (channel, "lib.version", PK_VERSION_S);
	write_kv (channel, "agent.version", PKA_VERSION_S);
	g_io_channel_write_chars (channel, "\n", -1, NULL, NULL);

	generate_channels (channel);

	/* TODO */

	if (!g_io_channel_flush (channel, &error)) {
		g_printerr ("%s\n", error->message);
		g_error_free (error);
		return EXIT_FAILURE;
	}

	g_io_channel_close (channel);

	return EXIT_SUCCESS;
}
Exemplo n.º 26
0
void
rc_line_buf_set_fd (RCLineBuf *line_buf, int fd)
{
    if (line_buf->priv->cb_id) {
        g_source_remove (line_buf->priv->cb_id);
    }

    if (line_buf->priv->channel) {
        g_io_channel_close (line_buf->priv->channel);
        g_io_channel_unref (line_buf->priv->channel);
    }

    if (line_buf->priv->buf) {
        g_string_truncate (line_buf->priv->buf, 0);
    }

    line_buf->priv->channel = g_io_channel_unix_new (fd);

    line_buf->priv->cb_id = g_io_add_watch (line_buf->priv->channel,
                                            G_IO_IN | G_IO_HUP | G_IO_ERR,
                                            (GIOFunc) rc_line_buf_cb,
                                            (gpointer) line_buf);
} /* rc_line_buf_set_fd */
Exemplo n.º 27
0
// to be called at program start and anytime the value of auto-log changes
static void
log_toggle (void)
{
	char *key;
	gboolean autolog;

	key = preferences_get_key (PREF_AUTO_LOG);
	autolog = preferences_get_bool (key);
	g_free (key);

	if (autolog && log_file == NULL) {
		GError *err;
		char *filename, *name, *path, *path_key;

		path_key = preferences_get_key (PREF_LOG_PATH);
		path = preferences_get_string (path_key);
		g_free (path_key);

		name = warlock_log_get_name ();

		filename = g_build_filename (path, name, NULL);

		g_free (name);
		g_free (path);

		err = NULL;
		log_file = g_io_channel_new_file (filename, "a", &err);
		if (log_file == NULL) {
			echo_f ("Error: \"%s\" for file \"%s\".\n",
					err->message, filename);
		}
	} else if (!autolog && log_file != NULL) {
		g_io_channel_close (log_file);
		g_io_channel_unref (log_file);
		log_file = NULL;
	}
}
Exemplo n.º 28
0
static void server_connect_callback_readpipe(SERVER_REC *server)
{
	RESOLVED_IP_REC iprec;
        IPADDR *ip;
	const char *errormsg;
	char *servername = NULL;

	g_source_remove(server->connect_tag);
	server->connect_tag = -1;

	net_gethostbyname_return(server->connect_pipe[0], &iprec);

	g_io_channel_close(server->connect_pipe[0]);
	g_io_channel_unref(server->connect_pipe[0]);
	g_io_channel_close(server->connect_pipe[1]);
	g_io_channel_unref(server->connect_pipe[1]);

	server->connect_pipe[0] = NULL;
	server->connect_pipe[1] = NULL;

	/* figure out if we should use IPv4 or v6 address */
	if (iprec.error != 0) {
                /* error */
		ip = NULL;
	} else if (server->connrec->family == AF_INET) {
		/* force IPv4 connection */
		ip = iprec.ip4.family == 0 ? NULL : &iprec.ip4;
		servername = iprec.host4;
	} else if (server->connrec->family == AF_INET6) {
		/* force IPv6 connection */
		ip = iprec.ip6.family == 0 ? NULL : &iprec.ip6;
		servername = iprec.host6;
	} else {
		/* pick the one that was found, or if both do it like
		   /SET resolve_prefer_ipv6 says. */
		if (iprec.ip4.family == 0 ||
		    (iprec.ip6.family != 0 &&
		     settings_get_bool("resolve_prefer_ipv6"))) {
			ip = &iprec.ip6;
			servername = iprec.host6;
		} else {
			ip = &iprec.ip4;
			servername = iprec.host4;
		}
	}

	if (ip != NULL) {
		/* host lookup ok */
		if (servername) {
			g_free(server->connrec->address);
			server->connrec->address = g_strdup(servername);
		}
		server_real_connect(server, ip, NULL);
		errormsg = NULL;
	} else {
		if (iprec.error == 0 || net_hosterror_notfound(iprec.error)) {
			/* IP wasn't found for the host, don't try to
			   reconnect back to this server */
			server->dns_error = TRUE;
		}

		if (iprec.error == 0) {
			/* forced IPv4 or IPv6 address but it wasn't found */
			errormsg = server->connrec->family == AF_INET ?
				"IPv4 address not found for host" :
				"IPv6 address not found for host";
		} else {
			/* gethostbyname() failed */
			errormsg = iprec.errorstr != NULL ? iprec.errorstr :
				"Host lookup failed";
		}

		server->connection_lost = TRUE;
		server_connect_failed(server, errormsg);
	}

	g_free(iprec.errorstr);
	g_free(iprec.host4);
	g_free(iprec.host6);
}
Exemplo n.º 29
0
/** cgi_handoff - hand off to CGI v1.1 (subset of)
 * @see http://tools.ietf.org/html/draft-robinson-www-interface-00
 * @param url requested
 * @param client to serve to
 * @param data - cgiroot
 *
 * TODO:
 *   - fix input/output to child.  I should be able to dup the socket
 *     such that the child processes stdin is the un-read payload data in
 *     in the socket and its stdout writes to the socket yet I haven't figured
 *     that out yet.  In the meantime I'm saving the payload to a file
 *     and providing that to the CGI as PAYLOAD_FILE
 */
gboolean
cgi_handoff(MediaURL *url, GstHTTPClient *client, gpointer data)
{
	const char *cgiroot = (const char*) data;
	gchar *path;
	gchar *scriptname;
	char *physpath;
	int pid;
	int outfd[2];
	int infd[2];
#ifdef CAPTURE_PAYLOAD
	int payload_len = 0;
#endif

	scriptname = url->path + strlen(CGI_PATH) + 2;
	path = g_strconcat(cgiroot, "/", scriptname, NULL);
	physpath = realpath(path, NULL);
	if (!physpath)
		goto err;
	/* ensure physpath is within cgiroot */
	if (strncmp(physpath, cgiroot, strlen(cgiroot)) ||
	   ((physpath[strlen(cgiroot)] != 0) && (physpath[strlen(cgiroot)] != '/')) )
	{
		goto err;
	}
	/* ensure file is executable */
	if (access(physpath, X_OK) < 0)
	{
		goto err;
	}

	/* capture post data to a file */
#ifdef CAPTURE_PAYLOAD
{
	gsize rz;
	gsize sz;
	gchar buf[100];
	gchar *str;
	int len;

	str = gst_http_client_get_header(client, "Content-Length");
	if (str)
		payload_len = atoi(str);

	if (payload_len) {
		len = payload_len;
		GST_DEBUG("Reading %d byte payload\n", len);
		GIOChannel *out = g_io_channel_new_file(CAPTURE_PAYLOAD, "w+", NULL);
		if (!out) {
			GST_ERROR("failed to open payload file %s: %s (%d)\n", CAPTURE_PAYLOAD,
				strerror(errno), errno);
		} else {
			while (len) {
				sz = sizeof(buf);
				if (len < sz)
					sz = len;
				g_io_channel_read_chars(client->gio, buf, sz, &rz, NULL);
// why does g_io_channel_read_chars work and read block?
//			rz = read(client->sock, &buf, sz);
				len -= rz;
				g_io_channel_write_chars(out, buf, rz, &sz, NULL);
			}
			g_io_channel_flush(out, NULL);
			g_io_channel_close(out);
		}
	}
}
#endif

	GST_INFO("Executing %s to %s:%d", physpath, client->peer_ip, client->port);

	pipe(outfd); // where the parent is going to write to
	pipe(infd);  // from where parent is going to read

	pid = fork();
	if (pid < 0) {
		GST_ERROR("fork failed: %d\n", errno);
		goto err;
	}

	// child
	if (pid == 0) {
		char *envp[32];
		int envc = 0;

#ifdef CAPTURE_PAYLOAD
		if (payload_len)
			envp[envc++] = g_strdup_printf("PAYLOAD_FILE=%s", CAPTURE_PAYLOAD);
#endif
		envp[envc++] = g_strdup_printf("REQUEST_URI=%s", url->path);
		envp[envc++] = g_strdup_printf("DOCUMENT_ROOT=%s", docroot);
		envp[envc++] = g_strdup_printf("SERVER_PROTOCOL=1.0");
		envp[envc++] = g_strdup_printf("SERVER_SOFTWARE=gst-httpd/" VERSION);
		envp[envc++] = g_strdup_printf("CONTENT_LENGTH=%s",
			gst_http_client_get_header(client, "Content-Length"));
		envp[envc++] = g_strdup_printf("CONTENT_TYPE=%s",
			gst_http_client_get_header(client, "Content-Type"));
		envp[envc++] = g_strdup_printf("REQUEST_METHOD=%s", url->method);
		envp[envc++] = g_strdup_printf("SCRIPT_FILENAME=%s", physpath);
		envp[envc++] = g_strdup_printf("SCRIPT_NAME=%s", scriptname);
		envp[envc++] = g_strdup_printf("QUERY_STRING=%s", url->query);
		envp[envc++] = g_strdup_printf("REMOTE_ADDR=%s", client->peer_ip);
		envp[envc++] = 0;

		close(STDOUT_FILENO);
		close(STDIN_FILENO);

		dup2(outfd[0], STDIN_FILENO);
		dup2(infd[1], STDOUT_FILENO);

		// not required for child
		close(outfd[0]);
		close(outfd[1]);
		close(infd[0]);
		close(infd[1]);

		//	execl(physpath, physpath, NULL);
		execle(physpath, physpath, NULL, envp);

		/* should not get here unless error */
		exit(0);
	}

	// parent
	else {
		int sz;
		char buf[1024];
		siginfo_t status;
		int res;
		int waiting;

		GST_INFO("spawned CGI child pid=%d\n", pid);

		// these are being used by the child
		close(outfd[0]);
		close(infd[1]);

/*
		write(outfd[1], "foobar\n", 7); // write to childs stdin
		char input[100];
		input[read(infd[0], input, 100)] = 0; // read for child's stdin
*/

		/* send childs stdout to client socket */
		waiting = 1;
		while (waiting) {
			if ((sz = read(infd[0], buf, sizeof(buf))) > 0) {
				write(client->sock, buf, sz);
			}
			status.si_pid = 0;
			res = waitid(P_PID, pid, &status, WEXITED | WSTOPPED | WNOHANG | WNOWAIT);
			if (status.si_pid == 0)
				continue;
			switch (status.si_code) {
				case CLD_EXITED: // child called exit (normal)
				case CLD_KILLED: // child killed by signal
				case CLD_DUMPED: // child killed by signal and dumped core
				case CLD_STOPPED: // child stopped by signal
				case CLD_TRAPPED: // child trapped
					waiting = 0;
					break;
			}
		}
		GST_DEBUG("cgi returned %d\n", status.si_status);
		write(client->sock, "", 0);

		close(outfd[1]);
		close(infd[0]);

		// reap the process
		waitpid(pid, NULL, 0);
	}
	free(physpath);
	g_free(path);
	return TRUE;

err:
	GST_ERROR("404 Not Found: %s", path);
	if (physpath)
		free(physpath);
	g_free(path);
	return TRUE;
}