diff --git a/.github/workflows/robuild.yaml b/.github/workflows/robuild.yaml new file mode 100644 index 0000000..de42bf4 --- /dev/null +++ b/.github/workflows/robuild.yaml @@ -0,0 +1,118 @@ +--- +# RISC OS CI build through build.riscos.online +# +# To reuse this configuration with your own repository: +# +# - Create a .robuild.yaml to describe what should be built on RISC OS. +# - `jobs.build.script` should be a list of commands to run on RISC OS +# - `jobs.build.artifacts.path` should be the directory to zip. +# - Create a VersionNum file if you wish to use the automated versioning +# in the same style as the RISC OS sources. [optional] +# - Update the 3rd step ('give the archive a versioned name') to give a +# suitable name for the archive. +# - Update the 4th step ('upload-artifacts') to include the same names. +# +# The 'release' job is triggered when a tag starting with a 'v' is created, +# which will create a GitHub release for the repository with the name of the +# version tag. The release will be a draft, and should be updated with +# changes as you see fit. +# + +name: RISC OS + +# Controls when the action will run. Triggers the workflow on: +# * push on any branch. +# * tag creation for tags beginning with a 'v' +on: + push: + tags: ["v*"] + # Pull request events happen on pull request state transitions, and also when the PR is created. + pull_request: + branches: ["*"] + +jobs: + build-riscos: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + outputs: + version: ${{ steps.version.outputs.version }} + leafname: ${{ steps.version.outputs.leafname }} + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + + - name: Obtain prerequisite build tool + run: | + # Fetch the build client + curl -s -L -o riscos-build-online https://github.com/gerph/robuild-client/releases/download/v0.05/riscos-build-online && chmod +x riscos-build-online + + - name: Build through build.riscos.online + run: | + # Zip up the source to send to robuild + zip -q9r /tmp/source-archive.zip * .robuild.yaml + # Send the archive file to build service (timeout of 60 seconds) + ./riscos-build-online -i /tmp/source-archive.zip -a off -t 60 -o /tmp/built + + - name: Give the output a versioned name + id: version + run: | + if [[ -f src/VersionNum ]] ; then + version=$(sed '/MajorVersion / ! d ; s/.*MajorVersion *"\(.*\)"/\1/' src/VersionNum) + else + version=$(git rev-parse --short HEAD) + fi + echo "This is version: $version" + leafname="WakeOnLAN-$version.zip" + if [ -f /tmp/built,a91 ] ; then + cp /tmp/built,a91 "WakeOnLAN-$version.zip" + else + echo "No archive was built?" + exit 1 + fi + echo "::set-output name=version::$version" + echo "::set-output name=leafname::$leafname" + + - uses: actions/upload-artifact@v2 + with: + name: RISCOS-build + path: ${{ steps.version.outputs.leafname }} + # The artifact that is downloadable from the Actions is actually a zip of the artifacts + # that we supply. So it will be a regular Zip file containing a RISC OS Zip file. + + # The release only triggers when the thing that was pushed was a tag starting with 'v' + release: + needs: build-riscos + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/v') + steps: + - name: Download built binary + uses: actions/download-artifact@v1 + with: + name: RISCOS-build + + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ needs.build-riscos.outputs.version }} + draft: true + prerelease: false + + - name: Upload Release Asset + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. + # See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: RISCOS-build/${{ needs.build-riscos.outputs.leafname }} + asset_name: ${{ needs.build-riscos.outputs.leafname }} + asset_content_type: application/zip diff --git a/.robuild.yaml b/.robuild.yaml new file mode 100644 index 0000000..da0d053 --- /dev/null +++ b/.robuild.yaml @@ -0,0 +1,33 @@ +%YAML 1.0 +--- + +# RISC OS Build service build file +# How to build manually on a non-RISC OS system: +# rm -f /tmp/source-archive.zip ; zip -9r /tmp/source-archive.zip .robuild.yaml src LICENSE ; riscos-build-online -i /tmp/source-archive.zip -o /tmp/built and unzip -l /tmp/built,a91 + +# Defines a list of jobs which will be performed. +# Only 1 job will currently be executed. +jobs: + build: + # Env defines system variables which will be used within the environment. + # Multiple variables may be assigned. + env: + "Sys$Environment": ROBuild + "BUILD32": 1 + "Locale": UK + + # Directory to change to before running script + dir: src + + # Commands which should be executed to perform the build. + # The build will terminate if any command returns a non-0 return code or an error. + script: + - /MkROBuild + + # Outputs from the build are defined in artifacts + # These are a list of artifacts to report directories or files. + # Only a single item is currently supported. + artifacts: + # Each element of the artifacts should have a path key, which gives the file or + # directory to return. + - path: Artifacts diff --git a/src/MakefileROBuild,fe1 b/src/MakefileROBuild,fe1 new file mode 100755 index 0000000..ebc1140 --- /dev/null +++ b/src/MakefileROBuild,fe1 @@ -0,0 +1,47 @@ +#!/usr/bin/env riscos-amu -f +# Makefile for WakeOnLan +# + +# +# Program specific options: +# +COMPONENT = WakeOnLan + +# Specifies additional targets for startup +#INITTARGET = inittarget + +# Specifies additional targets for clean +#CLEANTARGET = cleantarget + +# aif, for linked objects +# aof, for a partially linked AOF object +# util, for utilities built with objasm +# basic, for BASIC tools +TYPE = aif + +# The file to output (defaults ${COMPONENT}) +#TARGET = + +# Comma-separated list of paths to use for includes, such as: +# .LibName. +INCLUDES = TCPIPLibs: + +# Space separated list of defines to set, eg -DDEBUG +CDEFINES = + +# Space separated list of libraries to link against. +LIBS = ${CLIB} ${TCPIPLIBS} + +# Objects to build, using the format o. (will be varied for build type) +OBJS = o.magic \ + o.main \ + +# Space separated list of XML files for building documentation. +#DOCSRC = + + +include LibraryCommand + + +#--------------------------------------------------------------------------- +# Dynamic dependencies: diff --git a/src/MkROBuild,feb b/src/MkROBuild,feb new file mode 100644 index 0000000..4fec908 --- /dev/null +++ b/src/MkROBuild,feb @@ -0,0 +1,12 @@ +| Build on the RISC OS Build service + +Dir +cdir ^.Artifacts +cdir ^.Artifacts.Library +cdir ^.Artifacts.Library.Internet +amu -f MakeFileROBuild install INSTDIR=^.Artifacts.Library.Internet +if "" <> 0 Then Error Failed to build + +| Two LICENSE files are present, so must be supplied to the user. +copy LICENSE ^.Artifacts.LICENSE/1 ~CVF +copy ^.LICENSE ^.Artifacts.LICENSE/2 ~CVF diff --git a/src/Resources/UK/Help b/src/Resources/UK/Help new file mode 100644 index 0000000..5e69976 --- /dev/null +++ b/src/Resources/UK/Help @@ -0,0 +1,3 @@ +WakeOnLAN {Module_FullVersionAndDate} +*WakeOnLAN is used to send a magic network packet to a machine to cause it to wake up. The remote machine must be configured to accept such network packets. +Syntax: *WakeOnLAN -m [ -b ] [-v] diff --git a/src/VersionNum b/src/VersionNum new file mode 100644 index 0000000..4c7abda --- /dev/null +++ b/src/VersionNum @@ -0,0 +1,24 @@ +/* WakeOnLAN (0.02) 01:13:55 12/12/2022 + * + * This file is automatically maintained by vmanage, do not edit manually. + * + */ +#define Module_MajorVersion_CMHG 0.02 +#define Module_MinorVersion_CMHG +#define Module_Date_CMHG 12 Dec 2022 + +#define Module_MajorVersion "0.02" +#define Module_Version 2 +#define Module_MinorVersion "" +#define Module_Date "12 Dec 2022" + +#define Module_ApplicationDate2 "12-Dec-22" +#define Module_ApplicationDate4 "12-Dec-2022" + +#define Module_ComponentName "WakeOnLAN" +#define Module_ComponentBranch "" +#define Module_ComponentPath "WakeOnLAN" + +#define Module_FullVersion "0.02" +#define Module_FullVersionAndDate "0.02 (12 Dec 2022)" +#define Module_HelpVersion "0.02 (12 Dec 2022)" diff --git a/src/c/main b/src/c/main index ace0e77..d55b5dc 100644 --- a/src/c/main +++ b/src/c/main @@ -1,7 +1,6 @@ /* * WakeOnLAN command for RISC OS * - * release 0.1 * Copyright 2004 by Paolo Fabio Zaino * * Redistribution and use in source and binary forms, with or without @@ -48,26 +47,33 @@ #include #include -#ifdef __GNUC__ - #include - #include - #include - #include - #include -#else -#include "TCPIPLibs:sys.h.unistd" -#include "TCPIPLibs:sys.h.types" -#include "TCPIPLibs:sys.h.socket" -#include "TCPIPLibs:netinet.h.in" -#include "TCPIPLibs:netdb.h" +#include +#include +#include +#include +#include +#include + +#ifndef __GNUC__ +#include "unixlib.h" +#include "socklib.h" +char *__progname = "WakeOnLan"; #endif +#include "VersionNum" + #include "magic.h" + static verbose_output = 0; + +int sendMagicPacket(unsigned int mac[6], const char *broadcastAddress); + + void show_syntax() { - printf("Syntax: *wakeonlan -m [ -b ] [-v]\n"); + printf("WakeOnLAN %s\n", Module_FullVersionAndDate); + printf("Syntax: *WakeOnLAN -m [ -b ] [-v]\n"); printf(" Where has to be the MAC of the device you want to wake up. (MAC syntax: 01:02:03:04:05:06)\n"); printf(" And is a valid broadcast address for you LAN. (broadcast syntax: xxx.yyy.hhh.zzz\n"); printf(" -v specify you want verbose output\n"); @@ -98,12 +104,6 @@ void check_broadcast(char bAddress[], const char *user_input ) } int main(int argc, char** argv){ - // WakeOnLAN requires at least 2 arguments - if(argc < 2) - { - show_syntax(); - exit(EXIT_FAILURE); - } // bAddress is the default Broadcasting Address // by default it's set to a commonly used address @@ -112,18 +112,17 @@ int main(int argc, char** argv){ // Mac address unsigned int mac[6]; - // Packet Buffer - unsigned char packet[102]; - - // Set broadcast - int broadcast = 1; - - // Socket address - struct sockaddr_in udpClient, udpServer; - int user_mac = 0; int c = 0; opterr = 0; + + // WakeOnLAN requires at least 2 arguments + if(argc < 2) + { + show_syntax(); + exit(EXIT_FAILURE); + } + while (( c = getopt (argc, argv, "m:b:v")) != -1 ) switch (c) { @@ -162,46 +161,82 @@ int main(int argc, char** argv){ if (verbose_output) printf("Using %s broadcast address\n", bAddress); + if (!sendMagicPacket(mac, bAddress)) + { + exit(EXIT_FAILURE); + } + exit(EXIT_SUCCESS); +} + + +/****************************************************************** + Function: sendMagicPacket + Description: Send a wake-on-lan packet to a remote machine + Errors are printed to stdout. + Parameters: mac-> list of 6 ints to send (only the low 8 bits of each int will be used) + broadcastAddress-> string representation of address to send to + Returns: 0 for success, 1 for failure + ******************************************************************/ +int sendMagicPacket(unsigned int mac[6], const char *broadcastAddress) +{ + // Packet Buffer + unsigned char packet[102]; + int udpSocket; + int result; + int success = 0; + + // Set broadcast + int broadcast = 1; + + // Socket address + struct sockaddr_in udpClient, udpServer; + genMagicPacket(packet, mac); - int udpSocket = socket(AF_INET, SOCK_DGRAM, 0); + udpSocket = socket(AF_INET, SOCK_DGRAM, 0); if (udpSocket == -1) { printf("An error was encountered creating the UDP socket: '%s'.\n", strerror(errno)); - exit(EXIT_FAILURE); + goto cleanup; } - int setsock_result = setsockopt(udpSocket, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof broadcast); - if (setsock_result == -1) + result = setsockopt(udpSocket, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof broadcast); + if (result == -1) { printf("Failed to set socket options: '%s'.\n", strerror(errno)); - exit(EXIT_FAILURE); + goto cleanup; } udpClient.sin_family = AF_INET; udpClient.sin_addr.s_addr = INADDR_ANY; udpClient.sin_port = 0; - int bind_result = bind(udpSocket, (struct sockaddr*) &udpClient, sizeof(udpClient)); - if (bind_result == -1) + result = bind(udpSocket, (struct sockaddr*) &udpClient, sizeof(udpClient)); + if (result == -1) { printf("Failed to bind socket: '%s'.\n", strerror(errno)); - exit(EXIT_FAILURE); + goto cleanup; } udpServer.sin_family = AF_INET; - udpServer.sin_addr.s_addr = inet_addr(bAddress); + udpServer.sin_addr.s_addr = inet_addr(broadcastAddress); udpServer.sin_port = htons(9); // Send the packet - int result = sendto(udpSocket, &packet, sizeof(unsigned char) * 102, 0, (struct sockaddr*) &udpServer, sizeof(udpServer)); + result = sendto(udpSocket, &packet, sizeof(unsigned char) * 102, 0, (struct sockaddr*) &udpServer, sizeof(udpServer)); if (result == -1) { printf("Failed to send magic packet to socket: '%s'.\n", strerror(errno)); - exit(EXIT_FAILURE); + goto cleanup; + } + else + { + success = 1; } if (verbose_output) printf("Wake up packet was sent.\n"); - exit(EXIT_SUCCESS); +cleanup: + socketclose(udpSocket); + return success; } diff --git a/src/h/magic b/src/h/magic index e33c290..3dde3e1 100644 --- a/src/h/magic +++ b/src/h/magic @@ -1,5 +1,5 @@ -#ifdef __WOL_MAGIC -#define __WOL_MAGIC +#ifndef WOL_MAGIC +#define WOL_MAGIC /* * WakeOnLAN command for RISC OS @@ -25,4 +25,4 @@ // This function below creates one in memory. void genMagicPacket(unsigned char packet[], unsigned int macAddress[]); -#endif \ No newline at end of file +#endif