な?argvの0番ってプログラム名だけでなくディレクトリの部分も伝わってるってことなん??? #linux
@Common_Lisper Cのmainのargv[]がもらう内容はexec(3)のargv引数のコピーで、exec(3)には他に実行ファイルを指定する引数があるので、argv[0]には何でも渡せちゃった気がします。シェルから起動したときにはコマンドラインのファイル名かフルパスか、ユーザーがタイプした方が入っていることが多くて、内部的にマルチプロセスにするようなプログラムだとps(1)で見せたい情報を書くのかも。そのうちじっけんすゆ!
@Common_Lisper じっけんしました!! psはオプションによって表示するコマンド名が違うんですねえ
$ cat main.c
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void main(int argc, char *argv[])
{
pid_t pid;
char *arg;
arg = argv[1] ? argv[1] : argv[0];
printf("argv[0]: %s\n", argv[0]);
pid = fork();
if (pid) {
/* parent */
printf("a child with argv[0]: %s is sleeping for 60 sec at pid: %d\n", arg, pid);
} else {
/* child */
execl("/usr/bin/sleep", arg, "60", NULL);
}
}
$ gcc main.c && { ./a.out ねてる; `pwd`/a.out ねてるってば; }
argv[0]: ./a.out
a child with argv[0]: ねてる is sleeping for 60 sec at pid: 21227
argv[0]: /tmp/a.out
a child with argv[0]: ねてるってば is sleeping for 60 sec at pid: 21230
$ ps
PID TTY TIME CMD
:
21227 pts/2 00:00:00 sleep
21230 pts/2 00:00:00 sleep
:
$ ps x
PID TTY STAT TIME COMMAND
:
21227 pts/2 S 0:00 ねてる 60
21230 pts/2 S 0:00 ねてるってば 60
:
いつからargcが1のときにargv[1]がNULLだと思っていた…
@zundan @Common_Lisper 横からすみません。手っ取り早くargv[0]に代入するテクがあったような、太古の記憶があります。もうできないのかも。
@tadd @Common_Lisper 今手近にUbuntu 20.04.5しかなかったのですが、ちょっと検索してprctl(2)を使えそうなことがわかりました。これはPOSIXではないみたい。
$ cat main.c
#include <unistd.h>
#include <sys/prctl.h>
void main(void)
{
prctl(PR_SET_NAME, "寝てるよ");
sleep(60);
}
$ gcc main.c
$ ./a.out &
$ ps
PID TTY TIME CMD
141793 pts/0 00:00:00 bash
141991 pts/0 00:00:00 寝てるよ
141992 pts/0 00:00:00 ps
argv[0]に代入するのは何か壊しそうですよねw
$ cat main.c
#include <unistd.h>
#include <string.h>
void main(int argc, char *argv[])
{
strcpy(argv[0], "寝てるよ");
sleep(60);
}
$ gcc main.c
$ ./a.out &
$ ps
PID TTY TIME CMD
141793 pts/0 00:00:00 bash
142011 pts/0 00:00:00 a.out
142012 pts/0 00:00:00 ps
って効かなかったw
@zundan なるほど、prctlは初めて知りました。結局はpthread..._np相当とあるので、まぁたぶん、ポータブルじゃなさそうですね〜。
@zundan
ちゃんとしたAPI(?)の別ものとして、setprognameとかsetproctitleというのがあるらしい、とは頭の片隅にあったのですが、やはりPOSIXではないですね。
BSD由来らしく、Linuxだとlibbsd経由です。Macだとねいてぃぶかも。
https://man.openbsd.org/setproctitle
OpenBSDだと場合によっては最後、sysctlで、もちろんポータブルではなく。
https://github.com/openbsd/src/blob/master/lib/libc/gen/setproctitle.c
Linuxだとargv上書き相当?
https://github.com/openbsd/src/blob/master/lib/libc/gen/setproctitle.c
を早めに仕込むっぽいです。
https://github.com/freedesktop/libbsd/blob/master/src/setproctitle_ctor.c#L46-L52
@tadd setprogname(3)、Venturaで通ったんですが何が変わったかわからない感じです…(なおgccはclang
$ gcc --version
Apple clang version 14.0.0 (clang-1400.0.29.202)
Target: arm64-apple-darwin22.3.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
$ cat main.c
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
setprogname("sleeping");
sleep(100);
return 0;
}
$ gcc main.c
$ ./a.out&
[1] 1540
$ ps x | grep 1540
1540 s001 SN 0:00.00 ./a.out
1544 s001 S+ 0:00.00 grep 1540
@zundan あ、それだとproctiteの方がよさそうです。