mIRC Twitch.tv bot points system on and off commands - bots

I am currently working on a twitch.tv bot. What the bot is designed to do is to automatically give points to a user when they join chat on the mIRC end of things. A timer gets started and they receive 1 point every 30 mins. The problem with this is I do not want people to afk in the chat with the stream turned off so I would like to put in a command like "!pointstimer start". When that command is ran I would like it to display a message that the timer has started. I would like this command to also be op only so others can not run the command at anytime they see fit. I have the points system in place as well as a raffle system for give aways. The problem is when I put in commands to turn the points system on and off nothing happens. I can get it to display text if the command is not op but when it is op then nothing happens. Here is copies of all of my code.
Code:
on *:TEXT:!commands:#: {
if ((%floodcommands) || ($($+(%,floodcommands.,$nick),2))) { return }
set -u10 %floodcommands On
set -u30 %floodcommands. $+ $nick On
msg $chan The commands for this channel are the following. !commands, !social, !help, !cop, !hypno, !medic, !vigi, !inno, !gunsmith, !rafflesystem, !donks, !buytickets [number of tickets]. Mod only commands are the following, !donks [add|remove] [user] [number], !raffle [open|close], !roll, !permit [user]. $+
}
on *:TEXT:!social:#: {
if ((%floodsocial) || ($($+(%,floodsocial.,$nick),2))) { return }
set -u10 %floodsocial On
set -u30 %floodsocial. $+ $nick On
msg $chan The YouTube page is http://www.youtube.com/user/TheDailyMafia The Twitter page is http://twitter.com/DailyMafia Don't forget to follow and subscribe! $+
}
on *:TEXT:!help:#: {
if ((%floodhelp) || ($($+(%,floodhelp.,$nick),2))) { return }
set -u10 %floodhelp On
set -u30 %floodhelp. $+ $nick On
msg $chan To learn the rules of mafia check out $+
}
on *:TEXT:!cop:#: {
if ((%floodcop) || ($($+(%,floodcop.,$nick),2))) { return }
set -u10 %floodcop On
set -u30 %floodcop. $+ $nick On
msg $chan Every night the Cop picks a player who is currently alive to investigate or “check”. The mod will then tell the Cop whether that player is town or mafia. Note: the Cop only finds out if the player is town or mafia and is not informed of any special role the player might have. $+
}
on *:TEXT:!medic:#: {
if ((%floodmedic) || ($($+(%,floodmedic.,$nick),2))) { return }
set -u10 %floodmedic On
set -u30 %floodmedic. $+ $nick On
msg $chan Every night the Medic picks a player who is currently alive to protect or “save”. This player is protected from 1 KP for that night phase (and that night phase only). If the player is hit with 2 KP the player will still die even if the Medic is protecting them. The Medic may not save himself, and unless otherwise state the Medic may save the same person on consecutive nights. $+
}
on *:TEXT:!hypno:#: {
if ((%floodhypno) || ($($+(%,floodhypno.,$nick),2))) { return }
set -u10 %floodhypno On
set -u30 %floodhypno. $+ $nick On
msg $chan The Hypnotist has a one-time use power to use during the night. In order for the power to work both himself and the player the Hypnotist uses it on must be alive at the start of the following day. If the Hypnotists uses his power on you then you become hypnotized and must claim your role at the start of the next day. The first three words out of your mouth must be ‘I am *your role here*’. $+
}
on *:TEXT:!vigi:#: {
if ((%floodvigi) || ($($+(%,floodvigi.,$nick),2))) { return }
set -u10 %floodvigi On
set -u30 %floodvigi. $+ $nick On
msg $chan The Vigilante is given a gun with one bullet for the entire game. The Vigilante may choose to shoot someone during the night phase (and only the night phase). If the Vigilante shoots a player who is medic protected that player will not die and the Vigilante will lose his bullet. If the Vigilante shoots a player who is also shot by the mafia the Vigilante will lose his bullet. $+
}
on *:TEXT:!inno:#: {
if ((%floodinno) || ($($+(%,floodinno.,$nick),2))) { return }
set -u10 %floodinno On
set -u30 %floodinno. $+ $nick On
msg $chan The Innocent Child is a vanilla town confirmed at the very start of the game by mod. They have no power. $+
}
on *:TEXT:!gunsmith:#: {
if ((%floodgunsmith) || ($($+(%,floodgunsmith.,$nick),2))) { return }
set -u10 %floodgunsmith On
set -u30 %floodgunsmith. $+ $nick On
msg $chan The gunsmith is a town sided role that is allowed to give out a gun during the night which the recipient can then shoot only during the day by saying a command such as, "I Shoot X". The guns have a 1 time use. $+
}
on *:TEXT:!rafflesystem:#: {
if ((%floodgunsmith) || ($($+(%,floodgunsmith.,$nick),2))) { return }
set -u10 %floodgunsmith On
set -u30 %floodgunsmith. $+ $nick On
msg $chan We now have a point system for raffles. You earn Donks by being in chat and watching the games. To check how many Donks you have use !donks. When a raffle opens use !buytickets [number of tickets] to buy tickets for the raffle. $+
}
Code 2:
on *:TEXT:!buytickets &:#:{
if (!%raffle) { msg $chan Raffle is currently closed! }
else {
if ($int($2) < 1) { msg $chan Do you really want to buy no Tickets, $nick $+ ..? }
elseif ($int($2) > 1000) { msg $chan Sorry $nick but you can only buy up to 1000 raffle tickets at a time. }
else {
var %i = 0, %ticket = $int($2)
var %topic = $+(#,.,$nick), %user = $readini(Points.ini,%topic,Points), %end = 1 * %ticket, %delete = %user - %end
if (%delete > 0) {
writeini -n $qt(Points.ini) %topic Points %delete
while (%i < %ticket) {
write $qt(Raffle.txt) $nick
inc %i
}
msg $chan $nick you have bought %ticket tickets with %end Donks.
}
}
}
}
on *:TEXT:!raffle &:#:{
if ($nick isop #) {
if (($2 == open) && (!%raffle)) || (($2 == close) && (%raffle)) {
msg $chan RAFFLE IS NOW $replace($upper($2!!),CLOSE,CLOSED)
if ($2 == open) { set %raffle 1 }
else unset %raffle
write -c $qt(Raffle.txt)
}
}
}
on *:TEXT:!roll:#:{
if ($nick isop #) && (%raffle) {
msg $chan RAFFLE IS NOW BEING ROLLED, GOOD LUCK!!
.timerCD 1 3 msg $chan /me $!calc( $!timer(CD).reps + 1 ) $!+ !
.timer 1 4 msg $chan AND THE WINNER IS:
.timer 1 5 msg $chan $read(Raffle.txt, n)
unset %raffle
write -c $qt(Raffle.txt)
}
}
Code 3
alias -l addPoints {
if ($1 !isnum) { echo 2 -st $1 is not a number. It needs to be a number. | halt }
var %topic $+($chan,.,$nick)
var %points $calc($readini(Points.ini,%topic,Points) + $1)
writeini -n Points.ini %topic Points %points
return %points
}
alias -l lookUpPoints {
var %topic $+($chan,.,$nick)
var %points $readini(Points.ini,%topic,Points)
return %points
}
alias doaddpoints {
if ($3 !isnum) { echo 2 -st $3 is not a number. It needs to be a number. | halt }
var %topic $+($1,.,$2)
var %points $calc($readini(Points.ini,%topic,Points) + $3)
writeini -n Points.ini %topic Points %points
echo -a Added points for %topic
}
alias dorempoints {
var %topic $+($1,.,$2)
remini -n Points.ini %topic Points
echo -a Removed points for %topic
}
on *:text:!donks:#:{
if ((%floodpoints) || ($($+(%,floodpoints.,$nick),2))) { return }
set -u10 %floodpoints On
set -u30 %floodpoints. $+ $nick On
msg # $nick has $readini(Points.ini,$+(#,.,$nick),Points) total donks.
}
on $*:text:/!donks (add|remove)/Si:#:{
if ($nick isop #) {
if ($0 < 3) { msg # Insufficient parameters: Use !donks [add|remove] [user] [number] | return }
writeini -n Points.ini $+(#,.,$3) Points $calc($readini(Points.ini,$+(#,.,$3),Points) $iif($2 == add,+,-) $iif($4 isnum,$4,1))
{ msg $chan $3 now has $readini(Points.ini,$+(#,.,$3),Points) total donks. }
}
else { msg $chan This command is only available to moderators. }
}
on *:TEXT:!donktime &:#:{
if ($nick isop #) {
if (($2 == start) && (!%donktime)) || (($2 == stop) && (%donktime)) {
msg $chan DONKTIME IS NOW $replace($upper($2ED!!),CLOSE,CLOSED)
if ($2 == start) { set %donktime 1 }
else unset %donktown
}
}
}
on !*:join:#:{
if (!%donktown) {halt}
else{
$+(.timerpoints.,#,.,$nick) 0 1800 add.pts $+(#,.,$nick)
add.pts $+(#,.,$nick)}
}
on !*:part:#:$+(.timerpoints.,#,.,$nick) off
alias -l add.pts {
writeini -n Points.ini $1 Points $calc($readini(Points.ini,$1,Points) + 1)
}
Thank you in advance for any and all help.

This kind of question doesn't offer any code that we can help you with. You are basically asking us for code without showing us what have you tried so far to acheive it, just what you currently have that doesn't neccessrly related to your request. And for that reason no one as answer or helped you.
I too, was about to move for the next question, but since I wanted to see how were my mSL skills, I decided to give it a go.
Warning:
I over-killed this system in order to sharpen my mSL skills as I said previously.
The code wasn't fully tested.
I'm not gonna guide you how to Debug issues nor integrate it into your system, because I've built it almost Generic and Dynamic as possible, for easy Debug and Integration, so a person with little experience with mSL should have figure how to use this code for his goals.
Code:
;###
;### PointsTimer v1
;### - Granting channel user points by fixed interval
;### Programmer: Orel Eraki
;### Contact: Orel.Eraki#gmail.com
;###
;### Commands: !PointsTimer START|END|STATUS
#PointsTimer on
alias -l PointsTimer.Name return PointsTimer
alias -l PointsTimer.Description return Granting channel user points by fixed interval.
alias -l PointsTimer.Author return Orel Eraki (Orel.Eraki#gmail.com)
alias -l PointsTimer.Version return 1
;### Settings
alias -l PointsTimer.Channel return #TestTest
alias -l PointsTimer.Idle return 20
alias -l PointsTimer.PointsFile return Points.ini
alias -l PointsTimer.Status return $iif(%PointsTimer, $true, $false)
;### Messages
alias -l PointsTimer.MsgStarted return System has been Started.
alias -l PointsTimer.MsgEnded return System has been Ended.
alias -l PointsTimer.MsgAlreadyStarted return System already been started.
alias -l PointsTimer.MsgNotStarted return System didn't started yet.
;### Events
on *:QUIT: .PointsTimer END-FOR-NICK $nick
on me:*:PART:$($PointsTimer.Channel): .PointsTimer END
on me:*:JOIN:$($PointsTimer.Channel): .PointsTimer END
on !*:PART:$($PointsTimer.Channel): .PointsTimer.SetNickTimer $nick OFF
on !*:JOIN:$($PointsTimer.Channel): {
if (!$PointsTimer.Status) {
return
}
PointsTimer START-FOR-NICK $nick
}
on *:NICK: {
if (!$PointsTimer.Status) {
return
}
PointsTimer RENAME $nick $newnick
}
on *:TEXT:!PointsTimer INFO:$($PointsTimer.Channel): {
PointsTimer.Msg # $PointsTimer.Name v $+ $PointsTimer.Version By $PointsTimer.Author
PointsTimer.Msg # $PointsTimer.Description
}
on #*:TEXT:!PointsTimer *:$($PointsTimer.Channel): {
if ($2 == START) {
if ($PointsTimer.Status) {
PointsTimer.Msg # $PointsTimer.MsgAlreadyStarted
return
}
PointsTimer START #
if ($PointsTimer.Status) {
PointsTimer.Msg # $PointsTimer.MsgStarted
}
}
else if ($2 == END) {
if (!$PointsTimer.Status) {
PointsTimer.Msg # $PointsTimer.MsgNotStarted
return
}
PointsTimer END #
if (!$PointsTimer.Status) {
PointsTimer.Msg # $PointsTimer.MsgEnded
}
}
elseif ($2 == STATUS) {
PointsTimer.Msg # System is currently $iif($PointsTimer.Status, ON, OFF)
}
}
;### Commands
alias PointsTimer {
if ($1 == START) {
if ($PointsTimer.Status || $2 !ischan) {
return
}
inc %PointsTimer
PointsTimer.SetNicksTimer $PointsTimer.GetChannelNicks($2)
}
elseif ($1 == END) {
if (!$PointsTimer.Status) {
return
}
unset %PointsTimer
.timerPointsTimer.* off
}
elseif ($1 == START-FOR-NICK) {
if (!$PointsTimer.Status || !$ial($+($2,!*#*))) {
return
}
PointsTimer.SetNickTimer $2
}
elseif ($1 == END-FOR-NICK) {
if (!$PointsTimer.Status) {
return
}
PointsTimer.SetNickTimer $2 OFF
}
elseif ($1 == RENAME) {
.timer 1 0 PointsTimer END-FOR-NICK $2
.timer 1 1 PointsTimer START-FOR-NICK $3
}
else {
PointsTimer.Echo Unknown command $1
}
}
alias -l PointsTimer.Msg msg $1 * PointsTimer: $2-
alias -l PointsTimer.Echo echo $color(info) -agt * PointsTimer: $1-
alias -l PointsTimer.GetChannelNicks {
if ($1 !ischan) {
return
}
var %i = 1, %n = $nick($1, 0)
var %results
while (%i <= %n) {
%results = $addtok(%results, $nick($1, %i), 44)
inc %i
}
return %results
}
alias -l PointsTimer.SetNickTimer $+(.timerPointsTimer.,$1) $iif($2 == OFF, OFF,0 $PointsTimer.Idle Add.PTS $1)
alias -l PointsTimer.SetNicksTimer {
var %results
var %i = 1, %n = $numtok($1, 44)
while (%i <= %n) {
PointsTimer.SetNickTimer $gettok($1, %i, 44)
inc %i
}
}
alias -l Add.PTS writeini -n $PointsTimer.PointsFile $1 Points $calc($readini($PointsTimer.PointsFile, $1, Points) + 1)
#PointsTimer End

Related

Perl DBD::SQLite::db do failed: syntax error

I am developing a Perl script to query the PasteBin API using threads and DBD::SQLite to store information for later.
Upon running my script I get the following error:
DBD::SQLite::db do failed: near "day": syntax error at getpaste.pl line 113.
Thread 3 terminated abnormally: DBD::SQLite::db do failed: near "day": syntax error at getpaste.pl line 113.
Using my code to debug here's what I see in thread 3:
enum _Days {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
class HeadingItem implements ListItem {
String _weekday;
final int time;
final DocumentReference reference;
set day(String weekday) {
var value = _Days.values[int.parse(weekday) - 1].toString();
var idx = value.indexOf(".") + 1;
var result = value.substring(idx, value.length);
_weekday = result;
}
String get day {
return _weekday;
}
HeadingItem.fromMap(Map<String, dynamic> map, {this.reference})
: assert(map['day'] != null),
assert(map['time'] != null),
day = map['day'], // 'day' isn't a field in the enclosing class <--- this is the error that im stuck on...
time = map['time'];
HeadingItem.fromSnapshot(DocumentSnapshot snapshot) : this.fromMap(snapshot.data, reference: snapshot.reference);
}
If I had to make an educated guess it bombs out at String get day {
Here's a chunk of my code where this is relevant:
sub threadCheckKey {
my ($url, $key) = #_;
my $fullURL = $url.$key;
my #flaggedRegex = ();
my $date = strftime "%D", localtime;
my #data = ();
my $thread = threads->create(sub {
my $dbConnection = openDB();
open(GET_DATA, "curl -s " . $fullURL . " -k 2>&1 |") or die("$!");
open(WRITE_FILE, ">", $key . ".txt") or die("$!");
while(my $line = <GET_DATA>) {
print WRITE_FILE $line;
foreach my $regex(#regexs) {
if($line =~ m/$regex/) {
if(!($regex ~~ #flaggedRegex)) {
push(#flaggedRegex, $regex);
}
}
}
}
close(WRITE_FILE);
close(GET_DATA);
open(READ_FILE, $key . ".txt") or die("$!");
while(my $line = <READ_FILE>) {
push(#data, $line);
}
close(READ_FILE);
my $updateRow = qq(UPDATE $tables[0] set data = \'#data\', date = \'$date\', regex = \'#flaggedRegex\' where pastekey = \'$key\');
my $executeRowUpdate = $dbConnection->do($updateRow);
if($executeRowUpdate < 0) {
print $DBI::errstr;
}
Line 113 in this case is my $executeRowUpdate = $dbConnection->do($updateRow); Knowing Perl it's really complaining about my UPDATE statement just above it.
Where am I going wrong with this? I am a novice when it comes to interacting with anything sql related.
You need to log the $updateRow that is generated and then look at that and see what is wrong with it. Without that nobody knows.
The other issues ikegami notes in a comment above probably deserve new questions focused on their individual aspects. As you've discovered https://codereview.stackexchange.com/ is not for code with errors. But given all of the injection issues it might be time to try https://security.stackexchange.com/
If you fix those problems maybe your error will disappear too. Or not, but it is worth trying.

Why does PHP7 extension memory-leaking?

ANSWER: because php 7.0.15 and php 7.0.6 if different in the way they working with refcounter: in php 7.0.15 zval_dtor() decrement the refcounter, in php 7.0.6 is does not.
I call the following test_test function in loop, 100000 iterations and see memory usage increasing.
for( $i = 0; $i < 100000; ++ $i ) {
test_test();
if ( 0 == $i % 10000 ) {
echo memory_get_usage(), PHP_EOL;
}
}
The extension code:
PHP_FUNCTION(test_test)
{
zval zzz;
array_init(&zzz);
if (Z_REFCOUNTED(zzz)) {
if(Z_REFCOUNT(zzz) ) {
// --- we do reach this line of code
Z_DELREF(zzz); // (1)
}
if( 0 == Z_REFCOUNT(zzz) ) { // (2)
// --- we do reach this line of code
zval_dtor(&zzz);
}
}
}
When I remove (1) and (2) - no leank anymore. But these changes dont affect "zval_dtor()" call - it called in both scenarios.
(The more wild thing is that 2 different php7 machines behave differently: the problem exists only for one of them. I believe I have the same php7 version on both).

Better way of `chowning` unknown uid/gid of files `rsync` (including an --exclude-from file) would consider as source files

I am trying to change unknown uid's and gid's on files that my rsync command would consider as source files before I execute my rsync command.
My rsync command includes an exclude file.
The reason that I need to do this is explained in my question here.
I have tried this find command:
find /cygdrive/f -uid 4294967295 -exec chown 544. '{}' + -o -gid 4294967295 -exec chown .197121 '{}' +
BUT, it does not handle the exclude file. By that I mean, the above find searches all of f drive for files matching the unknown uid/gid, then chowns them. My rsync looks at drive f and copies all of it except the files in exclude file. I do not want to chown any Win7 side files that rsync does not copy.
For instance, one of the ways Win7 protects some of its hidden/sys files is by setting their uid and gid to 4294967295 (eg c:\pagefil.sys and c:\hiberfil.sys). I have excluded both these files in the rsync exclude file AND I want to leave their Win7 side uid/gid alone. The find command would chown them.
I have also tried to parse an ls listing, which may work, but very slowly. Since I am only dealing with Win7 files I think an ls would be suitable for parsing.
Is there a better way to solve my problem before I work with the ls listing (or parse the find output) before chowning script?
Another, more precise way, but slow and requiring a more difficult script for me, would be to parse an rsync --dry-run ... listing to figure out which items need chowning.
EDIT 2015-12-13: Unfortunately the rsync --dry-run ... does not generate the warnings about impossible to set UID/GID 's during the dry run so that method is out.
BUT, I have found the source code for rsync and it looks to me that it would be pretty easy to modify it so that the UID/GID 's could be set to the UID and GID of the process running the rsync command if the bad UID/GID 's are found during a session.
Can anyone give me a summary of what tools I need to compile the rsync source code on a Win7 computer?
Here is rsync.c from the source code (search for 'impossible to set'):
int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
const char *fnamecmp, int flags)
{
int updated = 0;
stat_x sx2;
int change_uid, change_gid;
mode_t new_mode = file->mode;
int inherit;
if (!sxp) {
if (dry_run)
return 1;
if (link_stat(fname, &sx2.st, 0) < 0) {
rsyserr(FERROR_XFER, errno, "stat %s failed",
full_fname(fname));
return 0;
}
init_stat_x(&sx2);
sxp = &sx2;
inherit = !preserve_perms;
} else
inherit = !preserve_perms && file->flags & FLAG_DIR_CREATED;
if (inherit && S_ISDIR(new_mode) && sxp->st.st_mode & S_ISGID) {
/* We just created this directory and its setgid
* bit is on, so make sure it stays on. */
new_mode |= S_ISGID;
}
if (daemon_chmod_modes && !S_ISLNK(new_mode))
new_mode = tweak_mode(new_mode, daemon_chmod_modes);
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode) && !ACL_READY(*sxp))
get_acl(fname, sxp);
#endif
change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
&& sxp->st.st_gid != (gid_t)F_GROUP(file);
#ifndef CAN_CHOWN_SYMLINK
if (S_ISLNK(sxp->st.st_mode)) {
;
} else
#endif
if (change_uid || change_gid) {
if (DEBUG_GTE(OWN, 1)) {
if (change_uid) {
rprintf(FINFO,
"set uid of %s from %u to %u\n",
fname, (unsigned)sxp->st.st_uid, F_OWNER(file));
}
if (change_gid) {
rprintf(FINFO,
"set gid of %s from %u to %u\n",
fname, (unsigned)sxp->st.st_gid, F_GROUP(file));
}
}
if (am_root >= 0) {
uid_t uid = change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid;
gid_t gid = change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid;
if (do_lchown(fname, uid, gid) != 0) {
/* We shouldn't have attempted to change uid
* or gid unless have the privilege. */
rsyserr(FERROR_XFER, errno, "%s %s failed",
change_uid ? "chown" : "chgrp",
full_fname(fname));
goto cleanup;
}
if (uid == (uid_t)-1 && sxp->st.st_uid != (uid_t)-1)
rprintf(FERROR_XFER, "uid 4294967295 (-1) is impossible to set on %s\n", full_fname(fname));
if (gid == (gid_t)-1 && sxp->st.st_gid != (gid_t)-1)
rprintf(FERROR_XFER, "gid 4294967295 (-1) is impossible to set on %s\n", full_fname(fname));
/* A lchown had been done, so we need to re-stat if
* the destination had the setuid or setgid bits set
* (due to the side effect of the chown call). */
if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
link_stat(fname, &sxp->st,
keep_dirlinks && S_ISDIR(sxp->st.st_mode));
}
}
updated = 1;
}
#ifdef SUPPORT_XATTRS
if (am_root < 0)
set_stat_xattr(fname, file, new_mode);
if (preserve_xattrs && fnamecmp)
set_xattr(fname, file, fnamecmp, sxp);
#endif
if (!preserve_times
|| (!(preserve_times & PRESERVE_DIR_TIMES) && S_ISDIR(sxp->st.st_mode))
|| (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(sxp->st.st_mode)))
flags |= ATTRS_SKIP_MTIME;
if (!(flags & ATTRS_SKIP_MTIME)
&& cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
int ret = set_modtime(fname, file->modtime, F_MOD_NSEC(file), sxp->st.st_mode);
if (ret < 0) {
rsyserr(FERROR_XFER, errno, "failed to set times on %s",
full_fname(fname));
goto cleanup;
}
if (ret == 0) /* ret == 1 if symlink could not be set */
updated = 1;
else
file->flags |= FLAG_TIME_FAILED;
}
#ifdef SUPPORT_ACLS
/* It's OK to call set_acl() now, even for a dir, as the generator
* will enable owner-writability using chmod, if necessary.
*
* If set_acl() changes permission bits in the process of setting
* an access ACL, it changes sxp->st.st_mode so we know whether we
* need to chmod(). */
if (preserve_acls && !S_ISLNK(new_mode)) {
if (set_acl(fname, file, sxp, new_mode) > 0)
updated = 1;
}
#endif
#ifdef HAVE_CHMOD
if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
if (ret < 0) {
rsyserr(FERROR_XFER, errno,
"failed to set permissions on %s",
full_fname(fname));
goto cleanup;
}
if (ret == 0) /* ret == 1 if symlink could not be set */
updated = 1;
}
#endif
if (INFO_GTE(NAME, 2) && flags & ATTRS_REPORT) {
if (updated)
rprintf(FCLIENT, "%s\n", fname);
else
rprintf(FCLIENT, "%s is uptodate\n", fname);
}
cleanup:
if (sxp == &sx2)
free_stat_x(&sx2);
return updated;
}
I have found two practical solutions that fix the base issue:
If both source and destination environments use rsync 3.1.0 or newer, there are new options available. In that case I could just add these options to my rsync command:
--usermap=4294967295:544 --groupmap=4294967295:197121
Thank-you Wayne Davison for directing me to these new options!
If you are stuck with an older rsync on your destination (as I am with my WD MyCloud), you can modify the rsync source code with cygwin as follows.
Make sure your cygwin is installed with gcc gcc-core perl make and quilt
Download the latest rsync source tar file at rsync site
I unzipped that to a folder in my ~ directory.
I downloaded Eclipse to use as an IDE but you could just modify the files with NotePad++ as follows:
In the main.c file I added an information line that you see every time you run rsync so you know you are using your personal rsync version. I am sure that there is also an appropriate way to set the version number to one of my own but I will let someone comment on how to do that. (all my lines end with /* dalek */):
starttime = time(NULL);
our_uid = MY_UID();
our_gid = MY_GID();
rprintf(FINFO,"rsync 3.1.1 with edits started by uid: %u gid: %u\n", our_uid, our_gid ); /* dalek */
Then, in flist.c, add my /* dalek */ lines as follows:
if (!preserve_uid || ((uid_t)F_OWNER(file) == uid && *lastname))
xflags |= XMIT_SAME_UID;
else {
uid = F_OWNER(file);
if (uid==4294967295){ /* dalek */
if (do_lchown(fname, our_uid, F_GROUP(file)) != 0) { /* dalek */
rprintf(FINFO, "COULD NOT CHANGE 4294967295 UID to %u on %s\n",our_uid,fname); /* dalek */
}else{ /* dalek */
uid=our_uid; /* dalek */
} /* dalek */
} /* dalek */
if (!numeric_ids) {
user_name = add_uid(uid);
if (inc_recurse && user_name)
xflags |= XMIT_USER_NAME_FOLLOWS;
}
}
if (!preserve_gid || ((gid_t)F_GROUP(file) == gid && *lastname))
xflags |= XMIT_SAME_GID;
else {
gid = F_GROUP(file);
if (gid==4294967295){ /* dalek */
if (do_lchown(fname, F_OWNER(file), our_gid) != 0) { /* dalek */
rprintf(FINFO, "COULD NOT CHANGE 4294967295 GID to %u on %s\n",our_gid,fname); /* dalek */
}else{ /* dalek */
gid=our_gid; /* dalek */
} /* dalek */
} /* dalek */
if (!numeric_ids) {
group_name = add_gid(gid);
if (inc_recurse && group_name)
xflags |= XMIT_GROUP_NAME_FOLLOWS;
}
}
Then in your recently added rsync source directory run ./configure.sh then run make then run make install. That is it! You should have a new rsync.exe file in .../usr/local/bin which will be run whenever you use rsync from now on since cygwin puts .../usr/local/bin ahead of .../bin in the PATH it uses. The original rsync is still in .../bin. To use the original, just move your modified rsync.exe out of .../usr/local/bin.
If you have spare space on your Win7 computer, try this:
rsync the files you want into a temporary location on the same computer. Because it is the same computer the UID/GID should set successfully.
In the copy do your find/chown script to set the UID/GID for all the files.
rsync the copy back to the original location (carefully!) The contents of the files should not have changed, so the only changes rsync should make will be to set the UID/GID.
Make sure you use -aHAX to do the copies, and do a dry-run before overwriting anything!

Setuid to Perl script

I am using a Perl script which deletes the data from mqueue folder for sendmail.
When I setuid to that Perl script and try to run it from user it throws this message:
Insecure dependency in chdir while running setuid at /file/find
How to solve it and succesfully run the script with root priveleges?
!/usr/bin/perl
use strict;
my $qtool = "/usr/local/bin/qtool.pl";
my $mqueue_directory = "/var/spool/mqueue";
my $messages_removed = 0;
use File::Find;
# Recursively find all files and directories in $mqueue_directory
find(\&wanted, $mqueue_directory);
sub wanted {
# Is this a qf* file?
if ( /^qf(\w{14})/ ) {
my $qf_file = $_;
my $queue_id = $1;
my $deferred = 0;
my $from_postmaster = 0;
my $delivery_failure = 0;
my $double_bounce = 0;
open (QF_FILE, $_);
while(<QF_FILE>) {
$deferred = 1 if ( /^MDeferred/ );
$from_postmaster = 1 if ( /^S<>$/ );
$delivery_failure = 1 if \
( /^H\?\?Subject: DELIVERY FAILURE: (User|Recipient)/ );
if ( $deferred && $from_postmaster && $delivery_failure ) {
$double_bounce = 1;
last;
}
}
close (QF_FILE);
if ($double_bounce) {
print "Removing $queue_id...\n";
system "$qtool", "-d", $qf_file;
$messages_removed++;
}
}
}
print "\n$messages_removed total \"double bounce\" message(s) removed from ";
print "mail queue.\n";
"Insecure dependency" is a Taint thing: http://perldoc.perl.org/perlsec.html.
Taint is being enforced because you have run the script setuid. You need to specify untaint as an %option key to File::Find:
http://metacpan.org/pod/File::Find
my %options = (
wanted => \&wanted,
untaint => 1
);
find(\%options, $mqueue_directory);
You should also have a look at the untaint_pattern in the POD for File::Find.
You should build a program wrapper. On almost any unix system, a script can never get root privileges via the SetUID bit. You can find some usefull example here http://www.tuxation.com/setuid-on-shell-scripts.html

Insecure ENV variable at setuid

i am using this code its working fine when i am running it from root but when i set root priviledges to it throws up an error saying "insecure $ENV{PATH} at line system "perl $qtool -d $mqueue_directory*$queue_id";"
my script is in path /scripts/deferred.pl
#!/usr/bin/perl
use strict;
my $qtool = "/usr/local/bin/qtool.pl";
my $mqueue_directory = "/var/spool/mqueue";
my $messages_removed = 0;
my #rf_id;
my #date;
my $temp
my #write_array;
my $to;
my $from;
use Untaint;
use File::Find;
# Recursively find all files and directories in $mqueue_directory
use Untaint;
find(\&wanted, $mqueue_directory);
sub wanted {
# Is this a qf* file?
if ( /^qf(\w{14})/ ) {
my $qf_file = $_;
my $queue_id = $1;
my $deferred = 0;
my $from_postmaster = 0;
my $delivery_failure = 0;
my $junk_mail = 0;
open (QF_FILE, $_);
while(<QF_FILE>) {
$deferred = 1 if ( /^MTemporarily/ | /^Mhost map: lookup/ | /^MUser unknown/ );
$delivery_failure = 1 if \
( /^H\?\?Subject: DELIVERY FAILURE: (User|Recipient)/ );
if ( $deferred && $from_postmaster && $delivery_failure ) {
$junk_mail = 1;
}
$temp=$qf_file.':';
if($junk_mail){
while(<QF_FILE>){
chomp;
if(/rRFC822;/){
$temp.=subdtr($_,9)
}
if(/H?D?Date:/){
$temp.=':'.substr($_,10);
push #write_array, $temp."\n";
}
}
}
}
close (QF_FILE);
my $subqueue_id = substr($queue_id,9);
if ($junk_mail) {
print "Removing $queue_id...\n";
system "perl $qtool -d $mqueue_directory*$queue_id";
$messages_removed++;
}
}
}
open (MYFILE,">/scripts/mail.txt");
print MYFILE "#write_array";
close (MYFILE);
$to='yagya#mydomain.in';
$from='system#mydomain.in';
$subject='deleted mails';
open(MAIL,"|/usr/sbin/sendmail -t");
print MAIL "To: $to\n";
print MAIL "From: $from\n";
print MAIL "Subject: $subject\n\n";
print MAIL "#write_array\n";
close(MAIL);
print "\n$messages_removed total \"double bounce\" message(s) removed from ";
print "mail queue.\n";
Setuid programs automatically run in taint mode. It's all explained in perlsec, including the text in your error message. Often, if you paste the error message into a search engine, you'll quickly find out what to do about it. You might also see Insecure $ENV{ENV} while running with -T switch.

Resources