source: Main/trunk/Server/main.c@ 213

Last change on this file since 213 was 213, checked in by Nishi, on Oct 3, 2024 at 2:45:40 AM

format the code

  • Property svn:keywords set to Id
File size: 18.5 KB
RevLine 
[2]1/* $Id: main.c 213 2024-10-02 17:45:40Z nishi $ */
2
[16]3#define SOURCE
4
[43]5#include "../config.h"
6
[212]7#ifndef _MSC_VER
[189]8#include <unistd.h>
[212]9#endif
[3]10#include <stdio.h>
11#include <stdbool.h>
12#include <string.h>
[16]13#include <signal.h>
[116]14#include <stdlib.h>
[3]15
[43]16#ifndef NO_SSL
[6]17#include <openssl/opensslv.h>
[43]18#endif
[6]19
[3]20#include <cm_log.h>
[62]21#include <cm_string.h>
[3]22
[4]23#include "tw_config.h"
[8]24#include "tw_server.h"
[3]25#include "tw_version.h"
26
[212]27#if defined(__MINGW32__) || defined(_MSC_VER)
[51]28#include <windows.h>
29#endif
30
[182]31#ifdef _PSP
32#include <pspkernel.h>
33#include <pspdebug.h>
[183]34#include <pspsdk.h>
35#include <psputility.h>
36#include <pspctrl.h>
37#include <pspnet_apctl.h>
38#include <pspwlan.h>
[182]39
40PSP_MODULE_INFO("Tewi HTTPd", PSP_MODULE_USER, 1, 1);
41PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER);
42
43#define printf(...) pspDebugScreenPrintf(__VA_ARGS__)
[183]44#define STDERR_LOG(...) pspDebugScreenPrintf(__VA_ARGS__)
[189]45#elif defined(__ps2sdk__)
46#include <debug.h>
[200]47#include <iopcontrol.h>
[189]48#include <sifrpc.h>
[200]49#include <kernel.h>
[189]50
51#define printf(...) scr_printf(__VA_ARGS__)
52#define STDERR_LOG(...) scr_printf(__VA_ARGS__)
[191]53#elif defined(__PPU__)
54#include <rsx/gcm_sys.h>
55#include <rsx/rsx.h>
56#include <sysutil/video.h>
57#include <malloc.h>
58#include <sys/thread.h>
59#include <stdarg.h>
[197]60#include <png.h>
[191]61
62#define printf(...) tt_printf(__VA_ARGS__)
63#define STDERR_LOG(...) tt_printf(__VA_ARGS__)
[212]64#elif defined(_MSC_VER)
[213]65void STDERR_LOG(const char* format, ...) {
[212]66 va_list args;
67 va_start(args, format);
68 vfprintf(stderr, format, args);
69 va_end(args);
70}
[183]71#else
72#define STDERR_LOG(...) fprintf(stderr, __VA_ARGS__)
[182]73#endif
74
[3]75extern bool cm_do_log;
[18]76extern struct tw_config config;
[62]77extern FILE* logfile;
[3]78
[18]79char tw_server[2048];
80
[62]81int startup(int argc, char** argv);
82
[212]83#if defined(__MINGW32__) || defined(_MSC_VER)
[206]84char* get_registry(const char* main, const char* sub) {
[208]85 DWORD bufsize = 512;
86 HKEY handle;
87 char* value = malloc(513);
88 int err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, main, 0, KEY_QUERY_VALUE, &handle);
[206]89 if(err == ERROR_SUCCESS) {
[208]90 err = RegQueryValueEx(handle, sub, NULL, NULL, value, &bufsize);
91 if(err != ERROR_SUCCESS) {
92 free(value);
93 RegCloseKey(handle);
94 return NULL;
95 }
96 RegCloseKey(handle);
[206]97 return value;
98 } else {
99 free(value);
100 return NULL;
101 }
102}
103#endif
104
[62]105#ifdef SERVICE
106SERVICE_STATUS status;
107SERVICE_STATUS_HANDLE status_handle;
108
[70]109void WINAPI servhandler(DWORD control) {
110 switch(control) {
111 case SERVICE_CONTROL_STOP:
112 case SERVICE_CONTROL_SHUTDOWN:
113 status.dwCurrentState = SERVICE_STOP_PENDING;
114 break;
[62]115 }
116 SetServiceStatus(status_handle, &status);
117}
118
[70]119void WINAPI servmain(DWORD argc, LPSTR* argv) {
[206]120 char* path = get_registry("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Tewi HTTPd", "InstallDir");
121 if(path != NULL) {
122 char* lpath = cm_strcat(path, "/logs/tewi.log");
123 logfile = fopen(lpath, "a");
124 free(lpath);
125 free(path);
126 } else {
127 logfile = fopen(PREFIX "/logs/tewi.log", "a");
128 }
[62]129 if(logfile == NULL) logfile = stderr;
130 status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
131 status.dwCurrentState = SERVICE_START_PENDING;
132 status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
133 status.dwWin32ExitCode = NO_ERROR;
134 status.dwServiceSpecificExitCode = 0;
135 status.dwCheckPoint = 0;
136 status.dwWaitHint = 0;
137 status_handle = RegisterServiceCtrlHandler("Tewi HTTPd", servhandler);
138 if(status_handle == NULL) return;
139 if(SetServiceStatus(status_handle, &status) == 0) return;
140 int st = startup(argc, argv);
[70]141 if(st != -1) {
[62]142 status.dwWin32ExitCode = NO_ERROR;
143 status.dwServiceSpecificExitCode = st;
144 status.dwCurrentState = SERVICE_STOPPED;
145 SetServiceStatus(status_handle, &status);
146 return;
147 }
148 status.dwCurrentState = SERVICE_RUNNING;
149 SetServiceStatus(status_handle, &status);
150 tw_server_loop();
151 status.dwCurrentState = SERVICE_STOPPED;
152 SetServiceStatus(status_handle, &status);
153}
154#endif
155
[183]156int running = 1;
157#ifdef _PSP
158
159int psp_exit_callback(int arg1, int arg2, void* arg3) { running = 0; }
160
161int psp_callback_thread(SceSize args, void* argp) {
162 int cid;
163 cid = sceKernelCreateCallback("Exit Call Back", psp_exit_callback, NULL);
164 sceKernelRegisterExitCallback(cid);
165 sceKernelSleepThreadCB();
166 return 0;
167}
168#endif
169
[191]170#ifdef __PPU__
171uint32_t depth_pitch;
172uint32_t depth_offset;
173uint32_t* depth_buffer;
174
175#define CB_SIZE 0x100000
176#define HOST_SIZE (32 * 1024 * 1024)
177
178struct rsx_buffer {
179 int width, height, id;
180 uint32_t* ptr;
181 uint32_t offset;
182};
183
184void wait_rsx(gcmContextData* ctx, uint32_t label) {
185 rsxSetWriteBackendLabel(ctx, GCM_INDEX_TYPE_32B, label);
186
187 rsxFlushBuffer(ctx);
188
189 while(*(uint32_t*)gcmGetLabelAddress(GCM_INDEX_TYPE_32B) != label) usleep(50);
190
191 label++;
192}
193
194void wait_rsx_until_idle(gcmContextData* ctx) {
195 uint32_t label = 1;
196 rsxSetWriteBackendLabel(ctx, GCM_INDEX_TYPE_32B, label);
197 rsxSetWaitLabel(ctx, GCM_INDEX_TYPE_32B, label);
198 label++;
199 wait_rsx(ctx, label);
200}
201
202void get_resolution(int* width, int* height) {
203 videoState state;
204 videoResolution res;
205 if(videoGetState(0, 0, &state) != 0) {
206 return;
207 }
208
209 if(state.state != 0) {
210 return;
211 }
212
213 if(videoGetResolution(state.displayMode.resolution, &res) != 0) {
214 return;
215 }
216 *width = res.width;
217 *height = res.height;
218}
219
220void make_buffer(struct rsx_buffer* buffer, int id) {
221 int w, h;
222 get_resolution(&w, &h);
223
224 buffer->ptr = (uint32_t*)rsxMemalign(64, 4 * w * h);
225 if(buffer->ptr == NULL) return;
226
227 if(rsxAddressToOffset(buffer->ptr, &buffer->offset) != 0) return;
228
229 if(gcmSetDisplayBuffer(id, buffer->offset, 4 * w, w, h) != 0) return;
230 buffer->width = w;
231 buffer->height = h;
232 buffer->id = id;
233}
234
235gcmContextData* init_screen(void) {
236 void* host = memalign(1024 * 1024, HOST_SIZE);
237 gcmContextData* ctx = NULL;
238 videoState state;
239 videoConfiguration vconfig;
240 videoResolution res;
241 rsxInit(&ctx, CB_SIZE, HOST_SIZE, host);
242 if(ctx == NULL) {
243 free(host);
244 return NULL;
245 }
246
247 if(videoGetState(0, 0, &state) != 0) {
248 rsxFinish(ctx, 0);
249 free(host);
250 return NULL;
251 }
252
253 if(state.state != 0) {
254 rsxFinish(ctx, 0);
255 free(host);
256 return NULL;
257 }
258
259 if(videoGetResolution(state.displayMode.resolution, &res) != 0) {
260 rsxFinish(ctx, 0);
261 free(host);
262 return NULL;
263 }
264
265 memset(&vconfig, 0, sizeof(vconfig));
266 vconfig.resolution = state.displayMode.resolution;
267 vconfig.format = VIDEO_BUFFER_FORMAT_XRGB;
268 vconfig.pitch = res.width * 4;
269 vconfig.aspect = state.displayMode.aspect;
270
271 wait_rsx_until_idle(ctx);
272
273 if(videoConfigure(0, &vconfig, NULL, 0) != 0) {
274 rsxFinish(ctx, 0);
275 free(host);
276 return NULL;
277 }
278
279 if(videoGetState(0, 0, &state) != 0) {
280 rsxFinish(ctx, 0);
281 free(host);
282 return NULL;
283 }
284 gcmSetFlipMode(GCM_FLIP_VSYNC);
285
286 depth_pitch = res.width * 4;
287 depth_buffer = (uint32_t*)rsxMemalign(64, (res.height * depth_pitch) * 2);
288 rsxAddressToOffset(depth_buffer, &depth_offset);
289
290 gcmResetFlipStatus();
291
292 return ctx;
293}
294
295void set_render_target(gcmContextData* context, struct rsx_buffer* buffer) {
296 gcmSurface sf;
297
298 sf.colorFormat = GCM_SURFACE_X8R8G8B8;
299 sf.colorTarget = GCM_SURFACE_TARGET_0;
300 sf.colorLocation[0] = GCM_LOCATION_RSX;
301 sf.colorOffset[0] = buffer->offset;
302 sf.colorPitch[0] = depth_pitch;
303
304 sf.colorLocation[1] = GCM_LOCATION_RSX;
305 sf.colorLocation[2] = GCM_LOCATION_RSX;
306 sf.colorLocation[3] = GCM_LOCATION_RSX;
307 sf.colorOffset[1] = 0;
308 sf.colorOffset[2] = 0;
309 sf.colorOffset[3] = 0;
310 sf.colorPitch[1] = 64;
311 sf.colorPitch[2] = 64;
312 sf.colorPitch[3] = 64;
313
314 sf.depthFormat = GCM_SURFACE_ZETA_Z16;
315 sf.depthLocation = GCM_LOCATION_RSX;
316 sf.depthOffset = depth_offset;
317 sf.depthPitch = depth_pitch;
318
319 sf.type = GCM_TEXTURE_LINEAR;
320 sf.antiAlias = GCM_SURFACE_CENTER_1;
321
322 sf.width = buffer->width;
323 sf.height = buffer->height;
324 sf.x = 0;
325 sf.y = 0;
326
327 rsxSetSurface(context, &sf);
328}
329
330void wait_flip(void) {
331 while(gcmGetFlipStatus() != 0) usleep(200);
332 gcmResetFlipStatus();
333}
334
335void flip(gcmContextData* ctx, uint32_t buffer) {
336 if(gcmSetFlip(ctx, buffer) == 0) {
337 rsxFlushBuffer(ctx);
338 gcmSetWaitFlip(ctx);
339 }
340}
341
342uint8_t* tvram;
343
344extern uint8_t font[];
345
346int tt_x = 0;
347int tt_y = 0;
348int tt_width;
349int tt_height;
350
351void tt_putstr(const char* str) {
352 int i;
[193]353 for(i = 0; str[i] != 0; i++) {
[191]354 tvram[tt_y * tt_width + tt_x] = str[i];
[193]355 if(str[i] == '\n') {
[191]356 tt_x = 0;
357 tt_y++;
[193]358 } else {
[191]359 tt_x++;
[193]360 if(tt_x == tt_width) {
[191]361 tt_x = 0;
362 tt_y++;
363 }
364 }
[193]365 if(tt_y == tt_height) {
[191]366 tt_y--;
367 int x, y;
[193]368 for(y = 0; y < tt_height - 1; y++) {
369 for(x = 0; x < tt_width; x++) {
[191]370 tvram[y * tt_width + x] = tvram[(y + 1) * tt_width + x];
371 }
372 }
[193]373 for(x = 0; x < tt_width; x++) {
[197]374 tvram[(tt_height - 1) * tt_width + x] = 0x20;
[191]375 }
376 }
377 }
378}
379
[193]380void tt_putchar(struct rsx_buffer* buffer, int x, int y, uint8_t c) {
[191]381 int i, j;
[197]382 if(c == 0) return;
[191]383 if(c < 0x20) c = 0x20;
384 if(c >= 0x7f) c = 0x20;
[197]385 for(i = 0; i < 8; i++) {
386 uint8_t l = i == 7 ? 0 : font[(c - 0x20) * 8 + i];
387 for(j = 0; j < 6; j++) {
388 uint32_t col = 0;
[193]389 if(l & (1 << 7)) {
[197]390 col = 0xffffff;
[191]391 }
392 l = l << 1;
[197]393 buffer->ptr[(y * 8 + i) * buffer->width + x * 6 + j] = col;
[191]394 }
395 }
396}
397
398void draw(struct rsx_buffer* buffer, int current) {
399 int i, j, c;
400 for(i = 0; i < buffer->height / 8; i++) {
401 for(j = 0; j < buffer->width / 6; j++) {
402 uint8_t c = tvram[i * (buffer->width / 6) + j];
403 tt_putchar(buffer, j, i, c);
404 }
405 }
406}
407
[197]408#define BUFFERS 1
[191]409gcmContextData* ctx;
410struct rsx_buffer buffers[BUFFERS];
411
412void text_thread(void* arg) {
413 int current = 0;
414 while(1) {
415 wait_flip();
416 draw(&buffers[current], current);
417 flip(ctx, buffers[current].id);
418 current++;
419 if(current >= BUFFERS) current = 0;
420 }
421}
422
423void tt_printf(const char* tmpl, ...) {
424 va_list va;
425 va_start(va, tmpl);
426 int i;
427 char cbuf[2];
428 cbuf[1] = 0;
429 char* log = cm_strdup("");
430 for(i = 0; tmpl[i] != 0; i++) {
431 if(tmpl[i] == '%') {
432 i++;
[193]433 if(tmpl[i] == 's') {
[191]434 char* tmp = log;
435 log = cm_strcat(tmp, va_arg(va, char*));
436 free(tmp);
[193]437 } else if(tmpl[i] == 'd') {
[191]438 char buf[513];
439 sprintf(buf, "%d", va_arg(va, int));
440 char* tmp = log;
441 log = cm_strcat(tmp, buf);
442 free(tmp);
[193]443 } else if(tmpl[i] == '%') {
[191]444 char* tmp = log;
445 log = cm_strcat(tmp, "%");
446 free(tmp);
447 }
448 } else {
449 cbuf[0] = tmpl[i];
450 char* tmp = log;
451 log = cm_strcat(tmp, cbuf);
452 free(tmp);
453 }
454 }
455 va_end(va);
456 tt_putstr(log);
457}
458
[197]459void show_png(void) {
460 FILE* f = fopen(PREFIX "/pbtewi.png", "rb");
461 if(f == NULL) {
462 f = fopen(PREFIX "/../ICON0.PNG", "rb");
463 }
464 if(f == NULL) return;
465 png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
466 png_infop info = png_create_info_struct(png);
467 if(setjmp(png_jmpbuf(png))) {
468 png_destroy_read_struct(&png, &info, NULL);
469 fclose(f);
470 return;
471 }
472
473 png_init_io(png, f);
474 png_read_info(png, info);
475
476 int width = png_get_image_width(png, info);
477 int height = png_get_image_height(png, info);
478 int depth = png_get_bit_depth(png, info);
479 int type = png_get_color_type(png, info);
480
481 if(depth == 16) png_set_strip_16(png);
482 if(type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png);
483 if(type == PNG_COLOR_TYPE_GRAY && depth < 8) png_set_expand_gray_1_2_4_to_8(png);
484 if(png_get_valid(png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png);
485 if(type == PNG_COLOR_TYPE_RGB || type == PNG_COLOR_TYPE_GRAY || type == PNG_COLOR_TYPE_PALETTE) png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
486 if(type == PNG_COLOR_TYPE_GRAY || type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png);
487 png_read_update_info(png, info);
488 png_bytep* rows = (png_bytep*)malloc(sizeof(*rows) * (height));
489
490 int i;
491
492 for(i = 0; i < height; i++) {
493 rows[i] = (png_byte*)malloc(png_get_rowbytes(png, info));
494 }
495
496 png_read_image(png, rows);
497
498 for(i = 0; i < height; i++) {
499 int j;
500 for(j = 0; j < width; j++) {
501 png_bytep byte = &(rows[i][j * 4]);
502 uint32_t col = (byte[0] << 16) | (byte[1] << 8) | (byte[2]);
503 int k;
504 for(k = 0; k < BUFFERS; k++) {
505 buffers[k].ptr[buffers[k].width * i - width + j] = col;
506 }
507 }
508 }
509
510 png_destroy_read_struct(&png, &info, NULL);
511 fclose(f);
512
513 for(i = 0; i < height; i++) {
514 free(rows[i]);
515 }
516 free(rows);
517}
518
[191]519#endif
520
[3]521int main(int argc, char** argv) {
[212]522 int st;
[62]523 logfile = stderr;
524#ifdef SERVICE
525 SERVICE_TABLE_ENTRY table[] = {{"Tewi HTTPd", servmain}, {NULL, NULL}};
526 StartServiceCtrlDispatcher(table);
527#else
[182]528#ifdef _PSP
529 pspDebugScreenInit();
530 pspDebugScreenSetXY(0, 0);
[183]531 printf("PSP Bootstrap, Tewi/%s\n", tw_get_version());
532 int thid = sceKernelCreateThread("update_thread", psp_callback_thread, 0x11, 0xfa0, 0, NULL);
533 if(thid >= 0) {
534 sceKernelStartThread(thid, 0, NULL);
535 } else {
536 printf("Failed to start thread\n");
537 while(running) sceKernelDelayThread(50 * 1000);
538 sceKernelExitGame();
539 }
540 sceCtrlSetSamplingCycle(0);
541 sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
542 sceUtilityLoadNetModule(PSP_NET_MODULE_COMMON);
543 sceUtilityLoadNetModule(PSP_NET_MODULE_INET);
544 if(pspSdkInetInit()) {
545 printf("Could not init the network\n");
546 while(running) sceKernelDelayThread(50 * 1000);
547 sceKernelExitGame();
548 } else {
549 printf("Network initialization successful\n");
550 }
551 if(sceWlanGetSwitchState() != 1) {
552 printf("Turn the Wi-Fi switch on\n");
553 while(sceWlanGetSwitchState() != 1) {
554 sceKernelDelayThread(1000 * 1000);
555 }
556 } else {
557 printf("Wi-Fi is turned on\n");
558 }
559 int i;
560 int choice[100];
561 int incr = 0;
562 int last = 0;
563 int cur = 0;
564 for(i = 1; i < 100; i++) {
565 choice[i - 1] = 0;
566 netData name;
567 netData data;
568 if(sceUtilityCheckNetParam(i) != 0) continue;
569 choice[incr++] = i;
570 pspDebugScreenSetXY(0, 1 + 3 + incr - 1);
571 if(incr == 1) printf("> ");
572 pspDebugScreenSetXY(2, 1 + 3 + incr - 1);
573 sceUtilityGetNetParam(i, 0, &name);
574 sceUtilityGetNetParam(i, 1, &data);
575 printf("SSID=%s", data.asString);
576 sceUtilityGetNetParam(i, 4, &data);
577 if(data.asString[0]) {
578 sceUtilityGetNetParam(i, 5, &data);
579 printf(" IPADDR=%s\n", data.asString);
580 } else {
581 printf(" DHCP\n");
582 }
583 }
584 int press = 0;
585 while(1) {
586 if(!running) {
587 sceKernelExitGame();
588 }
589 SceCtrlData c;
590 sceCtrlReadBufferPositive(&c, 1);
591 press = 0;
592 if(c.Buttons & PSP_CTRL_DOWN) {
593 if(cur < incr - 1) {
594 cur++;
595 }
596 press = 1;
597 } else if(c.Buttons & PSP_CTRL_UP) {
598 if(cur > 0) {
599 cur--;
600 }
601 press = -1;
602 } else if(c.Buttons & PSP_CTRL_START) {
603 break;
604 }
605 if(last != cur) {
606 pspDebugScreenSetXY(0, 1 + 3 + last);
607 printf(" ");
608 pspDebugScreenSetXY(0, 1 + 3 + cur);
609 printf("> ");
610 last = cur;
611 }
612 if(press != 0) {
613 while(1) {
614 SceCtrlData c;
615 sceCtrlReadBufferPositive(&c, 1);
616 if(press == 1) {
617 if(!(c.Buttons & PSP_CTRL_DOWN)) break;
618 } else if(press == -1) {
619 if(!(c.Buttons & PSP_CTRL_UP)) break;
620 }
621 }
622 }
623 }
624 pspDebugScreenSetXY(0, 1 + 3 + incr + 1);
625 int err = sceNetApctlConnect(choice[cur]);
626 if(err != 0) {
627 printf("Apctl initialization failure\n");
628 while(running) sceKernelDelayThread(50 * 1000);
629 sceKernelExitGame();
630 } else {
631 printf("Apctl initialization successful\n");
632 }
633 printf("Apctl connecting\n");
634 while(1) {
635 int state;
636 err = sceNetApctlGetState(&state);
637 if(err != 0) {
638 printf("Apctl getting status failure\n");
639 while(running) sceKernelDelayThread(50 * 1000);
640 sceKernelExitGame();
641 }
642 if(state == 4) {
643 break;
644 }
645 sceKernelDelayThread(50 * 1000);
646 }
647 union SceNetApctlInfo info;
648 if(sceNetApctlGetInfo(8, &info) != 0) {
649 printf("Got an unknown IP\n");
650 while(running) sceKernelDelayThread(50 * 1000);
651 sceKernelExitGame();
652 }
653 printf("Connected, My IP is %s\n", info.ip);
[187]654#elif defined(__PPU__)
[191]655 int i;
656 ctx = init_screen();
657 int w, h;
658 get_resolution(&w, &h);
659 tt_width = w / 6;
660 tt_height = h / 8;
661 tvram = malloc((w / 6) * (h / 8));
662 for(i = 0; i < BUFFERS; i++) make_buffer(&buffers[i], i);
663 flip(ctx, BUFFERS - 1);
664 sys_ppu_thread_t id;
665 sysThreadCreate(&id, text_thread, NULL, 1500, 0x1000, THREAD_JOINABLE, "TextThread");
[187]666 printf("PS3 Bootstrap, Tewi/%s\n", tw_get_version());
[197]667 show_png();
[187]668 netInitialize();
[189]669#elif defined(__ps2sdk__)
670 SifInitRpc(0);
[200]671 while(!SifIopReset("", 0))
672 ;
673 while(!SifIopSync())
674 ;
[189]675 init_scr();
676 scr_printf("PS2 Bootstrap, Tewi/%s\n", tw_get_version());
[200]677 SleepThread();
[182]678#endif
[212]679 st = startup(argc, argv);
[183]680 if(st != -1) {
681#ifdef _PSP
682 printf("Error code %d\n", st);
683 while(running) sceKernelDelayThread(50 * 1000);
684 sceKernelExitGame();
685#else
[191]686#ifdef __PPU__
687 printf("Error code %d\n", st);
688 while(1)
689 ;
690#endif
[183]691 return st;
692#endif
693 }
[62]694 tw_server_loop();
695#endif
[183]696#ifdef _PSP
697 sceKernelExitGame();
698#endif
[168]699 return 0;
[62]700}
701
[70]702int startup(int argc, char** argv) {
[3]703 int i;
[212]704 char* r;
705#if defined(__MINGW32__) || defined(_MSC_VER)
[206]706 char* confpath = cm_strdup(PREFIX "/etc/tewi.conf");
707 char* regpath = get_registry("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Tewi HTTPd", "InstallDir");
708 if(regpath != NULL) {
709 free(confpath);
710 confpath = cm_strcat(regpath, "/etc/tewi.conf");
711 free(regpath);
712 }
713#else
[18]714 const char* confpath = PREFIX "/etc/tewi.conf";
[206]715#endif
[70]716 if(argv != NULL) {
[62]717 for(i = 1; i < argc; i++) {
718 if(argv[i][0] == '-') {
719 if(strcmp(argv[i], "--verbose") == 0 || strcmp(argv[i], "-v") == 0) {
720 if(!cm_do_log) {
721 cm_do_log = true;
[70]722#ifndef NO_SSL
[62]723 cm_log("", "This is Tewi HTTPd, version %s, using %s", tw_get_version(), OPENSSL_VERSION_TEXT);
[70]724#else
[62]725 cm_log("", "This is Tewi HTTPd, version %s", tw_get_version());
[70]726#endif
[62]727 } else {
728 cm_do_log = true;
729 }
730 } else if(strcmp(argv[i], "--config") == 0 || strcmp(argv[i], "-C") == 0) {
731 i++;
732 if(argv[i] == NULL) {
[183]733 STDERR_LOG("Missing argument\n");
[62]734 return 1;
735 }
736 confpath = argv[i];
[182]737#ifndef _PSP
[117]738 } else if(strcmp(argv[i], "--logfile") == 0 || strcmp(argv[i], "-l") == 0) {
739 i++;
740 if(argv[i] == NULL) {
[183]741 STDERR_LOG("Missing argument\n");
[117]742 return 1;
743 }
744 if(logfile != NULL && logfile != stderr) {
745 fclose(logfile);
746 }
747 logfile = fopen(argv[i], "a");
748 if(logfile == NULL) {
[183]749 STDERR_LOG("Failed to open logfile\n");
[117]750 return 1;
751 }
[182]752#endif
[62]753 } else if(strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "-V") == 0) {
754 printf("Tewi HTTPd Tewi/%s\n", tw_get_version());
755 printf("Under public domain.\n");
756 printf("Original by 2024 Nishi\n");
757 printf("\n");
758 printf("Usage: %s [--config|-C config] [--verbose|-v] [--version|-V]\n", argv[0]);
[119]759 printf("--config | -C config : Specify config\n");
[182]760#ifndef _PSP
[119]761 printf("--logfile | -l logfile : Specify logfile\n");
[182]762#endif
[119]763 printf("--verbose | -v : Verbose mode\n");
764 printf("--version | -V : Version information\n");
[62]765 return 0;
[3]766 } else {
[183]767 STDERR_LOG("Unknown option: %s\n", argv[i]);
[4]768 return 1;
769 }
[3]770 }
771 }
772 }
[6]773 tw_config_init();
[18]774 if(tw_config_read(confpath) != 0) {
[183]775 STDERR_LOG("Could not read the config\n");
[4]776 return 1;
777 }
[8]778 if(tw_server_init() != 0) {
[183]779 STDERR_LOG("Could not initialize the server\n");
[8]780 return 1;
781 }
[18]782 sprintf(tw_server, "Tewi/%s (%s)%s", tw_get_version(), tw_get_platform(), config.extension == NULL ? "" : config.extension);
[212]783 r = cm_strcat(tw_server, " running...");
[62]784 cm_force_log(r);
785 free(r);
[212]786#if !defined(__MINGW32__) && !defined(_MSC_VER)
[16]787 signal(SIGCHLD, SIG_IGN);
[90]788 signal(SIGPIPE, SIG_IGN);
[50]789#else
790 SetConsoleTitle(tw_server);
[16]791#endif
[62]792 return -1;
[3]793}
Note: See TracBrowser for help on using the repository browser.