| | 151 | /** |
| | 152 | * Prints the @a error to stderr (by means of gLog), and if the user is running |
| | 153 | * X, tries to show a dialog with the error. |
| | 154 | */ |
| | 155 | static void DisplayFatalError(const char* error) |
| | 156 | { |
| | 157 | gLog.Error(error); |
| | 158 | |
| | 159 | // Try to show the error if we're running X |
| | 160 | if (getenv("DISPLAY") != NULL) |
| | 161 | { |
| | 162 | pid_t child = fork(); |
| | 163 | if (child == 0) |
| | 164 | { |
| | 165 | // execlp never returns (except on error). |
| | 166 | execlp("kdialog", "kdialog", "--error", error, NULL); |
| | 167 | execlp("Xdialog", "Xdialog", "--title", "Error", "--msgbox", error, "0", "0", NULL); |
| | 168 | execlp("xmessage", "xmessage", "-center", error, NULL); |
| | 169 | |
| | 170 | exit(EXIT_FAILURE); |
| | 171 | } |
| | 172 | else if (child != -1) |
| | 173 | { |
| | 174 | int status; |
| | 175 | waitpid(child, &status, 0); |
| | 176 | } |
| | 177 | } |
| | 178 | } |
| 312 | | FILE *fs = fopen(szConf, "r"); |
| 313 | | if (fs != NULL) |
| 314 | | { |
| 315 | | fgets(szKey, 32, fs); |
| 316 | | pid_t pid = atol(szKey); |
| 317 | | if (pid != 0) |
| 318 | | { |
| 319 | | if (kill(pid, 0) == -1) { |
| 320 | | gLog.Warn(tr("%sLicq: Ignoring stale lockfile (pid %d)\n"), L_WARNxSTR, pid); |
| | 342 | |
| | 343 | // Never close pidFile! |
| | 344 | int pidFile = open(szConf, O_RDWR | O_CREAT); |
| | 345 | if (pidFile < 0) |
| | 346 | { |
| | 347 | // We couldn't open (or create) the file for writing. |
| | 348 | // If the file doesn't exists we continue without lockfile protection. |
| | 349 | // If it does exist, we bail out. |
| | 350 | struct stat buf; |
| | 351 | if (stat(szConf, &buf) < 0 && errno == ENOENT) |
| | 352 | { |
| | 353 | gLog.Warn(tr("%sLicq: %s cannot be opened for writing.\n" |
| | 354 | "%s skipping lockfile protection.\n"), |
| | 355 | L_WARNxSTR, szConf, L_BLANKxSTR); |
| | 356 | } |
| | 357 | else |
| | 358 | { |
| | 359 | const size_t ERR_SIZE = 511; |
| | 360 | char error[ERR_SIZE + 1]; |
| | 361 | |
| | 362 | // Try to read the pid of running Licq instance. |
| | 363 | FILE* fs = fopen(szConf, "r"); |
| | 364 | if (fs != NULL) |
| | 365 | { |
| | 366 | fgets(szKey, 32, fs); |
| | 367 | pid_t pid = atol(szKey); |
| | 368 | |
| | 369 | snprintf(error, ERR_SIZE, |
| | 370 | tr("%sLicq: Already running at pid %d.\n" |
| | 371 | "%s Kill process or remove %s.\n"), |
| | 372 | L_ERRORxSTR, pid, L_BLANKxSTR, szConf); |
| | 373 | fclose(fs); |
| 327 | | tr("%sLicq: Already running at pid %d.\n" |
| 328 | | "%s Kill process or remove %s.\n"), |
| 329 | | L_ERRORxSTR, pid, L_BLANKxSTR, szConf); |
| 330 | | error[ERR_SIZE] = '\0'; |
| 331 | | |
| 332 | | gLog.Error(error); |
| 333 | | m_bDeletePID = false; |
| 334 | | |
| 335 | | // Try to show the error if we're running X |
| 336 | | if (getenv("DISPLAY") != NULL) |
| 337 | | { |
| 338 | | pid_t child = fork(); |
| 339 | | if (child == 0) |
| 340 | | { |
| 341 | | // execlp never returns (except on error). |
| 342 | | execlp("kdialog", "kdialog", "--error", error, NULL); |
| 343 | | execlp("Xdialog", "Xdialog", "--title", "Error", "--msgbox", error, "0", "0", NULL); |
| 344 | | execlp("xmessage", "xmessage", "-center", error, NULL); |
| 345 | | |
| 346 | | exit(EXIT_FAILURE); |
| 347 | | } |
| 348 | | else if (child != -1) |
| 349 | | { |
| 350 | | int status; |
| 351 | | waitpid(child, &status, 0); |
| 352 | | } |
| 353 | | } |
| 354 | | |
| 355 | | return false; |
| | 378 | tr("%sLicq: Unabled to determine pid of running Licq instance.\n"), |
| | 379 | L_ERRORxSTR); |
| 368 | | gLog.Warn(tr("%sLicq: %s cannot be opened for writing.\n" |
| 369 | | "%s skipping lockfile protection.\n"), |
| 370 | | L_WARNxSTR, szConf, L_BLANKxSTR); |
| | 389 | { |
| | 390 | struct flock lock; |
| | 391 | lock.l_type = F_WRLCK; // Write lock is exclusive lock |
| | 392 | lock.l_whence = SEEK_SET; |
| | 393 | lock.l_start = 0; |
| | 394 | lock.l_len = 0; // Lock file through to the end of file |
| | 395 | |
| | 396 | if (fcntl(pidFile, F_SETLK, &lock) != 0) |
| | 397 | { |
| | 398 | // Failed to get the lock => Licq is already running |
| | 399 | const size_t ERR_SIZE = 511; |
| | 400 | char error[ERR_SIZE + 1]; |
| | 401 | |
| | 402 | if (fcntl(pidFile, F_GETLK, &lock) != 0) |
| | 403 | { |
| | 404 | snprintf(error, ERR_SIZE, |
| | 405 | tr("%sLicq: Unabled to determine pid of running Licq instance.\n"), |
| | 406 | L_ERRORxSTR); |
| | 407 | } |
| | 408 | else |
| | 409 | { |
| | 410 | snprintf(error, ERR_SIZE, |
| | 411 | tr("%sLicq: Already running at pid %d.\n"), |
| | 412 | L_ERRORxSTR, lock.l_pid); |
| | 413 | } |
| | 414 | |
| | 415 | error[ERR_SIZE] = '\0'; |
| | 416 | DisplayFatalError(error); |
| | 417 | |
| | 418 | return false; |
| | 419 | } |
| | 420 | else |
| | 421 | { |
| | 422 | // Save our pid in the file |
| | 423 | ftruncate(pidFile, 0); |
| | 424 | int size = snprintf(szKey, 32, "%d\n", getpid()); |
| | 425 | write(pidFile, szKey, (size > 32 ? 32 : size)); |
| | 426 | } |
| | 427 | } |