#!/usr/bin/lua senders2delete = {} deletebinaries = false modemn = arg[1] local smsresult = "/tmp/smsresult" .. modemn .. ".at" local smsslots = "/tmp/smsslots" .. modemn local smstime = "/tmp/smstime" .. modemn local t = {} local tptr local m_pdu_ptr local m_pdu local m_smsc local m_with_udh local m_report local m_number local m_replace local m_alphabet local m_dcs local m_flash local m_date local m_time local m_text local m_concat local m_read local m_index local g_table1 = {} local g_table2 = {} local max_smsc = 64 local max_number = 64 local max_udh_data = 512 surrogate = 0 function reset() m_smsc = nil m_with_udh = 0 m_report = 0 m_number = nil m_replace = 0 m_alphabet = -1 m_flash = 0 m_date = nil m_time = nil m_text = nil m_concat = nil end function hasbit(x, p) return x % (p + p) >= p end function bitor(x, y) local p = 1; local z = 0; local limit = x > y and x or y while p <= limit do if hasbit(x, p) or hasbit(y, p) then z = z + p end p = p + p end return z end function bitand(x, y) local p = 1; local z = 0; local limit = x > y and x or y while p <= limit do if hasbit(x, p) and hasbit(y, p) then z = z + p end p = p + p end return z end function bitright(x, y) return math.floor(x / 2 ^ y) end function bitleft(x, y) return x * 2 ^ y end function ocount(x, y) local j = 0 local i = x:find(y, 0) while i ~= nil do i = x:find(y, i + 1) j = j + 1 end return j end printf = function(s,...) if echo == 0 then io.write(s:format(...)) else ss = s:format(...) os.execute("/usr/lib/rooter/logprint.sh " .. ss) end end function isxdigit(digit) if digit == nil then return 0 end if digit >= 48 and digit <= 57 then return 1 end if digit >= 97 and digit <= 102 then return 1 end if digit >= 65 and digit <= 70 then return 1 end return 0 end function isdigit(digit) if digit >= 48 and digit <= 57 then return 1 end return 0 end function octet2bin(octet) result = 0 if octet:byte(1) > 57 then result = result + octet:byte(1) - 55 else result = result + octet:byte(1) - 48 end result = result * 16 if octet:byte(2) > 57 then result = result + octet:byte(2) - 55 else result = result + octet:byte(2) - 48 end return result end function octet2bin_check(octet) if octet:byte(1) == 0 then return -1 end if octet:byte(2) == 0 then return -2 end if isxdigit(octet:byte(1)) == 0 then return -3 end if isxdigit(octet:byte(2)) == 0 then return -4 end return octet2bin(octet) end function swapchars(sstring) local length = sstring:len() local xstring = nil local i = 1 while i < length do c1 = sstring:sub(i, i) c2 = sstring:sub(i+1, i+1) if xstring == nil then xstring = c2 .. c1 else xstring = xstring .. c2 .. c1 end i = i + 2 end return xstring end function parseSMSC() m_pdu_ptr = m_pdu local length = octet2bin_check(m_pdu_ptr) if length < 0 then return -1 end if length == 0 then m_smsc = "" m_pdu_ptr = m_pdu_ptr:sub(3) return 1 end if length < 2 or length > max_smsc then return -1 end length = (length * 2) - 2 local mlen = m_pdu:len() if mlen < (length + 4) then return -1 end m_pdu_ptr = m_pdu_ptr:sub(3) local addr_type = octet2bin_check(m_pdu_ptr) if addr_type < 0 then return -1 end if addr_type < 0x80 then return -1 end m_pdu_ptr = m_pdu_ptr:sub(3) m_smsc = m_pdu_ptr:sub(0, length) m_smsc = swapchars(m_smsc) if addr_type < 0x90 then for j=1, length do if isxdigit(m_smsc:byte(j)) == 0 then return -1 end end else if m_smsc:byte(length) == 70 then m_smsc = m_smsc:sub(1, length-1) end local leng = m_smsc:len() for j=1,leng do if isdigit(m_smsc:byte(j)) == 0 then return -1 end end end m_pdu_ptr = m_pdu_ptr:sub(length + 1) return 1 end function explainAddressType(octet_char, octet_int) local result if octet_char ~= nil then result = octet2bin_check(octet_char) else result = octet_int end return result end function concatinfo(x) while #x > 9 do if x:sub(1, 4) == '0003' then if x:sub(7, 10) ~= '0101' then m_concat = 'Msg# ' .. tonumber(x:sub(5, 6), 16) m_concat = m_concat .. ',' .. tonumber(x:sub(9, 10), 16) m_concat = m_concat .. '/' .. tonumber(x:sub(7, 8), 16) end x = "" elseif x:sub(1, 4) == '0804' then if x:sub(9, 12) ~= '0101' then m_concat = 'Msg# ' .. tonumber(x:sub(5, 8), 16) m_concat = m_concat .. ',' .. tonumber(x:sub(11, 12), 16) m_concat = m_concat .. '/' .. tonumber(x:sub(9, 10), 16) end x = "" else local iel = tonumber(x:sub(3, 4), 16) x = x:sub(5 + iel * 2) end end end function pdu2binary(pdu, with_udh) local skip_octets = 0 local octetcounter m_text = '' local octets = octet2bin_check(pdu) local last_i = 0 if octets < 0 then return -1 end if with_udh > 0 then local pdu2 = pdu:sub(3) local udhl = tonumber(pdu2:sub(1, 2), 16) concatinfo(pdu2:sub(3, (udhl + 1) * 2)) local udhsize = octet2bin_check(pdu2) if udhsize < 0 then return -1 end skip_octets = udhsize + 1 end for octetcounter = 0, (octets - skip_octets - 1) do local pdu2 = pdu:sub((octetcounter * 2) + 3 + (skip_octets * 2)) local i = octet2bin_check(pdu2) if i < 0 then return -1 end if m_alphabet == 2 then if (2 + octetcounter) % 2 == 0 then last_i = i else m_text = word2utf8(bitor(bitleft(last_i, 8), i), m_text) end else if i < 32 or i > 127 then i = 0x25A1 end m_text = word2utf8(i, m_text) end end return (octets - skip_octets) end function pdu2text(pdu, with_udh) local result local octetcounter local skip_characters = 0 local binary = 0 m_text = '' local septets = octet2bin_check(pdu) if septets < 0 then return -1 end if with_udh > 0 then local pdu2 = pdu:sub(3) local udhl = tonumber(pdu2:sub(1, 2), 16) concatinfo(pdu2:sub(3, (udhl + 1) * 2)) local udhsize = octet2bin_check(pdu2) skip_characters = math.floor((((udhsize+1)*8)+6)/7) end local octets = math.floor((septets * 7 + 7) / 8) local bitposition = 0 local byteposition local byteoffset local i local g_table_nbr = 1 octetcounter = 0 for charcounter=0,septets-1 do local c = 0 for bitcounter=0,6 do byteposition = math.floor(bitposition / 8) byteoffset = bitposition % 8 while (byteposition >= octetcounter) and (octetcounter < octets) do local pdu2 = pdu:sub((octetcounter * 2) + 3) i = octet2bin_check(pdu2) if i < 0 then return -2 end binary = i octetcounter = octetcounter + 1 end if bitand(binary, (2^byteoffset)) > 0 then c = bitor(c, 128) end bitposition = bitposition + 1 c = bitand(math.floor(c / 2), 127) end c = gsm2byte(c) if charcounter >= skip_characters and c ~= 27 then m_text = word2utf8(c, m_text) end end return 1 end function gsm2byte(ch) if g_table_nbr == 2 then if g_table2[ch] == nil then ch = 63 else ch = g_table2[ch] end g_table_nbr = 1 else if ch == 27 then g_table_nbr = 2 else if g_table1[ch] ~= nil then ch = g_table1[ch] end end end return ch end function word2utf8(i, txt) if surrogate > 0 then if i >= 0xDC00 and i <= 0xDFFF then local ii = 0x10000 + bitand(i, 0x3FF) + bitleft(bitand(surrogate, 0x3FF), 10) txt = txt .. string.char(bitor(0xF0, bitright(bitand(ii, 0x1C0000), 18))) txt = txt .. string.char(bitor(0x80, bitright(bitand(ii, 0x3F000), 12))) txt = txt .. string.char(bitor(0x80, bitright(bitand(ii, 0xFC0), 6))) txt = txt .. string.char(bitor(0x80, bitand(ii, 0x3F))) else txt = txt .. string.char(0xe2) .. string.char(0x96) .. string.char(0xa1) end surrogate = 0 elseif i >= 0xD800 and i <= 0xDBFF then surrogate = i elseif i >= 0xDC00 and i <= 0xDFFF then txt = txt .. string.char(0xe2) .. string.char(0x96) .. string.char(0xa1) elseif i < 0x80 then txt = txt .. string.char(i) elseif i < 0x800 then txt = txt .. string.char(bitor(0xC0, bitright(bitand(i, 0x7C0), 6))) txt = txt .. string.char(bitor(0x80, bitand(i, 0x3F))) else if i == 0x2029 then txt = txt .. string.char(10) else txt = txt .. string.char(bitor(0xE0, bitright(bitand(i, 0xF000), 12))) txt = txt .. string.char(bitor(0x80, bitright(bitand(i, 0xFC0), 6))) txt = txt .. string.char(bitor(0x80, bitand(i, 0x3F))) end end return txt end function parseDeliver() if m_pdu_ptr:len() < 4 then return 0 end local padding = 0 local length = octet2bin_check(m_pdu_ptr) local timezone if length < 0 or length > max_number then return 0 end -- Sender Address if length == 0 then m_pdu_ptr = m_pdu_ptr:sub(5) else padding = length % 2 m_pdu_ptr = m_pdu_ptr:sub(3) local addr_type = explainAddressType(m_pdu_ptr, 0) if addr_type < 0 then return 0 end if addr_type < 0x80 then return 0 end m_pdu_ptr = m_pdu_ptr:sub(3) if bitand(addr_type, 112) == 80 then if m_pdu_ptr:len() < (length + padding) then return 0 end local htmp = string.format("%x", math.floor((length * 4) / 7)) if htmp:len() < 2 then htmp = "0" .. htmp end htmp = htmp:upper() local tpdu = htmp .. m_pdu_ptr local res = pdu2text(tpdu, 0) if res < 0 then return 0 end m_number = string.gsub(m_text, "\n", " ") m_text = nil else m_number = m_pdu_ptr:sub(1, length + padding + 1) m_number = swapchars(m_number) if m_number:byte(length + padding) == 70 then m_number = m_number:sub(1, length + padding - 1) end if addr_type == 145 then m_number = "+" .. m_number end end end m_pdu_ptr = m_pdu_ptr:sub(length + padding + 1) if m_pdu_ptr:len() < 20 then return 0 end -- PID local byte_buf = octet2bin_check(m_pdu_ptr) if byte_buf < 0 then return 0 end if bitand(byte_buf, 0xF8) == 0x40 then m_replace = bitand(byte_buf, 0x07) end m_pdu_ptr = m_pdu_ptr:sub(3) -- Alphabet byte_buf = octet2bin_check(m_pdu_ptr) if byte_buf < 0 then return 0 end m_alphabet = math.floor(bitand(byte_buf, 0x0C) / 4) if m_alphabet == 3 then return 0 end if m_alphabet == 0 then m_alphabet = -1 end -- DCS, Flash Msg m_dcs = byte_buf if bitand(byte_buf, 0x10) > 0 then if bitand(byte_buf, 0x01) > 0 then m_flash = 1 end end m_pdu_ptr = m_pdu_ptr:sub(3) -- Date local str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. "-" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. "-" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then return 0 end m_date = str_buf m_pdu_ptr = m_pdu_ptr:sub(7) -- Time str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. ":" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. ":" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then return 0 end if tonumber(m_pdu_ptr:sub(8,8), 16) > 7 then timezone = '-' .. ((tonumber(m_pdu_ptr:sub(8, 8), 16) - 8) .. tonumber(m_pdu_ptr:sub(7, 7), 16)) / 4 else timezone = '+' .. (m_pdu_ptr:sub(8, 8) .. tonumber(m_pdu_ptr:sub(7, 7), 16)) / 4 end if timezone:sub(-2, -1) == '.0' then timezone = timezone:sub(1, -3) end m_time = str_buf .. ' ' .. timezone .. 'h' m_pdu_ptr = m_pdu_ptr:sub(7) if octet2bin_check(m_pdu_ptr) < 0 then return 0 end m_pdu_ptr = m_pdu_ptr:sub(3) -- Text local result = 0 local bin_udh = 1 if m_alphabet <= 0 then result = pdu2text(m_pdu_ptr, m_with_udh) return result else result = pdu2binary(m_pdu_ptr, m_with_udh) return result end return 1 end function parseStatusReport() if m_pdu_ptr:len() < 6 then return 0 end local messageid = octet2bin_check(m_pdu_ptr) if messageid < 0 then return 0 end m_pdu_ptr = m_pdu_ptr:sub(3) local length = octet2bin_check(m_pdu_ptr) if length < 1 or length > max_number then return 0 end local padding = length % 2 m_pdu_ptr = m_pdu_ptr:sub(3) local addr_type = explainAddressType(m_pdu_ptr, 0) if addr_type < 0x80 then return 0 end m_pdu_ptr = m_pdu_ptr:sub(3) if bitand(addr_type, 112) == 80 then if m_pdu_ptr:len() < (length + padding) then return 0 end local htmp = string.format("%x", math.floor((length * 4) / 7)) if htmp:len() < 2 then htmp = "0" .. htmp end local tpdu = htmp .. m_pdu_ptr local res = pdu2text(tpdu, 0) if res < 0 then return 0 end m_number = m_text m_text = nil else m_number = m_pdu_ptr:sub(1, length + padding + 1) m_number = swapchars(m_number) if m_number:byte(length + padding) == 70 then m_number = m_number:sub(1, length + padding - 1) end end m_pdu_ptr = m_pdu_ptr:sub(length + padding + 1) if m_pdu_ptr:len() < 14 then return 0 end -- Date local str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. "-" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. "-" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then return 0 end m_date = str_buf m_pdu_ptr = m_pdu_ptr:sub(7) -- Time str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. ":" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. ":" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then return 0 end m_time = str_buf m_pdu_ptr = m_pdu_ptr:sub(7) if octet2bin_check(m_pdu_ptr) < 0 then return 0 end m_pdu_ptr = m_pdu_ptr:sub(3) -- Discharge Date local str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. "-" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. "-" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then return 0 end local d_date = str_buf m_pdu_ptr = m_pdu_ptr:sub(7) -- Time str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. ":" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. ":" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then return 0 end local d_time = str_buf m_pdu_ptr = m_pdu_ptr:sub(7) if octet2bin_check(m_pdu_ptr) < 0 then return 0 end m_pdu_ptr = m_pdu_ptr:sub(3) local status = octet2bin_check(m_pdu_ptr) if status < 0 then return 0 end m_text = string.format("Discharge Timestamp: %s %s Message ID: %d Status: %d", d_date, d_time, messageid, status) return 1 end function parse() local flag = parseSMSC() if flag ~= 1 then return 0 end local tmp = octet2bin_check(m_pdu_ptr) if tmp < 0 then return 0 end if bitand(tmp, 0x40) > 0 then m_with_udh = 1 end if bitand(tmp, 0x20) > 0 then m_report = 1 end local type = bitand(tmp, 3) if type == 0 then m_pdu_ptr = m_pdu_ptr:sub(3) local result = parseDeliver() if result < 1 then return 0 end else if type == 2 then m_pdu_ptr = m_pdu_ptr:sub(3) local result = parseStatusReport() return result else return 0 end end return 1 end function trim(s) return (s:gsub("^%s*(.-)%s*$", "%1")) end function readpdu(pdu) m_pdu = pdu m_pdu_ptr = m_pdu reset() local flag = parse() if flag > 0 then t[tptr] = m_index t[tptr+1] = m_read t[tptr+2] = m_number if string.find(delsend, gschar .. m_number .. gschar, 1, true) then delslots = delslots .. m_index .. " " else if m_dcs == 245 and deletebinaries then delslots = delslots .. m_index .. " " end end t[tptr+3] = m_date t[tptr+4] = m_time if m_concat ~= nil then m_text = m_concat .. '\n' .. m_text end t[tptr+5] = m_text tptr = tptr + 6 end end local max_msg = "0" local used_msg = "0" gschar = string.char(29) delsend = gschar .. table.concat(senders2delete, gschar) .. gschar delslots = "" tptr = 3 t[1] = used_msg t[2] = max_msg g_table1 = {163, 36, 165, 232, 233, 249, 236, 242, 199, 10, 216, 248, 13, 197, 229, 0x394, 95, 0x3A6, 0x393, 0x39B, 0x3A9, 0x3A0, 0x3A8, 0x3A3, 0x398, 0x39E} g_table1[0] = 64 g_table1[28] = 198 g_table1[29] = 230 g_table1[30] = 223 g_table1[31] = 201 g_table1[36] = 164 g_table1[64] = 161 g_table1[91] = 196 g_table1[92] = 214 g_table1[93] = 209 g_table1[94] = 220 g_table1[95] = 167 g_table1[96] = 191 g_table1[123] = 228 g_table1[124] = 246 g_table1[125] = 241 g_table1[126] = 252 g_table1[127] = 224 g_table2[10] = 10 g_table2[20] = 94 g_table2[40] = 123 g_table2[41] = 125 g_table2[47] = 92 g_table2[60] = 91 g_table2[61] = 126 g_table2[62] = 93 g_table2[64] = 124 g_table2[101] = 0x20AC -- os.execute("touch " .. smsslots) local slottab = {} local file = io.open(smsslots, "r") for k in file:lines() do slottab[k] = true end file:close() local file = io.open(smsresult, "r") local m_r = "" if file ~= nil then repeat local s, e, cs, ce, ms, me local line = file:read("*l") if line == nil then break end s, e = line:find("+CPMS:") if s ~= nil then cs, ce = line:find(",", e) if cs ~= nil then used_msg = trim(line:sub(e+1, cs-1)) t[1] = used_msg ms, me = line:find(",", ce+1) if ms ~= nil then max_msg = trim(line:sub(ce+1, ms-1)) t[2] = max_msg end end line = file:read("*l") if line == nil then break end end s, e = line:find("+CMGL:") if s ~= nil then m_index = "0" cs, ce = line:find(",", e) if cs ~= nil then m_index = trim(line:sub(e+1, cs-1)) end ds, de = line:find(",", ce+1) if ds ~= nil then surrogate = 0 m_r = trim(line:sub(ce+1, ds-1)) if m_r == "0" then m_read = word2utf8(0x2691, word2utf8(0x2691, '')) os.execute("date +%s > " .. smstime) if not slottab[m_index] then os.execute("echo " .. m_index .. " >> " .. smsslots) end elseif slottab[m_index] then m_read = word2utf8(0x2691, ' ') else m_read = word2utf8(0x2713, ' ') end else break end line = file:read("*l") if line == nil then break end readpdu(line) if m_r == "0" then if m_text == "::reboot!!" then os.execute("(sleep 60; reboot -f) &") elseif m_text == "::pwrtoggle!!" then os.execute("(sleep 60; /usr/lib/rooter/pwrtoggle.sh 3) &") elseif m_text:sub(1, 3) == "GPS" then cmd_hand = io.popen("uci -q get modem.general.pin") gpspin = cmd_hand:read() cmd_hand:close() if (m_text == "GPS" and gpspin == nil) or (m_text == "GPS " .. gpspin) then if tonumber(m_number) ~= nil then os.execute("/usr/lib/gps/smsreply.sh " .. modemn .. " " .. m_number .. "&") delslots = delslots .. m_index .. " " end end end end end until 1==0 file:close() end local tfname = "/tmp/smstemptext" .. math.random(99) local tfile = io.open(tfname, "w") tfile:write(t[1] .. "\n") tfile:write(t[2] .. "\n") if tonumber(used_msg) == 0 then tfile:close() else i = 3 while t[i] ~= nil do local mtxt = t[i + 5] tfile:write(t[i] .. "\n") tfile:write(t[i + 2] .. "\n") tfile:write((ocount(mtxt, '\n') + 1) .. '\n') tfile:write(mtxt .. "\n") local mn = t[i + 2] .. " " mn = mn:sub(1,20) local stxt = '' local j = 0 local k = 1 local ch = '' while j < 20 do ch = string.byte(mtxt:sub(k, k)) if ch == nil then j = 20 elseif ch == 10 or ch == 13 then stxt = stxt .. ' ' k = k + 1 elseif ch < 127 then stxt = stxt .. string.char(ch) k = k + 1 elseif ch < 0xE0 then stxt = stxt .. mtxt:sub(k, k + 1) k = k + 2 elseif ch < 0xF0 then stxt = stxt .. mtxt:sub(k, k + 2) k = k + 3 else stxt = stxt .. mtxt:sub(k, k + 3) k = k + 4 end j = j + 1 end if mtxt ~= stxt then stxt = stxt .. " ..." end local msg = t[i + 1] .. " " .. mn .. t[i + 3] .. " " .. t[i + 4] .. " " .. stxt tfile:write(msg .. "\n") i = i + 6 end tfile:close() end os.execute("mv " .. tfname .. " /tmp/smstext" .. modemn) if #delslots > 0 then os.execute("/usr/lib/sms/delsms.sh " .. modemn .. " " .. delslots .. " &") end