commit: faadcbaa492ca5d73d7a196affad47ab5cd9b46a
parent 3527ac7133512a5ad3f72564ef03de64b2355a38
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Sat, 1 Jun 2024 07:07:53 +0200
Add support for -o and -v
Diffstat:
M | httpc.c | 69 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ |
1 file changed, 63 insertions(+), 6 deletions(-)
diff --git a/httpc.c b/httpc.c
@@ -4,12 +4,16 @@
#include <limits.h> // PAGESIZE
#include <tls.h>
+#include <errno.h>
#include <stdio.h> // fprintf
-#include <unistd.h> // write
-#include <string.h> // strlen
+#include <unistd.h> // write, fsync
+#include <string.h> // strlen, strerror
#include <stdlib.h> // abort
+#include <stdbool.h>
+#include <fcntl.h> // open, O_*
int body = 0;
+bool verbose = false;
static size_t
read_header(const char *res, ssize_t len)
@@ -28,8 +32,12 @@ read_header(const char *res, ssize_t len)
return i+1;
}
- fwrite(res, 1, header_len, stderr);
- fputs("\n", stderr);
+ if(verbose)
+ {
+ fputs("> ", stderr);
+ fwrite(res, 1, header_len, stderr);
+ fputs("\n", stderr);
+ }
return i+1;
}
@@ -45,6 +53,37 @@ read_header(const char *res, ssize_t len)
int
main(int argc, char *argv[])
{
+ int out_flags = O_WRONLY | O_CLOEXEC | O_CREAT | O_NOCTTY | O_TRUNC;
+ char *out_name = NULL;
+ int out = -1;
+
+ int c = -1;
+ while((c = getopt(argc, argv, ":o:v")) != -1)
+ {
+ switch(c)
+ {
+ case 'o':
+ out_name = optarg;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ }
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ // FIXME: URL basename
+ if(out_name == NULL) out_name = "body";
+
+ out = open(out_name, out_flags, 0644);
+ if(out < 0)
+ {
+ fprintf(stderr, "httpc: Failed opening destination file '%s': %s\n", out_name, strerror(errno));
+ return 1;
+ }
+
const char *hostname = "lanodan.eu";
const char *target = "/";
const char *port = "443";
@@ -66,9 +105,12 @@ main(int argc, char *argv[])
return 1;
}
+ int err = 0;
+
if(tls_handshake(tls_ctx) != 0)
{
fprintf(stderr, "httpc: TLS Handshake Error: %s\n", tls_error(tls_ctx));
+ err = 1;
goto cleanup;
}
@@ -82,10 +124,13 @@ Connection: close\r\n\
snprintf(req, PAGESIZE, req_fmt, target, hostname);
+ if(verbose) write(STDERR_FILENO, req, strlen(req));
+
ssize_t nwrite = tls_write(tls_ctx, req, strlen(req));
if(nwrite < 0)
{
fprintf(stderr, "httpc: Write Error: %s\n", tls_error(tls_ctx));
+ err = 1;
goto cleanup;
}
@@ -110,7 +155,19 @@ Connection: close\r\n\
// TODO: Read status
while(body == 0 && off < nread) off += read_header(res+off, nread);
- if(body == 1) write(STDOUT_FILENO, res+off, nread-off);
+ if(body == 1) write(out, res+off, nread-off);
+ }
+
+ if(fsync(out) < 0)
+ {
+ fprintf(stderr, "httpc: Failed syncing destination file '%s' to disk: %s\n", out_name, strerror(errno));
+ err = 1;
+ }
+
+ if(close(out) < 0)
+ {
+ fprintf(stderr, "httpc: Failed closing destination file '%s': %s\n", out_name, strerror(errno));
+ err = 1;
}
cleanup:
@@ -118,5 +175,5 @@ cleanup:
tls_free(tls_ctx);
tls_config_free(tls_cfg);
- return 0;
+ return err;
}