summaryrefslogtreecommitdiffstats
path: root/main.c
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2009-04-08 01:08:37 +0200
committerGravatar Nikias Bassen2009-04-08 01:08:37 +0200
commit466ff3c456383456630ce9d67abae991566c158e (patch)
tree5700fbc01e1fcde9bb55a5dfe97e281deb2471ab /main.c
parent0080c074ba46c0a4eae6561f40c6b4c749ac0ab1 (diff)
downloadusbmuxd-466ff3c456383456630ce9d67abae991566c158e.tar.gz
usbmuxd-466ff3c456383456630ce9d67abae991566c158e.tar.bz2
Implemented lockfile stuff to prevent multiple running instances.
Implemented daemonizing, use -f to run in foreground. Implemented logging to syslog (or to std{out,err} when running in foreground). Modified the udev rules file (removed --pidfile etc.).
Diffstat (limited to 'main.c')
-rw-r--r--main.c213
1 files changed, 188 insertions, 25 deletions
diff --git a/main.c b/main.c
index 832ff7f..0af0735 100644
--- a/main.c
+++ b/main.c
@@ -24,6 +24,10 @@
24#include <errno.h> 24#include <errno.h>
25#include <stdlib.h> 25#include <stdlib.h>
26#include <string.h> 26#include <string.h>
27#include <getopt.h>
28#include <stdarg.h>
29#include <syslog.h>
30#include <fcntl.h>
27#include <sys/socket.h> 31#include <sys/socket.h>
28#include <sys/un.h> 32#include <sys/un.h>
29#include <sys/stat.h> 33#include <sys/stat.h>
@@ -43,9 +47,12 @@
43#define DEFAULT_CHILDREN_CAPACITY 10 47#define DEFAULT_CHILDREN_CAPACITY 10
44#define DEBUG_LEVEL 0 48#define DEBUG_LEVEL 0
45 49
50#define LOCKFILE "/var/run/usbmuxd.lock"
51
46static int quit_flag = 0; 52static int quit_flag = 0;
47static int fsock = -1; 53static int fsock = -1;
48static int verbose = DEBUG_LEVEL; 54static int verbose = DEBUG_LEVEL;
55static int foreground = 0;
49 56
50struct device_use_info { 57struct device_use_info {
51 uint32_t device_id; 58 uint32_t device_id;
@@ -764,7 +771,43 @@ leave:
764 */ 771 */
765static int daemonize() 772static int daemonize()
766{ 773{
767 // TODO still to be implemented, also logging is missing! 774 pid_t pid;
775 pid_t sid;
776
777 // already a daemon
778 if (getppid() == 1) return 0;
779
780 pid = fork();
781 if (pid < 0) {
782 exit(EXIT_FAILURE);
783 }
784
785 if (pid > 0) {
786 // exit parent process
787 exit(EXIT_SUCCESS);
788 }
789
790 // At this point we are executing as the child process
791
792 // Change the file mode mask
793 umask(0);
794
795 // Create a new SID for the child process
796 sid = setsid();
797 if (sid < 0) {
798 return -1;
799 }
800
801 // Change the current working directory.
802 if ((chdir("/")) < 0) {
803 return -2;
804 }
805
806 // Redirect standard files to /dev/null
807 freopen("/dev/null", "r", stdin);
808 freopen("/dev/null", "w", stdout);
809 freopen("/dev/null", "w", stderr);
810
768 return 0; 811 return 0;
769} 812}
770 813
@@ -779,12 +822,85 @@ static void clean_exit(int sig)
779 quit_flag = 1; 822 quit_flag = 1;
780} 823}
781 824
825static void logmsg(int prio, char *format, ...)
826{
827 va_list args;
828 va_start(args, format);
829
830 if (!foreground) {
831 // daemon. log using syslog.
832 vsyslog(prio, format, args);
833 } else {
834 // running in foreground. log to stdout/stderr.
835 char msgbuf[256];
836 FILE *lfp = stdout;
837 switch(prio) {
838 case LOG_EMERG:
839 case LOG_ALERT:
840 case LOG_CRIT:
841 case LOG_ERR:
842 case LOG_WARNING:
843 lfp = stderr;
844 break;
845 default:
846 lfp = stdout;
847 }
848 strcpy(msgbuf, "usbmuxd: ");
849 vsnprintf(msgbuf+9, 244, format, args);
850 strcat(msgbuf, "\n");
851 fputs(msgbuf, lfp);
852 }
853
854 va_end(args);
855}
856
857static void usage()
858{
859 printf("usage: usbmuxd [options]\n");
860 printf("\t-h|--help print this message.\n");
861 printf("\t-v|--verbose be verbose\n");
862 printf("\t-f|--foreground do not daemonize\n");
863 printf("\n");
864}
865
866static void parse_opts(int argc, char **argv)
867{
868 static struct option longopts[] = {
869 { "help", 0, NULL, 'h' },
870 { "foreground", 0, NULL, 'f' },
871 { "verbose", 0, NULL, 'v' },
872 { NULL, 0, NULL, 0}
873 };
874 int c;
875
876 while (1) {
877 c = getopt_long(argc, argv, "hfv", longopts, (int *) 0);
878 if (c == -1) {
879 break;
880 }
881
882 switch (c) {
883 case 'h':
884 usage();
885 exit(0);
886 case 'f':
887 foreground = 1;
888 break;
889 case 'v':
890 sock_stuff_set_verbose(++verbose);
891 break;
892 default:
893 usage();
894 exit(2);
895 }
896 }
897}
898
782/** 899/**
783 * main function. Initializes all stuff and then loops waiting in accept. 900 * main function. Initializes all stuff and then loops waiting in accept.
784 */ 901 */
785int main(int argc, char **argv) 902int main(int argc, char **argv)
786{ 903{
787 int foreground = 1;
788 struct sockaddr_un c_addr; 904 struct sockaddr_un c_addr;
789 socklen_t len = sizeof(struct sockaddr_un); 905 socklen_t len = sizeof(struct sockaddr_un);
790 struct client_data *cdata = NULL; 906 struct client_data *cdata = NULL;
@@ -793,20 +909,47 @@ int main(int argc, char **argv)
793 int i; 909 int i;
794 int result = 0; 910 int result = 0;
795 int cnt = 0; 911 int cnt = 0;
912 FILE *lfd = NULL;
913 struct flock lock;
796 914
797 for (i = 1; i < argc; i++) { 915 parse_opts(argc, argv);
798 if (argv[i] != NULL && (!strncmp("-v", argv[i], 2) || !strncmp("--verbose", argv[i], 10))) { 916
799 sock_stuff_set_verbose(++verbose); 917 argc -= optind;
800 } 918 argv += optind;
919
920 if (!foreground) {
921 openlog("usbmuxd", LOG_PID, 0);
801 } 922 }
802 923
803 if (verbose >= 2) fprintf(stderr, "usbmuxd: starting\n"); 924 if (verbose >= 2) logmsg(LOG_NOTICE, "starting");
804 925
805 // TODO: Parameter checking. 926 // signal(SIGHUP, reload_conf); // none yet
927 signal(SIGINT, clean_exit);
928 signal(SIGQUIT, clean_exit);
929 signal(SIGTERM, clean_exit);
930 signal(SIGPIPE, SIG_IGN);
931
932 // check for other running instance
933 lfd = fopen(LOCKFILE, "r");
934 if (lfd) {
935 lock.l_type = 0;
936 lock.l_whence = SEEK_SET;
937 lock.l_start = 0;
938 lock.l_len = 0;
939 fcntl(fileno(lfd), F_GETLK, &lock);
940 fclose(lfd);
941 if (lock.l_type != F_UNLCK) {
942 logmsg(LOG_NOTICE, "another instance is already running. exiting.");
943 return -1;
944 }
945 }
806 946
807 fsock = create_unix_socket(USBMUXD_SOCKET_FILE); 947 fsock = create_unix_socket(USBMUXD_SOCKET_FILE);
808 if (fsock < 0) { 948 if (fsock < 0) {
809 if (verbose >= 1) fprintf(stderr, "Could not create socket, exiting\n"); 949 logmsg(LOG_ERR, "Could not create socket, exiting");
950 if (!foreground) {
951 closelog();
952 }
810 return -1; 953 return -1;
811 } 954 }
812 955
@@ -814,26 +957,36 @@ int main(int argc, char **argv)
814 957
815 if (!foreground) { 958 if (!foreground) {
816 if (daemonize() < 0) { 959 if (daemonize() < 0) {
960 fprintf(stderr, "usbmuxd: FATAL: Could not daemonize!\n");
961 syslog(LOG_ERR, "FATAL: Could not daemonize!");
962 closelog();
817 exit(EXIT_FAILURE); 963 exit(EXIT_FAILURE);
818 } 964 }
819 } 965 }
820 966
821 // signal(SIGHUP, reload_conf); // none yet 967 // now open the lockfile and place the lock
822 signal(SIGINT, clean_exit); 968 lfd = fopen(LOCKFILE, "w");
823 signal(SIGQUIT, clean_exit); 969 if (lfd) {
824 signal(SIGTERM, clean_exit); 970 lock.l_type = F_WRLCK;
825 signal(SIGPIPE, SIG_IGN); 971 lock.l_whence = SEEK_SET;
972 lock.l_start = 0;
973 lock.l_len = 0;
974 fcntl(fileno(lfd), F_SETLK, &lock);
975 }
826 976
827 // Reserve space for 10 clients which should be enough. If not, the 977 // Reserve space for 10 clients which should be enough. If not, the
828 // buffer gets enlarged later. 978 // buffer gets enlarged later.
829 children = (struct client_data**)malloc(sizeof(struct client_data*) * children_capacity); 979 children = (struct client_data**)malloc(sizeof(struct client_data*) * children_capacity);
830 if (!children) { 980 if (!children) {
831 if (verbose >= 2) fprintf(stderr, "usbmuxd: Out of memory when allocating memory for child threads. Terminating.\n"); 981 logmsg(LOG_ERR, "Out of memory when allocating memory for child threads. Terminating.");
982 if (!foreground) {
983 closelog();
984 }
832 exit(EXIT_FAILURE); 985 exit(EXIT_FAILURE);
833 } 986 }
834 memset(children, 0, sizeof(struct client_data*) * children_capacity); 987 memset(children, 0, sizeof(struct client_data*) * children_capacity);
835 988
836 if (verbose >= 2) fprintf(stderr, "usbmuxd: waiting for connection\n"); 989 if (verbose >= 2) logmsg(LOG_NOTICE, "waiting for connection");
837 while (!quit_flag) { 990 while (!quit_flag) {
838 // Check the file descriptor before accepting a connection. 991 // Check the file descriptor before accepting a connection.
839 // If no connection attempt is made, just repeat... 992 // If no connection attempt is made, just repeat...
@@ -845,7 +998,7 @@ int main(int argc, char **argv)
845 if (children[i]) { 998 if (children[i]) {
846 if (children[i]->dead != 0) { 999 if (children[i]->dead != 0) {
847 pthread_join(children[i]->thread, NULL); 1000 pthread_join(children[i]->thread, NULL);
848 if (verbose >= 3) fprintf(stderr, "usbmuxd: reclaimed client thread (fd=%d)\n", children[i]->socket); 1001 if (verbose >= 3) logmsg(LOG_NOTICE, "reclaimed client thread (fd=%d)", children[i]->socket);
849 free(children[i]); 1002 free(children[i]);
850 children[i] = NULL; 1003 children[i] = NULL;
851 cnt++; 1004 cnt++;
@@ -864,7 +1017,7 @@ int main(int argc, char **argv)
864 } 1017 }
865 continue; 1018 continue;
866 } else { 1019 } else {
867 if (verbose >= 3) fprintf(stderr, "usbmuxd: select error: %s\n", strerror(errno)); 1020 if (verbose >= 3) logmsg(LOG_ERR, "usbmuxd: select error: %s", strerror(errno));
868 continue; 1021 continue;
869 } 1022 }
870 } 1023 }
@@ -873,7 +1026,7 @@ int main(int argc, char **argv)
873 memset(cdata, 0, sizeof(struct client_data)); 1026 memset(cdata, 0, sizeof(struct client_data));
874 if (!cdata) { 1027 if (!cdata) {
875 quit_flag = 1; 1028 quit_flag = 1;
876 if (verbose >= 1) fprintf(stderr, "usbmuxd: Error: Out of memory! Terminating.\n"); 1029 logmsg(LOG_ERR, "Error: Out of memory! Terminating.");
877 break; 1030 break;
878 } 1031 }
879 1032
@@ -883,12 +1036,12 @@ int main(int argc, char **argv)
883 if (errno == EINTR) { 1036 if (errno == EINTR) {
884 continue; 1037 continue;
885 } else { 1038 } else {
886 if (verbose >= 3) fprintf(stderr, "usbmuxd: Error in accept: %s\n", strerror(errno)); 1039 if (verbose >= 3) logmsg(LOG_ERR, "Error in accept: %s", strerror(errno));
887 continue; 1040 continue;
888 } 1041 }
889 } 1042 }
890 1043
891 if (verbose >= 1) fprintf(stderr, "usbmuxd: new client connected (fd=%d)\n", cdata->socket); 1044 if (verbose >= 1) logmsg(LOG_NOTICE, "new client connected (fd=%d)", cdata->socket);
892 1045
893 // create client thread: 1046 // create client thread:
894 if (pthread_create(&cdata->thread, NULL, usbmuxd_client_init_thread, cdata) == 0) { 1047 if (pthread_create(&cdata->thread, NULL, usbmuxd_client_init_thread, cdata) == 0) {
@@ -900,19 +1053,19 @@ int main(int argc, char **argv)
900 children_capacity++; 1053 children_capacity++;
901 children = realloc(children, sizeof(struct client_data*) * children_capacity); 1054 children = realloc(children, sizeof(struct client_data*) * children_capacity);
902 if (!children) { 1055 if (!children) {
903 if (verbose >= 1) fprintf(stderr, "usbmuxd: Out of memory when enlarging child thread buffer\n"); 1056 logmsg(LOG_ERR, "Out of memory when enlarging child thread buffer");
904 } 1057 }
905 } 1058 }
906 children[i] = cdata; 1059 children[i] = cdata;
907 } else { 1060 } else {
908 if (verbose >= 3) fprintf(stderr, "usbmuxd: Failed to create client_init_thread.\n"); 1061 logmsg(LOG_ERR, "Failed to create client_init_thread.");
909 close(cdata->socket); 1062 close(cdata->socket);
910 free(cdata); 1063 free(cdata);
911 cdata = NULL; 1064 cdata = NULL;
912 } 1065 }
913 } 1066 }
914 1067
915 if (verbose >= 3) fprintf(stderr, "usbmuxd: terminating\n"); 1068 if (verbose >= 3) logmsg(LOG_NOTICE, "terminating");
916 1069
917 // preparing for shutdown: wait for child threads to terminate (if any) 1070 // preparing for shutdown: wait for child threads to terminate (if any)
918 if (verbose >= 2) fprintf(stderr, "usbmuxd: waiting for child threads to terminate...\n"); 1071 if (verbose >= 2) fprintf(stderr, "usbmuxd: waiting for child threads to terminate...\n");
@@ -934,7 +1087,17 @@ int main(int argc, char **argv)
934 1087
935 unlink(USBMUXD_SOCKET_FILE); 1088 unlink(USBMUXD_SOCKET_FILE);
936 1089
937 if (verbose >= 1) fprintf(stderr, "usbmuxd: terminated\n"); 1090 // unlock lock file and close it.
1091 if (lfd) {
1092 lock.l_type = F_UNLCK;
1093 fcntl(fileno(lfd), F_SETLK, lock);
1094 fclose(lfd);
1095 }
1096
1097 if (verbose >= 1) logmsg(LOG_NOTICE, "usbmuxd: terminated");
1098 if (!foreground) {
1099 closelog();
1100 }
938 1101
939 return 0; 1102 return 0;
940} 1103}