I have been trying to write a PHP script to send SMS messages via a GSM modem connected to the server machine.
Below is the aforesaid PHP script.
<?php
$device = "COM7";
exec("mode $device BAUD=9600 PARITY=n DATA=8");
$comport = fopen($device, "w");
fputs($comport,"AT+CMGF=1\n\r");
fputs($comport,"AT+cmgs=\"xxxxxxxxxx\"\n\r");
fputs($comport,"sms text\n\r");
fputs($comport,chr(26));
fclose($comport);
echo "done";
?>
When I try to run the above code I get the following error;
Warning: fopen(COM7): failed to open stream: Permission denied in E:\wamp\www\sms\index.php on line 4
and
Warning: fclose() expects parameter 1 to be resource, boolean given in E:\wamp\www\sms\index.php on line 9
I have tried changing the user permission in windows to allow WAMP server full access, which WAMP server already had by default.
As a workaround I have tried using the DIO extension which gave a similar error when trying to open a port. DIO also gave an permission denied error.
It was suggested here in stackoverflow to use the physical address of the GSM modem instead of "COM7", I tried it didn't work. Another answer had suggested to add the www-data to the dialout group, but that solution was for Linux.
I tried writing a Java servlet as a workaround for this issue. The Java program runs as a stand alone file, but when its run as a servlet via Tomcat, it again gives an "Access Violation" error. I used RXTX library for the Java servlet.
So I am guessing this error is caused by lack of permission assigned to whoever is trying to access the com port via the server. (I get "SYSTEM" when I ran echo get_current_user();
from the above PHP script)
I am trying to find the root cause of this error. Your help is much appreciated.
Below is the Java SMS sender class which uses the RXTX Library.
import java.io.*;
import java.util.*;
import gnu.io.*;
public class SMSsender {
static Enumeration portList;
static CommPortIdentifier portId;
static String messageString1 = "AT";
static String messageString3 = "AT+CMGF=1";
static String messageString4 = "AT+CMGS=\"+xxxxxxxxxx\"";
static String messageString5 = "TESTY2";
static SerialPort serialPort;
static OutputStream outputStream;
static InputStream inputStream;
static char enter = 13;
static char CTRLZ = 26;
public void sendMessage(String[] args) throws InterruptedException {
portList = CommPortIdentifier.getPortIdentifiers();
while (portList.hasMoreElements()) {
portId = (CommPortIdentifier) portList.nextElement();
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
if (portId.getName().equals("COM7")) {
try {
serialPort = (SerialPort) portId.open("COM7", 2000);
} catch (PortInUseException e) {
System.out.println("err");
}
try {
outputStream = serialPort.getOutputStream();
inputStream = serialPort.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
try {
serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
} catch (UnsupportedCommOperationException e) {
e.printStackTrace();
}
try {
outputStream.write((messageString1 + enter).getBytes());
Thread.sleep(100);
outputStream.flush();
// outputStream.write((messageString2 + enter).getBytes());
Thread.sleep(100);
outputStream.flush();
outputStream.write((messageString3 + enter).getBytes());
Thread.sleep(100);
outputStream.flush();
outputStream.write((messageString4 + enter).getBytes());
Thread.sleep(100);
outputStream.flush();
outputStream.write((messageString5 + CTRLZ).getBytes());
outputStream.flush();
Thread.sleep(100);
System.out.println("step 1");
Thread.sleep(3000);
outputStream.close();
serialPort.close();
System.out.println("step 2");
} catch (IOException e) {
e.printStackTrace();
serialPort.close();
} finally {
serialPort.close();
}
}
}
}
}
}
Above code works when its run outside of the server as a stand alone application.
Following is the servlet code which invokes the above class to send an SMS.
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class sendSMS extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// Set the response MIME type of the response message
response.setContentType("text/html");
// Allocate a output writer to write the response message into the network socket
PrintWriter out = response.getWriter();
SMSsender obj = new SMSsender();
try {
obj.sendMessage(null);
}
catch(Exception e)
{
out.println(e.getMessage());
}
finally {
out.close(); // Always close the output writer
}
}
}
When this servlet is run through Apache Tomcat, the server automatically closes with the following error in the log.
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000001cf32174465, pid=5828, tid=2276
#
# JRE version: Java(TM) SE Runtime Environment (10.0.2+13) (build 10.0.2+13)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (10.0.2+13, mixed mode, tiered, compressed oops, g1 gc, windows-amd64)
# Problematic frame:
# C [rxtxSerial.dll+0x4465]
#
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.