18 Commits

Author SHA1 Message Date
a8e2a9349e Exit with appropriate return code if password is not provided, fixes #87 2024-11-07 21:39:37 +02:00
deed43ad61 Makefile macOS fix, resolves #82, resolves #102
- Remove "ginstall" as "install" replacement on macOS
- Remove "-D" flag from "install" parameters
2024-11-07 17:14:25 +02:00
aa933d2c1f Add support for Valve style authentication, fixes #106 2024-11-07 14:59:31 +02:00
accae57e4b Remove ".travis.yml" 2024-11-07 14:21:31 +02:00
fa25cde79c Modify compilation flags:
- Remove "-s" flag
- Change stack protector mode from "strong" to "all"
- Change optimization level from "-Os" to "-O2"
2024-11-07 14:06:48 +02:00
e96b2eff6e Remove broken Travis CI links and update package list 2024-11-07 13:54:40 +02:00
b5951e9634 Merge pull request #83 from Tiiffi/develop
Merge develop to master
2021-10-30 22:34:42 +03:00
7b8ea2bf39 Update copyright year 2021-10-30 22:30:12 +03:00
05aaff88d4 Update version information, changelog and readme 2021-10-30 22:21:25 +03:00
fca278e092 - Quit gracefully when Ctrl-D or Ctrl-C is pressed
- Remove "exit" and "quit" as quit commands
2021-10-30 22:16:29 +03:00
b3147ebe43 Fix erroneous string length check 2021-02-15 04:31:07 +02:00
48c065c304 Use setvbuf() instead of fflush() 2021-02-15 03:29:44 +02:00
29a1c99f82 Merge pull request #53 from AddisonG/master
Fix compiler warning
2021-02-12 04:23:54 +02:00
bf11460a0d Merge pull request #39 from kabiroberai/master
Flush stdout when needed
2021-02-08 22:51:54 +02:00
3e8acd5e42 Merge pull request #62 from jbaldus/master
Fixes typo in ANSI escape sequence for LCYAN
2021-02-08 05:16:11 +02:00
ada14bb4d9 Fixes typo in ANSI escape sequence for LCYAN 2021-01-13 19:22:02 -05:00
336f528668 Fixed compiler bug
This fixes the compiler issue:

```
mcrcon.c: In function ‘packet_build’:
mcrcon.c:576:2: warning: ‘strncpy’ specified bound 4096 equals destination size [-Wstringop-truncation]
  strncpy(packet.data, s1, DATA_BUFFSIZE);
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
2020-08-12 14:10:58 +10:00
58a7a86bc3 Flush stdout when needed
This is required on certain machines (eg the iSH emulator on iOS)
2020-01-31 17:26:27 +05:30
8 changed files with 77 additions and 74 deletions

View File

@ -1,20 +0,0 @@
language: c
sudo: false
dist: trusty
cache:
ccache: true
compiler:
- gcc
- clang
env:
global:
- EXTRAFLAGS='-v'
- PREFIX="${HOME}"
install:
- 'true'
script:
- make
- ./mcrcon -h
- ./mcrcon -v
- make install
- make uninstall

View File

@ -1,5 +1,17 @@
#### Version history: #### Version history:
###### 0.7.3
- Add support to Valve style rcon authentication
###### 0.7.2
- Quit gracefully when Ctrl-D or Ctrl+C is pressed
- Remove "exit" and "quit" as quitting commands
* these are actual rcon commands on some servers
- Suppress compiler warning (strncpy)
- fix erroneous string length in packet building function
- Fix typo in ANSI escape sequence for LCYAN
- Make stdout and stderr unbuffered
###### 0.7.1 ###### 0.7.1
- Deprecate `-i` flag for invoking terminal mode - Deprecate `-i` flag for invoking terminal mode
- Add workaround to prevent server-side bug. - Add workaround to prevent server-side bug.

View File

@ -1,11 +1,11 @@
Building and installing Building and installing
------------------------ -----------------------
Only dependency is C library and POSIX getopt support. Only dependency is C library and POSIX getopt support.
Compiling with GCC or CLANG: Compiling with GCC or CLANG:
cc -std=gnu99 -Wpedantic -Wall -Wextra -Os -s -o mcrcon mcrcon.c cc -std=gnu99 -Wpedantic -Wall -Wextra -O2 -o mcrcon mcrcon.c
Note: on Windows remember to link with winsock by adding `-lws2_32` to your compiler command line. Note: on Windows remember to link with winsock by adding `-lws2_32` to your compiler command line.

View File

@ -1,4 +1,4 @@
Copyright (c) 2012-2020, Tiiffi <tiiffi at gmail> Copyright (c) 2012-2021, Tiiffi <tiiffi at gmail>
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -18,4 +18,3 @@ freely, subject to the following restrictions:
3. This notice may not be removed or altered from any source 3. This notice may not be removed or altered from any source
distribution. distribution.

View File

@ -4,7 +4,7 @@
# make # make
# #
# Windows cross compile: # Windows cross compile:
# i686-w64-mingw32-gcc -std=gnu99 -Wall -Wextra -Wpedantic -Os -s -o mcrcon.exe mcrcon.c -lws2_32 # x86_64-w64-mingw32-gcc -std=gnu99 -Wall -Wextra -Wpedantic -O2 -fstack-protector-all -o mcrcon.exe mcrcon.c -lws2_32
EXENAME = mcrcon EXENAME = mcrcon
PREFIX ?= /usr/local PREFIX ?= /usr/local
@ -14,8 +14,8 @@ LINKER =
RM = rm -v -f RM = rm -v -f
CC = gcc CC = gcc
CFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Os -s CFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -O2
EXTRAFLAGS ?= -fstack-protector-strong EXTRAFLAGS ?= -fstack-protector-all
ifeq ($(OS), Windows_NT) ifeq ($(OS), Windows_NT)
LINKER = -lws2_32 LINKER = -lws2_32
@ -23,11 +23,6 @@ ifeq ($(OS), Windows_NT)
RM = cmd /C del /F RM = cmd /C del /F
endif endif
ifeq ($(shell uname), Darwin)
INSTALL = ginstall
CFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Os
endif
.PHONY: all .PHONY: all
all: $(EXENAME) all: $(EXENAME)
@ -37,8 +32,8 @@ $(EXENAME): mcrcon.c
ifneq ($(OS), Windows_NT) ifneq ($(OS), Windows_NT)
.PHONY: install .PHONY: install
install: install:
$(INSTALL) -vD $(EXENAME) $(DESTDIR)$(PREFIX)/bin/$(EXENAME) $(INSTALL) -v $(EXENAME) $(DESTDIR)$(PREFIX)/bin/$(EXENAME)
$(INSTALL) -vD -m 0644 mcrcon.1 $(DESTDIR)$(PREFIX)/share/man/man1/mcrcon.1 $(INSTALL) -v -m 0644 mcrcon.1 $(DESTDIR)$(PREFIX)/share/man/man1/mcrcon.1
@echo "\nmcrcon installed. Run 'make uninstall' if you want to uninstall.\n" @echo "\nmcrcon installed. Run 'make uninstall' if you want to uninstall.\n"
.PHONY: uninstall .PHONY: uninstall

View File

@ -6,24 +6,30 @@ mcrcon is console based Minecraft [rcon](https://developer.valvesoftware.com/wik
### Installing: ### Installing:
##### via packet manager: ##### via package manager:
See https://pkgs.org/download/mcrcon for available packages in various Linux distros (note that available packages might be outdated). See https://pkgs.org/download/mcrcon and https://repology.org/project/mcrcon/packages for available packages in various Linux distros (note that some packages might be outdated).
- Gentoo Linux: https://packages.gentoo.org/packages/games-util/mcrcon - Fedora: https://packages.fedoraproject.org/pkgs/mcrcon/mcrcon/
- Arch Linux: https://aur.archlinux.org/packages/mcrcon/ - Gentoo: https://packages.gentoo.org/packages/games-util/mcrcon
- Arch: https://aur.archlinux.org/packages/mcrcon/
- NixOS: https://search.nixos.org/packages?show=mcrcon
- Snapcraft: https://snapcraft.io/mcrcon-nsg
- Scoop: https://scoop.sh/#/apps?q=mcrcon
##### building from sources: ##### building from sources:
```sh ```sh
git clone https://github.com/Tiiffi/mcrcon.git git clone https://github.com/Tiiffi/mcrcon.git
cd mcrcon cd mcrcon
make make
# install is optional
sudo make install sudo make install
``` ```
Check [INSTALL.md](INSTALL.md) for more details. Check [INSTALL.md](INSTALL.md) for more details.
Precompiled binaries (if provided)*: https://github.com/Tiiffi/mcrcon/releases/latest Precompiled binaries*: https://github.com/Tiiffi/mcrcon/releases/latest
<sub>*At the moment binaries are provided for Linux and Windows.</sub> <sub>*Binaries are provided for Linux and Windows.</sub>
--- ---
@ -76,8 +82,7 @@ rcon.password=your_rcon_pasword
##### Contact: ##### Contact:
* WWW: https://github.com/Tiiffi/mcrcon/ * WWW: https://github.com/Tiiffi/mcrcon/
* MAIL: tiiffi at gmail * MAIL: tiiffi+mcrcon at gmail
* IRC: tiiffi @ quakenet
* BUG REPORTS: https://github.com/Tiiffi/mcrcon/issues/ * BUG REPORTS: https://github.com/Tiiffi/mcrcon/issues/
--- ---
@ -87,6 +92,3 @@ rcon.password=your_rcon_pasword
This project is licensed under the zlib License - see the [LICENSE](LICENSE) file for details. This project is licensed under the zlib License - see the [LICENSE](LICENSE) file for details.
--- ---
<sub>Master:</sub> ![Master build](https://api.travis-ci.org/Tiiffi/mcrcon.svg?branch=master)
<sub>Develop:</sub> ![Develop build](https://api.travis-ci.org/Tiiffi/mcrcon.svg?branch=develop)

View File

@ -1,7 +1,7 @@
.\" Process this file with .\" Process this file with
.\" groff -man -Tascii mcrcon.1 .\" groff -man -Tascii mcrcon.1
.\" .\"
.TH MCRCON 1 "January 2020" "Version 0.7.1" .TH MCRCON 1 "November 2024" "Version 0.7.3"
.SH NAME .SH NAME
mcrcon \- send rcon commands to a Minecraft server mcrcon \- send rcon commands to a Minecraft server
.SH SYNOPSIS .SH SYNOPSIS

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012-2020, Tiiffi <tiiffi at gmail> * Copyright (c) 2012-2021, Tiiffi <tiiffi at gmail>
* *
* This software is provided 'as-is', without any express or implied * This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages * warranty. In no event will the authors be held liable for any damages
@ -24,8 +24,8 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <string.h> #include <string.h>
#include <strings.h>
#include <signal.h> #include <signal.h>
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
@ -47,7 +47,7 @@
#include <netdb.h> #include <netdb.h>
#endif #endif
#define VERSION "0.7.1" #define VERSION "0.7.3"
#define IN_NAME "mcrcon" #define IN_NAME "mcrcon"
#define VER_STR IN_NAME" "VERSION" (built: "__DATE__" "__TIME__")" #define VER_STR IN_NAME" "VERSION" (built: "__DATE__" "__TIME__")"
@ -123,8 +123,11 @@ void exit_proc(void)
} }
// Check windows & linux behaviour !!! // Check windows & linux behaviour !!!
void sighandler(/*int sig*/) void sighandler(int sig)
{ {
if (sig == SIGINT)
putchar('\n');
global_connection_alive = 0; global_connection_alive = 0;
#ifndef _WIN32 #ifndef _WIN32
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
@ -167,6 +170,10 @@ int main(int argc, char *argv[])
if (!port) port = "25575"; if (!port) port = "25575";
if (!host) host = "localhost"; if (!host) host = "localhost";
// disable output buffering (https://github.com/Tiiffi/mcrcon/pull/39)
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
if(argc < 1 && pass == NULL) usage(); if(argc < 1 && pass == NULL) usage();
// default getopt error handler enabled // default getopt error handler enabled
@ -202,7 +209,7 @@ int main(int argc, char *argv[])
if (pass == NULL) { if (pass == NULL) {
puts("You must give password (-p password).\nTry 'mcrcon -h' or 'man mcrcon' for help."); puts("You must give password (-p password).\nTry 'mcrcon -h' or 'man mcrcon' for help.");
return 0; exit(EXIT_FAILURE);
} }
if(optind == argc && terminal_mode == 0) if(optind == argc && terminal_mode == 0)
@ -238,10 +245,7 @@ int main(int argc, char *argv[])
exit_code = EXIT_FAILURE; exit_code = EXIT_FAILURE;
} }
net_close(global_rsock); exit(exit_code);
global_rsock = -1;
return exit_code;
} }
void usage(void) void usage(void)
@ -429,6 +433,7 @@ rc_packet *net_recv_packet(int sd)
return NULL; return NULL;
} }
// NOTE(Tiiffi): This should fail if size is out of spec!
if (psize < 10 || psize > DATA_BUFFSIZE) { if (psize < 10 || psize > DATA_BUFFSIZE) {
fprintf(stderr, "Warning: invalid packet size (%d). Must over 10 and less than %d.\n", psize, DATA_BUFFSIZE); fprintf(stderr, "Warning: invalid packet size (%d). Must over 10 and less than %d.\n", psize, DATA_BUFFSIZE);
@ -484,7 +489,7 @@ void print_color(int color)
"\033[0;1;30m", /* 08 DGREY 0x38 */ "\033[0;1;30m", /* 08 DGREY 0x38 */
"\033[0;1;34m", /* 09 LBLUE 0x39 */ "\033[0;1;34m", /* 09 LBLUE 0x39 */
"\033[0;1;32m", /* 10 LGREEN 0x61 */ "\033[0;1;32m", /* 10 LGREEN 0x61 */
"\033[0:1;36m", /* 11 LCYAN 0x62 */ "\033[0;1;36m", /* 11 LCYAN 0x62 */
"\033[0;1;31m", /* 12 LRED 0x63 */ "\033[0;1;31m", /* 12 LRED 0x63 */
"\033[0;1;35m", /* 13 LPURPLE 0x64 */ "\033[0;1;35m", /* 13 LPURPLE 0x64 */
"\033[0;1;33m", /* 14 YELLOW 0x65 */ "\033[0;1;33m", /* 14 YELLOW 0x65 */
@ -564,16 +569,16 @@ rc_packet *packet_build(int id, int cmd, char *s1)
static rc_packet packet = {0, 0, 0, { 0x00 }}; static rc_packet packet = {0, 0, 0, { 0x00 }};
// size + id + cmd + s1 + s2 NULL terminator // size + id + cmd + s1 + s2 NULL terminator
int s1_len = strlen(s1); int len = strlen(s1);
if (s1_len > DATA_BUFFSIZE) { if (len >= DATA_BUFFSIZE) {
fprintf(stderr, "Warning: Command string too long (%d). Maximum allowed: %d.\n", s1_len, DATA_BUFFSIZE); fprintf(stderr, "Warning: Command string too long (%d). Maximum allowed: %d.\n", len, DATA_BUFFSIZE - 1);
return NULL; return NULL;
} }
packet.size = sizeof(int) * 2 + s1_len + 2; packet.size = sizeof(int) * 2 + len + 2;
packet.id = id; packet.id = id;
packet.cmd = cmd; packet.cmd = cmd;
strncpy(packet.data, s1, DATA_BUFFSIZE); strncpy(packet.data, s1, DATA_BUFFSIZE - 1);
return &packet; return &packet;
} }
@ -590,10 +595,18 @@ int rcon_auth(int sock, char *passwd)
if (!ret) if (!ret)
return 0; // send failed return 0; // send failed
receive:
packet = net_recv_packet(sock); packet = net_recv_packet(sock);
if (packet == NULL) if (packet == NULL)
return 0; return 0;
/* Valve rcon sends empty "RCON_RESPONSEVALUE" packet before real auth response
* so we have to check packet type and try again if necessary.
*/
if (packet->cmd != RCON_AUTH_RESPONSE) {
goto receive;
}
// return 1 if authentication OK // return 1 if authentication OK
return packet->id == -1 ? 0 : 1; return packet->id == -1 ? 0 : 1;
} }
@ -650,19 +663,18 @@ int run_terminal_mode(int sock)
int ret = 0; int ret = 0;
char command[DATA_BUFFSIZE] = {0x00}; char command[DATA_BUFFSIZE] = {0x00};
puts("Logged in. Type 'quit' or 'exit' to quit."); puts("Logged in.\nType 'Q' or press Ctrl-D / Ctrl-C to disconnect.");
while (global_connection_alive) { while (global_connection_alive) {
putchar('>'); putchar('>');
int len = get_line(command, DATA_BUFFSIZE); int len = get_line(command, DATA_BUFFSIZE);
if (len < 1) continue;
if ((strcasecmp(command, "exit") && strcasecmp(command, "quit")) == 0) if (strcasecmp(command, "Q") == 0)
break; break;
if(command[0] == 'Q' && command[1] == 0) if (len > 0 && global_connection_alive)
break;
if(len > 0 && global_connection_alive)
ret += rcon_command(sock, command); ret += rcon_command(sock, command);
/* Special case for "stop" command to prevent server-side bug. /* Special case for "stop" command to prevent server-side bug.
@ -676,7 +688,7 @@ int run_terminal_mode(int sock)
break; break;
} }
command[0] = len = 0; //command[0] = len = 0;
} }
return ret; return ret;
@ -686,11 +698,14 @@ int run_terminal_mode(int sock)
int get_line(char *buffer, int bsize) int get_line(char *buffer, int bsize)
{ {
char *ret = fgets(buffer, bsize, stdin); char *ret = fgets(buffer, bsize, stdin);
if (ret == NULL) if (ret == NULL) {
exit(EXIT_FAILURE); if (ferror(stdin)) {
fprintf(stderr, "Error %d: %s\n", errno, strerror(errno));
if (buffer[0] == 0) exit(EXIT_FAILURE);
global_connection_alive = 0; }
putchar('\n');
exit(EXIT_SUCCESS);
}
// remove unwanted characters from the buffer // remove unwanted characters from the buffer
buffer[strcspn(buffer, "\r\n")] = '\0'; buffer[strcspn(buffer, "\r\n")] = '\0';