Пример #1
0
gs_vertbuffer_t *create_uv_vbuffer(uint32_t num_verts, bool add_color) {
	obs_enter_graphics();

	gs_vertbuffer_t *tmp = NULL;
	struct gs_vb_data *vrect = NULL;

	vrect = gs_vbdata_create();
	vrect->num = num_verts;
	vrect->points = (struct vec3 *)bmalloc(sizeof(struct vec3) * num_verts);
	vrect->num_tex = 1;
	vrect->tvarray =
		(struct gs_tvertarray *)bmalloc(sizeof(struct gs_tvertarray));
	vrect->tvarray[0].width = 2;
	vrect->tvarray[0].array = bmalloc(sizeof(struct vec2) * num_verts);
	if (add_color)
		vrect->colors = (uint32_t *)bmalloc
		(sizeof(uint32_t)* num_verts);

	memset(vrect->points, 0, sizeof(struct vec3) * num_verts);
	memset(vrect->tvarray[0].array, 0, sizeof(struct vec2) * num_verts);
	if (add_color)
		memset(vrect->colors, 0, sizeof(uint32_t)* num_verts);

	tmp = gs_vertexbuffer_create(vrect, GS_DYNAMIC);

	if (tmp == NULL) {
		blog(LOG_WARNING, "Couldn't create UV vertex buffer.");
	}

	obs_leave_graphics();
	
	return tmp;
}
Пример #2
0
bstr *bstr_new(void)
{
  bstr *str;
  str = bmalloc(sizeof(bstr));
  str->bufsiz = 64;
  str->length = 0;
  str->text = bmalloc(str->bufsiz);
  str->text[0] = '\0';
  return str;
}
Пример #3
0
static inline struct source_frame *cache_video(obs_source_t source,
        const struct source_frame *frame)
{
    /* TODO: use an actual cache */
    struct source_frame *new_frame = bmalloc(sizeof(struct source_frame));
    memcpy(new_frame, frame, sizeof(struct source_frame));
    new_frame->data = bmalloc(frame->row_bytes * frame->height);

    return new_frame;
}
Пример #4
0
/*
 * Allocate a new, empty output struct and call bail if memory allocation
 * fails.
 */
struct output *
output_new(void)
{
    struct output *output;

    output = bmalloc(sizeof(struct output));
    output->count = 0;
    output->allocated = 1;
    output->strings = bmalloc(sizeof(char *));
    output->strings[0] = NULL;
    return output;
}
Пример #5
0
char *bstrdup(char *str)
{
  char *newstr;

  if (str) {
    newstr = bmalloc(strlen(str) + 1);
    strcpy(newstr, str);
  } else {
    newstr = bmalloc(1);
    newstr[0] = '\0';
  }
  return newstr;
}
Пример #6
0
static void *random_create(obs_data_t settings, obs_source_t source)
{
	struct random_tex *rt = bzalloc(sizeof(struct random_tex));
	uint32_t *pixels = bmalloc(20*20*4);
	size_t x, y;

	for (y = 0; y < 20; y++) {
		for (x = 0; x < 20; x++) {
			uint32_t pixel = 0xFF000000;
			pixel |= (rand()%256);
			pixel |= (rand()%256) << 8;
			pixel |= (rand()%256) << 16;
			//pixel |= 0xFFFFFFFF;
			pixels[y*20 + x] = pixel;
		}
	}

	gs_entercontext(obs_graphics());

	rt->texture = gs_create_texture(20, 20, GS_RGBA, 1,
			(const void**)&pixels, 0);
	bfree(pixels);

	if (!rt->texture) {
		random_destroy(rt);
		return NULL;
	}

	gs_leavecontext();

	UNUSED_PARAMETER(settings);
	UNUSED_PARAMETER(source);
	return rt;
}
Пример #7
0
static void coreaudio_enum_devices(struct device_list *list, bool input)
{
	AudioObjectPropertyAddress addr = {
		kAudioHardwarePropertyDevices,
		kAudioObjectPropertyScopeGlobal,
		kAudioObjectPropertyElementMaster
	};

	UInt32        size = 0;
	UInt32        count;
	OSStatus      stat;
	AudioDeviceID *ids;

	stat = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &addr,
			0, NULL, &size);
	if (!enum_success(stat, "get kAudioObjectSystemObject data size"))
		return;

	ids   = bmalloc(size);
	count = size / sizeof(AudioDeviceID);

	stat = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr,
			0, NULL, &size, ids);

	if (enum_success(stat, "get kAudioObjectSystemObject data"))
		for (UInt32 i = 0; i < count; i++)
			coreaudio_enum_add_device(list, ids[i], input);

	bfree(ids);
}
Пример #8
0
obs_scene_t obs_scene_create(const char *name)
{
	struct obs_source *source = bmalloc(sizeof(struct obs_source));
	struct obs_scene  *scene;

	memset(source, 0, sizeof(struct obs_source));
	if (!obs_source_init_handlers(source)) {
		bfree(source);
		return NULL;
	}

	source->settings = obs_data_create();
	scene = scene_create(source->settings, source);
	source->data = scene;

	assert(scene);
	if (!scene) {
		obs_data_release(source->settings);
		bfree(source);
		return NULL;
	}

	source->name  = bstrdup(name);
	source->type  = SOURCE_SCENE;

	scene->source = source;
	obs_source_init(source, &scene_info);
	memcpy(&source->callbacks, &scene_info, sizeof(struct source_info));
	return scene;
}
Пример #9
0
/*
 * Create the plugin object
 */
static void *pulse_create(obs_data_t settings, obs_source_t source)
{
	UNUSED_PARAMETER(settings);

	struct pulse_data *data = bmalloc(sizeof(struct pulse_data));
	memset(data, 0, sizeof(struct pulse_data));

	data->source = source;
	data->speakers = SPEAKERS_STEREO;

	blog(LOG_DEBUG, "pulse-input: obs wants '%s'",
		obs_data_getstring(settings, "device_id"));

	/* TODO: use obs-studio icon */
	data->props = pa_proplist_new();
	pa_proplist_sets(data->props, PA_PROP_APPLICATION_NAME,
		"OBS Studio");
	pa_proplist_sets(data->props, PA_PROP_APPLICATION_ICON_NAME,
		"application-exit");
	pa_proplist_sets(data->props, PA_PROP_MEDIA_ROLE,
		"production");

	if (os_event_init(&data->event, OS_EVENT_TYPE_MANUAL) != 0)
		goto fail;
	if (pthread_create(&data->thread, NULL, pulse_thread, data) != 0)
		goto fail;

	return data;

fail:
	pulse_destroy(data);
	return NULL;
}
Пример #10
0
int audio_output_open(audio_t *audio, media_t media, struct audio_info *info)
{
	struct audio_output *out;

	if (!valid_audio_params(info))
		return AUDIO_OUTPUT_INVALIDPARAM;

	out = bmalloc(sizeof(struct audio_output));
	memset(out, 0, sizeof(struct audio_output));

	memcpy(&out->info, info, sizeof(struct audio_info));
	pthread_mutex_init_value(&out->line_mutex);
	out->media = media;
	out->block_size = get_audio_channels(info->speakers) *
	                  get_audio_bytes_per_channel(info->format);

	if (pthread_mutex_init(&out->line_mutex, NULL) != 0)
		goto fail;
	if (event_init(&out->stop_event, true) != 0)
		goto fail;
	if (!ao_add_to_media(out))
		goto fail;
	if (pthread_create(&out->thread, NULL, audio_thread, out) != 0)
		goto fail;

	out->initialized = true;
	*audio = out;
	return AUDIO_OUTPUT_SUCCESS;

fail:
	audio_output_close(out);
	return AUDIO_OUTPUT_FAIL;
}
Пример #11
0
obs_properties_t obs_properties_create()
{
	struct obs_properties *list;
	list = bmalloc(sizeof(struct obs_properties));
	memset(list, 0, sizeof(struct obs_properties));
	return list;
}
Пример #12
0
size_t os_wcs_to_utf8_ptr(const wchar_t *str, size_t len, char **pstr)
{
	size_t out_len = os_wcs_to_utf8(str, len, NULL);

	*pstr = bmalloc((out_len+1) * sizeof(char));
	return os_wcs_to_utf8(str, out_len, *pstr);
}
Пример #13
0
size_t os_mbs_to_wcs_ptr(const char *str, size_t len, wchar_t **pstr)
{
	size_t  out_len = os_mbs_to_wcs(str, len, NULL);

	*pstr = bmalloc((out_len+1) * sizeof(wchar_t));
	return os_mbs_to_wcs(str, out_len, *pstr);
}
Пример #14
0
static void *scene_create(obs_data_t *settings, struct obs_source *source)
{
	pthread_mutexattr_t attr;
	struct obs_scene *scene = bmalloc(sizeof(struct obs_scene));
	scene->source     = source;
	scene->first_item = NULL;

	signal_handler_add_array(obs_source_get_signal_handler(source),
			obs_scene_signals);

	if (pthread_mutexattr_init(&attr) != 0)
		goto fail;
	if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0)
		goto fail;
	if (pthread_mutex_init(&scene->audio_mutex, &attr) != 0) {
		blog(LOG_ERROR, "scene_create: Couldn't initialize audio "
				"mutex");
		goto fail;
	}
	if (pthread_mutex_init(&scene->video_mutex, &attr) != 0) {
		blog(LOG_ERROR, "scene_create: Couldn't initialize video "
				"mutex");
		goto fail;
	}

	UNUSED_PARAMETER(settings);
	return scene;

fail:
	pthread_mutexattr_destroy(&attr);
	bfree(scene);
	return NULL;
}
Пример #15
0
blistd *blistd_einit(void **vs, int ct) {
    blistd *b = (blistd *) bmalloc(sizeof(blistd));
    if (b == NULL) return NULL;
    int i = 0;
    for (; i < ct; i++) blistd_append(b, vs[i]);
    return b;
}
Пример #16
0
static void
appendview(			/* append standard view */
	char	*nm,
	VIEW	*vp
)
{
	FILE	*fp;
					/* check if already in there */
	if (!memcmp(&thisview, vwl[currentview].v, sizeof(VIEW))) {
		error(COMMAND, "view already in standard list");
		return;
	}
					/* append to file */
	if ((fp = fopen(radfile, "a")) == NULL) {
		error(COMMAND, "cannot append rad input file");
		return;
	}
	fputs("view=", fp);
	if (nm != NULL) {
		fputc(' ', fp); fputs(nm, fp);
	}
	fprintview(vp, fp); fputc('\n', fp);
	fclose(fp);
					/* append to our list */
	while (vwl[currentview].v != NULL)
		currentview++;
	if (currentview >= MAXVIEW)
		error(INTERNAL, "too many views in appendview");
	vwl[currentview].v = (VIEW *)bmalloc(sizeof(VIEW));
	*(vwl[currentview].v) = thisview;
	if (nm != NULL)
		vwl[currentview].nam = savqstr(nm);
}
Пример #17
0
char *read_line(HANDLE hin)
{
  char *buf;
  int bufsize = 32, strind = 0;
  DWORD bytes_read;

  buf = bmalloc(bufsize);

  while (1) {
    if (!ReadFile(hin, &buf[strind], 1, &bytes_read, NULL)) {
      printf("Read error\n");
      break;
    }
    if (bytes_read == 0) {
      buf[strind] = '\0';
      break;
    } else if (buf[strind] == '\r')
      continue;
    else if (buf[strind] == '\n') {
      buf[strind++] = '\0';
      break;
    } else {
      strind++;
      if (strind >= bufsize) {
        bufsize *= 2;
        buf = brealloc(buf, bufsize);
      }
    }
  }
  if (strind == 0) {
    bfree(buf);
    return NULL;
  } else
    return buf;
}
Пример #18
0
static BSR *store_fileregex(LEX *lc, BSR *bsr)
{
   int token;
   int rc;

   token = lex_get_token(lc, T_STRING);
   if (token == T_ERROR) {
      return NULL;
   }

   if (bsr->fileregex) free(bsr->fileregex);
   bsr->fileregex = bstrdup(lc->str);

   if (bsr->fileregex_re == NULL)
      bsr->fileregex_re = (regex_t *)bmalloc(sizeof(regex_t));

   rc = regcomp(bsr->fileregex_re, bsr->fileregex, REG_EXTENDED|REG_NOSUB);
   if (rc != 0) {
      char prbuf[500];
      regerror(rc, bsr->fileregex_re, prbuf, sizeof(prbuf));
      Emsg2(M_ERROR, 0, _("REGEX '%s' compile error. ERR=%s\n"),
            bsr->fileregex, prbuf);
      return NULL;
   }
   return bsr;
}
Пример #19
0
void *fade_create(obs_data_t *settings, obs_source_t *source)
{
    struct fade_info *fade;
    char *file = obs_module_file("fade_transition.effect");
    gs_effect_t *effect;

    obs_enter_graphics();
    effect = gs_effect_create_from_file(file, NULL);
    obs_leave_graphics();
    bfree(file);

    if (!effect) {
        blog(LOG_ERROR, "Could not find fade_transition.effect");
        return NULL;
    }

    fade = bmalloc(sizeof(*fade));
    fade->source = source;
    fade->effect = effect;
    fade->a_param = gs_effect_get_param_by_name(effect, "tex_a");
    fade->b_param = gs_effect_get_param_by_name(effect, "tex_b");
    fade->fade_param = gs_effect_get_param_by_name(effect, "fade_val");

    UNUSED_PARAMETER(settings);
    return fade;
}
Пример #20
0
char *
savqstr(char *s)			/* save a private string */
{
	static char  *curp = NULL;		/* allocated memory pointer */
	static unsigned  nrem = 0;		/* bytes remaining in block */
	static unsigned  nextalloc = MINBLOCK;	/* next block size */
	char  *cp;
	unsigned  n;

	for (cp = s; *cp++; )			/* compute strlen()+1 */
		;
	if ((n = cp-s) > nrem) {		/* do we need more core? */
		bfree(curp, nrem);			/* free remnant */
		while (n > nextalloc)
			nextalloc <<= 1;
		if ((curp = bmalloc(nrem=nextalloc)) == NULL) {
			eputs("out of memory in savqstr");
			quit(1);
		}
		if ((nextalloc <<= 1) > MAXBLOCK)	/* double block size */
			nextalloc = MAXBLOCK;
	}
	for (cp = curp; *cp++ = *s++; )		/* inline strcpy() */
		;
	s = curp;				/* update allocation info. */
	curp = cp;
	nrem -= n;
	return(s);				/* return new location */
}
Пример #21
0
size_t os_fread_mbs(FILE *file, char **pstr)
{
	size_t size = 0;
	size_t len = 0;

	fseeko(file, 0, SEEK_END);
	size = (size_t)ftello(file);
	*pstr = NULL;

	if (size > 0) {
		char *mbstr = bmalloc(size+1);

		fseeko(file, 0, SEEK_SET);
		size = fread(mbstr, 1, size, file);
		if (size == 0) {
			bfree(mbstr);
			return 0;
		}

		mbstr[size] = 0;
		len = os_mbs_to_utf8(mbstr, size, pstr);
		bfree(mbstr);
	}

	return len;
}
Пример #22
0
obs_source_t obs_source_create(enum obs_source_type type, const char *id,
                               const char *name, const char *settings)
{
    struct obs_source *source;

    const struct source_info *info = get_source_info(type, id);
    if (!info) {
        blog(LOG_WARNING, "Source '%s' not found", id);
        return NULL;
    }

    source = bmalloc(sizeof(struct obs_source));
    memset(source, 0, sizeof(struct obs_source));

    if (!obs_source_init_handlers(source))
        goto fail;

    source->name = bstrdup(name);
    source->type = type;
    source->data = info->create(settings, source);
    if (!source->data)
        goto fail;

    if (!obs_source_init(source, settings, info))
        goto fail;

    obs_source_dosignal(source, "source-create");
    return source;

fail:
    blog(LOG_ERROR, "obs_source_create failed");
    obs_source_destroy(source);
    return NULL;
}
Пример #23
0
/*
 * This automatically manages FBOs so that render targets are always given
 * an FBO that matches their width/height/format to maximize optimization
 */
struct fbo_info *get_fbo(struct gs_device *device,
		uint32_t width, uint32_t height, enum gs_color_format format)
{
	size_t i;
	GLuint fbo;
	struct fbo_info *ptr;

	for (i = 0; i < device->fbos.num; i++) {
		ptr = device->fbos.array[i];

		if (ptr->width  == width && ptr->height == height &&
		    ptr->format == format)
			return ptr;
	}

	glGenFramebuffers(1, &fbo);
	if (!gl_success("glGenFramebuffers"))
		return NULL;

	ptr = bmalloc(sizeof(struct fbo_info));
	ptr->fbo                 = fbo;
	ptr->width               = width;
	ptr->height              = height;
	ptr->format              = format;
	ptr->cur_render_target   = NULL;
	ptr->cur_render_side     = 0;
	ptr->cur_zstencil_buffer = NULL;

	da_push_back(device->fbos, &ptr);
	return ptr;
}
Пример #24
0
int gs_create(graphics_t *pgraphics, const char *module,
		struct gs_init_data *data)
{
	int errcode = GS_ERROR_FAIL;

	graphics_t graphics = bmalloc(sizeof(struct graphics_subsystem));
	memset(graphics, 0, sizeof(struct graphics_subsystem));
	pthread_mutex_init_value(&graphics->mutex);

	graphics->module = os_dlopen(module);
	if (!graphics->module) {
		errcode = GS_ERROR_MODULENOTFOUND;
		goto error;
	}

	if (!load_graphics_imports(&graphics->exports, graphics->module,
	                           module))
		goto error;

	graphics->device = graphics->exports.device_create(data);
	if (!graphics->device)
		goto error;

	if (!graphics_init(graphics))
		goto error;

	*pgraphics = graphics;
	return GS_SUCCESS;

error:
	gs_destroy(graphics);
	return errcode;
}
Пример #25
0
char *cf_literal_to_str(const char *literal, size_t count)
{
	const char *temp_src;
	char *str, *temp_dst;

	if (!count)
		count = strlen(literal);

	if (count < 2)
		return NULL;
	if (literal[0] != literal[count-1])
		return NULL;
	if (literal[0] != '\"' && literal[0] != '\'')
		return NULL;

	str = bmalloc(count - 1);
	temp_src = literal;
	temp_dst = str;

	while (*temp_src) {
		if (*temp_src == '\\') {
			temp_src++;
			cf_convert_from_escape_literal(&temp_dst, &temp_src);
		} else {
			*(temp_dst++) = *(temp_src++);
		}
	}

	*temp_dst = 0;
	return str;
}
Пример #26
0
device_t device_create(struct gs_init_data *info)
{
	struct gs_device *device = bmalloc(sizeof(struct gs_device));
	memset(device, 0, sizeof(struct gs_device));

	device->plat = gl_platform_create(device, info);
	if (!device->plat)
		goto fail;

	if (!gl_init_extensions(device))
		goto fail;
	
	gl_enable(GL_CULL_FACE);
	
	glGenProgramPipelines(1, &device->pipeline);
	if (!gl_success("glGenProgramPipelines"))
		goto fail;

	glBindProgramPipeline(device->pipeline);
	if (!gl_success("glBindProgramPipeline"))
		goto fail;

	device_leavecontext(device);
	device->cur_swap = gl_platform_getswap(device->plat);

	return device;

fail:
	blog(LOG_ERROR, "device_create (GL) failed");
	bfree(device);
	return NULL;
}
Пример #27
0
vertbuffer_t gs_rendersave(void)
{
	graphics_t graphics = thread_graphics;
	size_t num_tex, i;

	if (graphics->using_immediate)
		return NULL;

	if (!graphics->vbd->num) {
		vbdata_destroy(graphics->vbd);
		return NULL;
	}

	for (num_tex = 0; num_tex < 16; num_tex++) {
		if (!graphics->texverts[num_tex].num)
			break;
	}

	graphics->vbd->points  = graphics->verts.array;
	graphics->vbd->normals = graphics->norms.array;
	graphics->vbd->colors  = graphics->colors.array;
	graphics->vbd->num     = graphics->verts.num;
	graphics->vbd->num_tex = num_tex;
	graphics->vbd->tvarray = bmalloc(sizeof(struct tvertarray) * num_tex);
	for (i = 0; i < num_tex; i++) {
		graphics->vbd->tvarray[i].width = 2;
		graphics->vbd->tvarray[i].array = graphics->texverts[i].array;
	}

	reset_immediate_arrays(graphics);

	return gs_create_vertexbuffer(graphics->vbd, 0);
}
Пример #28
0
static void
initambfile(		/* initialize ambient file */
	int  cre8
)
{
	extern char  *progname, *octname;
	static char  *mybuf = NULL;

#ifdef	F_SETLKW
	aflock(cre8 ? F_WRLCK : F_RDLCK);
#endif
	SET_FILE_BINARY(ambfp);
	if (mybuf == NULL)
		mybuf = (char *)bmalloc(BUFSIZ+8);
	setbuf(ambfp, mybuf);
	if (cre8) {			/* new file */
		newheader("RADIANCE", ambfp);
		fprintf(ambfp, "%s -av %g %g %g -aw %d -ab %d -aa %g ",
				progname, colval(ambval,RED),
				colval(ambval,GRN), colval(ambval,BLU),
				ambvwt, ambounce, ambacc);
		fprintf(ambfp, "-ad %d -as %d -ar %d ",
				ambdiv, ambssamp, ambres);
		if (octname != NULL)
			fputs(octname, ambfp);
		fputc('\n', ambfp);
		fprintf(ambfp, "SOFTWARE= %s\n", VersionID);
		fputnow(ambfp);
		fputformat(AMBFMT, ambfp);
		fputc('\n', ambfp);
		putambmagic(ambfp);
	} else if (checkheader(ambfp, AMBFMT, NULL) < 0 || !hasambmagic(ambfp))
		error(USER, "bad ambient file");
}
Пример #29
0
/*
 * This automatically manages FBOs so that render targets are always given
 * an FBO that matches their width/height/format to maximize optimization
 */
static struct fbo_info *get_fbo(struct gs_device *device, texture_t tex)
{
	size_t i;
	uint32_t width, height;
	GLuint fbo;
	struct fbo_info *ptr;

	if (!get_tex_dimensions(tex, &width, &height))
		return NULL;

	for (i = 0; i < device->fbos.num; i++) {
		ptr = device->fbos.array[i];

		if (ptr->width  == width && ptr->height == height &&
		    ptr->format == tex->format)
			return ptr;
	}

	glGenFramebuffers(1, &fbo);
	if (!gl_success("glGenFramebuffers"))
		return NULL;

	ptr = bmalloc(sizeof(struct fbo_info));
	ptr->fbo                 = fbo;
	ptr->width               = width;
	ptr->height              = height;
	ptr->format              = tex->format;
	ptr->cur_render_target   = NULL;
	ptr->cur_render_side     = 0;
	ptr->cur_zstencil_buffer = NULL;

	da_push_back(device->fbos, &ptr);
	return ptr;
}
Пример #30
0
/*
 * Test the network write function with a timeout.  We fork off a child
 * process that runs delay_reader, and then we write 64KB to the network in
 * two chunks, once with a timeout and once without, and then try a third time
 * when we should time out.
 */
static void
test_network_write(void)
{
    socket_type fd, c;
    pid_t child;
    struct sockaddr_in sin;
    socklen_t slen;
    char *buffer;

    /* Create the data that we're going to send. */
    buffer = bmalloc(4096 * 1024);
    memset(buffer, 'a', 4096 * 1024);

    /* Create the listening socket. */
    fd = network_bind_ipv4(SOCK_STREAM, "127.0.0.1", 11119);
    if (fd == INVALID_SOCKET)
        sysbail("cannot create or bind socket");
    if (listen(fd, 1) < 0)
        sysbail("cannot listen to socket");

    /* Create the child, which will connect and then read data with delay. */
    child = fork();
    if (child < 0)
        sysbail("cannot fork");
    else if (child == 0) {
        socket_close(fd);
        client_delay_reader("127.0.0.1");
    }

    /* Set an alarm just in case our timeouts don't work. */
    alarm(10);

    /* Accept the client connection. */
    slen = sizeof(struct sockaddr_in);
    c = accept(fd, &sin, &slen);
    if (c == INVALID_SOCKET)
        sysbail("cannot accept on socket");

    /* Test some successful writes with and without a timeout. */
    socket_set_errno(0);
    ok(network_write(c, buffer, 32 * 1024, 0), "network_write");
    ok(network_write(c, buffer, 32 * 1024, 1),
       "network_write with timeout");

    /*
     * A longer write cannot be completely absorbed before the client sleep,
     * so should fail with a timeout.
     */
    ok(!network_write(c, buffer, 4096 * 1024, 1),
       "network_write aborted with timeout");
    is_int(ETIMEDOUT, socket_errno, "...with correct error");
    alarm(0);

    /* Clean up. */
    socket_close(c);
    kill(child, SIGTERM);
    waitpid(child, NULL, 0);
    socket_close(fd);
    free(buffer);
}