【脱獄アプリ開発】第9回SyslogをON/OFFできるFlipSwitchトグルの作成方法

   


Jailbreak Tweakを開発するときなどにデバイスの情報をログとして出力する「syslogd to var/log/syslog」があります。

過去にSBSettingsのトグルとしてもありましたが、今回はそれと同様の動作をするFlipSwitchトグルの作成方法を紹介します。

syslogd to var/log/syslogの使い方


名前の通り/var/log/syslogにログファイルをリアルタイムで生成します。

OpenSSHとBigBoss Recommended Toolsをインストールしていれば、MacのターミナルなどからSSHでiPhoneに接続しリアルタイムでログを確認できます。

#SSHでiPhoneに接続
ssh [email protected]

#tailコマンドでログを確認
tail -f /var/log/syslog

#NSLogなどで一部の名称のみ確認したい場合(例.hoge)
tail -f /var/log/syslog | grep hoge

Tweak作成時などで上手いこと行かない場合、ソースファイルにNSLog()を記述して調べてみると解決の糸口に繋がるかと思います。

TheosにFlipSwitchのテンプレートを入れる


Link:https://github.com/a3tweaks/Flipswitch

NIC Templateの中にある「iphone_flipswitch_switch.nic.tar」を、Macの"/opt/theos/templates/iphone"ディレクトリに入れます。そうすると、Theosのパッケージを作成する項目にFlipSwitchが追加されます。

Theosの構築などについては過去記事を参照ください。

【脱獄アプリ開発】第7回theosのインストールから簡単なTweakの作成までのガイドライン | Will feel Tips

【脱獄アプリ開発】第8回armv6からarm64(iPhone 3Gから5s)に対応したTweakの作成 | Will feel Tips

Syslog Toggleに必要な動作


1.syslogdのデーモンをON/OFFする

launchctlコマンドで"/System/Library/LaunchDaemons/com.apple.syslogd.plist"をunload/loadしてあげることで可能となります。

ただし、FlipSwitchではSBSettingsのようにroot権限で動作することが出来ないため、Theosでいう"tool"を使ったバイナリを別に作成します。以下は、main.mmに記述していきます。

#import <Foundation/NSTask.h>

NSTask *task = [[NSTask alloc] init];
[task setLaunchPath: @"/bin/launchctl"];

//unload
NSArray *unload = [NSArray arrayWithObjects: @"unload", @"/System/Library/LaunchDaemons/com.apple.syslogd.plist", nil];
[task setArguments:unload];
[task launch];

//load
NSArray *load = [NSArray arrayWithObjects: @"load", @"/System/Library/LaunchDaemons/com.apple.syslogd.plist", nil];
[task setArguments:load];
[task launch];

このようにNSTaskを利用して実行することが出来ます。

2."/etc/syslog.conf"ファイルを編集する

/var/log/syslogに出力するONの時は、"*.* /var/log/syslog"
OFFの時は、"#*.* /var/log/syslog"先頭をコメントアウトしています。

static BOOL syslogEnabled;

NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:filePath];
NSData *data = [fileHandle readDataToEndOfFile];
NSString *str = [[NSString alloc]initWithData:data
                                             encoding:NSUTF8StringEncoding];
syslogEnabled = [str hasPrefix:@"*.* /var/log/syslog"];
[fileHandle closeFile];

hasPrefix:@"*.* /var/log/syslog"で先頭の文字に#がない場合、syslogEnabledの値がYESになります。

これを利用してファイルを編集します。

static NSString *filePath = @"/etc/syslog.conf";

//OFFにするときの文字列
NSString *str1 = @"#*.* /var/log/syslog\n";

//ONにするときの文字列
NSString *str2 = @"*.* /var/log/syslog\n";

NSFileManager *manager = [NSFileManager defaultManager];

//一度"/etc/syslog.conf"を削除
if ([manager removeItemAtPath:filePath error:nil]) {

    //syslog.confを新規作成
    [manager createFileAtPath:filePath contents:nil attributes:nil];
    
    if (syslogEnabled) {
        //syslogがONの時OFFにする
        [str1 writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
        
        [task setArguments:unload];
        [task launch];
        
        [task setArguments:load];
        [task launch];
    } else {
        //OFFの時ONにする
        [str2 writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
        
        [task setArguments:load];
        [task launch];
    }
}

以上のような方法でバイナリを作成します。

通常toolで作成した場合、"/usr/bin"ディレクトリに入りますが、FlipSwitchのバンドルに入れて見た目をスッキリさせます。名前を「syslogsw」としてFlipSwitch側を「SyslogToggle.bundle」とします。

TOOL_NAME = syslogsw
syslogsw_FILES = main.mm
syslogsw_INSTALL_PATH = /Library/Switches/SyslogToggle.bundle

こうすると「SyslogToggle.bundle」の中に「syslogsw」が入ります。

また、root権限で実行させるようにするためパーミッションを「4755」にします。

before-package::
sudo chmod 4755 $(THEOS_STAGING_DIR)/Library/Switches/SyslogToggle.bundle/syslogsw

これでdebパッケージにする前にパーミッションを変更します。

3.FlipSwitchでのON/OFF

ソースはSwitch.xファイルを見てコンパイルしますが、Xcodeで編集した場合にシンタックスハイライトされないためシンボリックリンクを作って編集すると見やすくなります。

mv Switch.x Switch.mm; ln -s Switch.mm Switch.x

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "FSSwitchDataSource.h"
#import "FSSwitchPanel.h"

static NSString *logPath = @"/var/log/syslog";
static NSString *filePath = @"/etc/syslog.conf";
static BOOL syslogEnabled;

@interface SyslogToggleSwitch : NSObject <FSSwitchDataSource>
@end

@implementation SyslogToggleSwitch

- (id)init
{
if ((self = [super init])) {
        NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:filePath];
        NSData *data = [fileHandle readDataToEndOfFile];
        NSString *str = [[NSString alloc]initWithData:data
                                             encoding:NSUTF8StringEncoding];
        syslogEnabled = [str hasPrefix:@"*.* /var/log/syslog"];
        [fileHandle closeFile];
}
return self;
}

- (FSSwitchState)stateForSwitchIdentifier:(NSString *)switchIdentifier
{
return syslogEnabled;
}

- (void)applyState:(FSSwitchState)newState forSwitchIdentifier:(NSString *)switchIdentifier
{
if (newState == FSSwitchStateIndeterminate)
return;
    
    syslogEnabled = newState;
    
    system("/Library/Switches/SyslogToggle.bundle/syslogsw");
}

メインは、"syslogsw"を実行させることになります。

4.スイッチ長押し時にログファイルサイズを表示/削除させる

//スイッチ長押しで実行する処理
- (void)applyAlternateActionForSwitchIdentifier:(NSString *)switchIdentifier
{
    //syslog(logPath)のファイルサイズを取得
    NSFileManager *fm = [NSFileManager defaultManager];
    NSDictionary *attribute = [fm attributesOfItemAtPath:logPath error:nil];
    NSNumber *fileSize = [attribute objectForKey:NSFileSize];
    float num = [fileSize floatValue];
    //KBに変換
    num /= 1028;
    //floatをNSStringに変換し、@"%.0f KB",roundf(num)で小数点を消し四捨五入
    NSString *logSize = [[NSString alloc] initWithFormat:@"%.0f KB",roundf(num)];

    //アラートを表示させる
    UIAlertView *alert =
    [[UIAlertView alloc] initWithTitle:@"Logfile Size\nLocation: /var/log/syslog"
                               message:logSize
                              delegate:self
                     cancelButtonTitle:@"Dismiss"
                     otherButtonTitles:@"Clear File",nil];
    [alert show];
    [alert release];
    
}

-(void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 0) {//Dismiss
    } else if (buttonIndex == 1) {//Clear Fileを押した時
        ///var/mobile以下はFlipSwitchからアクセス出来るので空ファイルを作成
        system("touch /var/mobile/Library/Caches/syslogclear");

        //syslogを削除した場合、再度ONにする必要があるためOFFにする
        system("/Library/Switches/SyslogToggle.bundle/syslogsw");
        syslogEnabled = NO;
    }
}
@end

static NSString *clearCache = @"/var/mobile/Library/Caches/syslogclear";
static NSString *logPath = @"/var/log/syslog";

//syslogclearファイルが合った場合、OFFにする記述を追加
NSString *str1 = @"#*.* /var/log/syslog\n";

NSFileManager *manager = [NSFileManager defaultManager];

if ([manager removeItemAtPath:clearCache error:nil]) {
    //syslog削除
    [manager removeItemAtPath:logPath error:nil];

    //syslogをOFFにする
    [str1 writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
    
    [task setArguments:unload];
    [task launch];
    
    [task setArguments:load];
    [task launch];
}

5.初回起動時に動作しない問題を修正

#!/bin/sh

/Library/Switches/SyslogToggle.bundle/syslogsw

exit 0

インストール後に一度"syslogsw"を実行することで回避します。

まとめ


ずらずらとコードを書きましたが、断片的で分かりにくいかと思います。GitHubにソースを上げておいたので参考にしてください。

Link:https://github.com/ichitaso/Syslog-Toggle-Flipswitch

ichitasoリポにも「Syslog Toggle(Flipswitch)」という名前で入れておきました。Cydiaの設定がHacker以上で表示されるようになっています。

昨夜はWWDC 2014でiOS 8や新しい言語「Swift」が発表されましたね!脱獄関連の動きも気になるところですが、とりあえず今できることをやろうということで紹介しました。

それでは!!

 

この記事が気に入ったら
いいね!しよう

最新情報をお届けします

Twitter でWillFeelTipsをフォローしよう!


  関連記事

【脱獄アプリ開発】第11回新しいtheosのインストールと簡単なTweakの作成方法

今回は、以前紹介したtheosの構築方法が古いものになってしまったので、新しくな ...

【脱獄アプリ開発】第4回 XcodeとiOSOpenDevをインストールしよう!

はい。やめようかと思ったけど、楽しみにしてくれてる方がいらっしゃるとのことで、脱 ...

【脱獄アプリ開発】第3回 Google App Engineを使ったCydiaリポジトリの作成方法

さて!連載3回目です。今回は、自分で作ったdebパッケージをCydia Repo ...

【脱獄アプリ開発】第2回 Cydia Debパッケージを作成しよう!

前回は仮想マシンに「Ubuntu」をインストールしました。 今回は、実際にdeb ...

【脱獄アプリ開発】第5回 Cydia 有料Tweakの提出方法 BigBoss編

今回は、自分で開発した脱獄アプリをCydiaの本家であるBigBossへ提出する ...

 - iOS development